update patches
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
diff --git a/node_modules/expo-image-picker/android/src/main/java/expo/modules/imagepicker/exporters/RawImageExporter.kt b/node_modules/expo-image-picker/android/src/main/java/expo/modules/imagepicker/exporters/RawImageExporter.kt
|
||||
index f339e5f..fa35e82 100644
|
||||
--- a/node_modules/expo-image-picker/android/src/main/java/expo/modules/imagepicker/exporters/RawImageExporter.kt
|
||||
+++ b/node_modules/expo-image-picker/android/src/main/java/expo/modules/imagepicker/exporters/RawImageExporter.kt
|
||||
@@ -16,7 +16,12 @@ class RawImageExporter : ImageExporter {
|
||||
copyFile(source, output, contentResolver)
|
||||
val exifInterface = ExifInterface(output.absolutePath)
|
||||
val imageRotation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0)
|
||||
- val isRotatedLandscape = (imageRotation == ExifInterface.ORIENTATION_ROTATE_90 || imageRotation == ExifInterface.ORIENTATION_ROTATE_270)
|
||||
+ val isRotatedLandscape = (
|
||||
+ imageRotation == ExifInterface.ORIENTATION_ROTATE_90 ||
|
||||
+ imageRotation == ExifInterface.ORIENTATION_ROTATE_270 ||
|
||||
+ imageRotation == ExifInterface.ORIENTATION_TRANSPOSE ||
|
||||
+ imageRotation == ExifInterface.ORIENTATION_TRANSVERSE
|
||||
+ )
|
||||
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
|
||||
|
||||
BitmapFactory.decodeFile(output.absolutePath, options)
|
||||
@@ -1,5 +0,0 @@
|
||||
## expo-modules-core Patch
|
||||
|
||||
This patch fixes crashes seen in some Android clients when using intents to open the app. See https://github.com/expo/expo/pull/29513.
|
||||
|
||||
Do not remove this patch until that PR lands in Expo and is released.
|
||||
@@ -1,26 +0,0 @@
|
||||
diff --git a/node_modules/expo-modules-core/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java b/node_modules/expo-modules-core/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java
|
||||
index bb74e80..0aa0202 100644
|
||||
--- a/node_modules/expo-modules-core/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java
|
||||
+++ b/node_modules/expo-modules-core/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java
|
||||
@@ -90,8 +90,8 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
|
||||
mModuleRegistry.ensureIsInitialized();
|
||||
|
||||
KotlinInteropModuleRegistry kotlinModuleRegistry = getKotlinInteropModuleRegistry();
|
||||
- kotlinModuleRegistry.emitOnCreate();
|
||||
kotlinModuleRegistry.installJSIInterop();
|
||||
+ kotlinModuleRegistry.emitOnCreate();
|
||||
|
||||
Map<String, Object> constants = new HashMap<>(3);
|
||||
constants.put(MODULES_CONSTANTS_KEY, new HashMap<>());
|
||||
diff --git a/node_modules/expo-modules-core/build/uuid/uuid.js b/node_modules/expo-modules-core/build/uuid/uuid.js
|
||||
index 109d3fe..c7fce9e 100644
|
||||
--- a/node_modules/expo-modules-core/build/uuid/uuid.js
|
||||
+++ b/node_modules/expo-modules-core/build/uuid/uuid.js
|
||||
@@ -1,5 +1,7 @@
|
||||
import bytesToUuid from './lib/bytesToUuid';
|
||||
import { Uuidv5Namespace } from './uuid.types';
|
||||
+import { ensureNativeModulesAreInstalled } from '../ensureNativeModulesAreInstalled';
|
||||
+ensureNativeModulesAreInstalled();
|
||||
const nativeUuidv4 = globalThis?.expo?.uuidv4;
|
||||
const nativeUuidv5 = globalThis?.expo?.uuidv5;
|
||||
function uuidv4() {
|
||||
@@ -1,216 +0,0 @@
|
||||
diff --git a/node_modules/expo-notifications/android/build.gradle b/node_modules/expo-notifications/android/build.gradle
|
||||
index b863077..8b5209e 100644
|
||||
--- a/node_modules/expo-notifications/android/build.gradle
|
||||
+++ b/node_modules/expo-notifications/android/build.gradle
|
||||
@@ -32,6 +32,7 @@ dependencies {
|
||||
api 'com.google.firebase:firebase-messaging:22.0.0'
|
||||
|
||||
api 'me.leolin:ShortcutBadger:1.1.22@aar'
|
||||
+ implementation project(':expo-background-notification-handler')
|
||||
|
||||
if (project.findProject(':expo-modules-test-core')) {
|
||||
testImplementation project(':expo-modules-test-core')
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/badge/BadgeHelper.kt b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/badge/BadgeHelper.kt
|
||||
index 63a46c5..f911834 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/badge/BadgeHelper.kt
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/badge/BadgeHelper.kt
|
||||
@@ -1,5 +1,6 @@
|
||||
package expo.modules.notifications.badge
|
||||
|
||||
+import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import me.leolin.shortcutbadger.ShortcutBadgeException
|
||||
@@ -12,7 +13,12 @@ object BadgeHelper {
|
||||
|
||||
fun setBadgeCount(context: Context, badgeCount: Int): Boolean {
|
||||
return try {
|
||||
- ShortcutBadger.applyCountOrThrow(context.applicationContext, badgeCount)
|
||||
+ if (badgeCount == 0) {
|
||||
+ val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
+ notificationManager.cancelAll()
|
||||
+ } else {
|
||||
+ ShortcutBadger.applyCountOrThrow(context.applicationContext, badgeCount)
|
||||
+ }
|
||||
BadgeHelper.badgeCount = badgeCount
|
||||
true
|
||||
} catch (e: ShortcutBadgeException) {
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/JSONNotificationContentBuilder.java b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/JSONNotificationContentBuilder.java
|
||||
index 0af7fe0..8f2c8d8 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/JSONNotificationContentBuilder.java
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/JSONNotificationContentBuilder.java
|
||||
@@ -14,6 +14,7 @@ import expo.modules.notifications.notifications.enums.NotificationPriority;
|
||||
import expo.modules.notifications.notifications.model.NotificationContent;
|
||||
|
||||
public class JSONNotificationContentBuilder extends NotificationContent.Builder {
|
||||
+ private static final String CHANNEL_ID_KEY = "channelId";
|
||||
private static final String TITLE_KEY = "title";
|
||||
private static final String TEXT_KEY = "message";
|
||||
private static final String SUBTITLE_KEY = "subtitle";
|
||||
@@ -36,6 +37,7 @@ public class JSONNotificationContentBuilder extends NotificationContent.Builder
|
||||
|
||||
public NotificationContent.Builder setPayload(JSONObject payload) {
|
||||
this.setTitle(getTitle(payload))
|
||||
+ .setChannelId(getChannelId(payload))
|
||||
.setSubtitle(getSubtitle(payload))
|
||||
.setText(getText(payload))
|
||||
.setBody(getBody(payload))
|
||||
@@ -60,6 +62,14 @@ public class JSONNotificationContentBuilder extends NotificationContent.Builder
|
||||
return this;
|
||||
}
|
||||
|
||||
+ protected String getChannelId(JSONObject payload) {
|
||||
+ try {
|
||||
+ return payload.getString(CHANNEL_ID_KEY);
|
||||
+ } catch (JSONException e) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
protected String getTitle(JSONObject payload) {
|
||||
try {
|
||||
return payload.getString(TITLE_KEY);
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationContent.java b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationContent.java
|
||||
index f1fed19..012757b 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationContent.java
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationContent.java
|
||||
@@ -20,6 +20,7 @@ import expo.modules.notifications.notifications.enums.NotificationPriority;
|
||||
* should be created using {@link NotificationContent.Builder}.
|
||||
*/
|
||||
public class NotificationContent implements Parcelable, Serializable {
|
||||
+ private String mChannelId;
|
||||
private String mTitle;
|
||||
private String mText;
|
||||
private String mSubtitle;
|
||||
@@ -50,6 +51,11 @@ public class NotificationContent implements Parcelable, Serializable {
|
||||
}
|
||||
};
|
||||
|
||||
+ @Nullable
|
||||
+ public String getChannelId() {
|
||||
+ return mChannelId;
|
||||
+ }
|
||||
+
|
||||
@Nullable
|
||||
public String getTitle() {
|
||||
return mTitle;
|
||||
@@ -121,6 +127,7 @@ public class NotificationContent implements Parcelable, Serializable {
|
||||
}
|
||||
|
||||
protected NotificationContent(Parcel in) {
|
||||
+ mChannelId = in.readString();
|
||||
mTitle = in.readString();
|
||||
mText = in.readString();
|
||||
mSubtitle = in.readString();
|
||||
@@ -146,6 +153,7 @@ public class NotificationContent implements Parcelable, Serializable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
+ dest.writeString(mChannelId);
|
||||
dest.writeString(mTitle);
|
||||
dest.writeString(mText);
|
||||
dest.writeString(mSubtitle);
|
||||
@@ -166,6 +174,7 @@ public class NotificationContent implements Parcelable, Serializable {
|
||||
private static final long serialVersionUID = 397666843266836802L;
|
||||
|
||||
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
|
||||
+ out.writeObject(mChannelId);
|
||||
out.writeObject(mTitle);
|
||||
out.writeObject(mText);
|
||||
out.writeObject(mSubtitle);
|
||||
@@ -190,6 +199,7 @@ public class NotificationContent implements Parcelable, Serializable {
|
||||
}
|
||||
|
||||
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
+ mChannelId = (String) in.readObject();
|
||||
mTitle = (String) in.readObject();
|
||||
mText = (String) in.readObject();
|
||||
mSubtitle = (String) in.readObject();
|
||||
@@ -240,6 +250,7 @@ public class NotificationContent implements Parcelable, Serializable {
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
+ private String mChannelId;
|
||||
private String mTitle;
|
||||
private String mText;
|
||||
private String mSubtitle;
|
||||
@@ -260,6 +271,11 @@ public class NotificationContent implements Parcelable, Serializable {
|
||||
useDefaultVibrationPattern();
|
||||
}
|
||||
|
||||
+ public Builder setChannelId(String channelId) {
|
||||
+ mChannelId = channelId;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
public Builder setTitle(String title) {
|
||||
mTitle = title;
|
||||
return this;
|
||||
@@ -336,6 +352,7 @@ public class NotificationContent implements Parcelable, Serializable {
|
||||
|
||||
public NotificationContent build() {
|
||||
NotificationContent content = new NotificationContent();
|
||||
+ content.mChannelId = mChannelId;
|
||||
content.mTitle = mTitle;
|
||||
content.mSubtitle = mSubtitle;
|
||||
content.mText = mText;
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.java b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.java
|
||||
index 6bd9928..ee93d70 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.java
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.java
|
||||
@@ -48,6 +48,10 @@ public class ExpoNotificationBuilder extends ChannelAwareNotificationBuilder {
|
||||
|
||||
NotificationContent content = getNotificationContent();
|
||||
|
||||
+ if (content.getChannelId() != null) {
|
||||
+ builder.setChannelId(content.getChannelId());
|
||||
+ }
|
||||
+
|
||||
builder.setAutoCancel(content.isAutoDismiss());
|
||||
builder.setOngoing(content.isSticky());
|
||||
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt
|
||||
index 55b3a8d..1b99d5b 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt
|
||||
@@ -12,11 +12,14 @@ import expo.modules.notifications.notifications.model.triggers.FirebaseNotificat
|
||||
import expo.modules.notifications.service.NotificationsService
|
||||
import expo.modules.notifications.service.interfaces.FirebaseMessagingDelegate
|
||||
import expo.modules.notifications.tokens.interfaces.FirebaseTokenListener
|
||||
+import expo.modules.backgroundnotificationhandler.BackgroundNotificationHandler
|
||||
+import expo.modules.backgroundnotificationhandler.BackgroundNotificationHandlerInterface
|
||||
+import expo.modules.backgroundnotificationhandler.ExpoBackgroundNotificationHandlerModule
|
||||
import org.json.JSONObject
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
|
||||
-open class FirebaseMessagingDelegate(protected val context: Context) : FirebaseMessagingDelegate {
|
||||
+open class FirebaseMessagingDelegate(protected val context: Context) : FirebaseMessagingDelegate, BackgroundNotificationHandlerInterface {
|
||||
companion object {
|
||||
// Unfortunately we cannot save state between instances of a service other way
|
||||
// than by static properties. Fortunately, using weak references we can
|
||||
@@ -89,12 +92,21 @@ open class FirebaseMessagingDelegate(protected val context: Context) : FirebaseM
|
||||
fun getBackgroundTasks() = sBackgroundTaskConsumerReferences.values.mapNotNull { it.get() }
|
||||
|
||||
override fun onMessageReceived(remoteMessage: RemoteMessage) {
|
||||
- NotificationsService.receive(context, createNotification(remoteMessage))
|
||||
- getBackgroundTasks().forEach {
|
||||
- it.scheduleJob(RemoteMessageSerializer.toBundle(remoteMessage))
|
||||
+ if (!ExpoBackgroundNotificationHandlerModule.isForegrounded) {
|
||||
+ BackgroundNotificationHandler(context, this).handleMessage(remoteMessage)
|
||||
+ return
|
||||
+ } else {
|
||||
+ showMessage(remoteMessage)
|
||||
+ getBackgroundTasks().forEach {
|
||||
+ it.scheduleJob(RemoteMessageSerializer.toBundle(remoteMessage))
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
+ override fun showMessage(remoteMessage: RemoteMessage) {
|
||||
+ NotificationsService.receive(context, createNotification(remoteMessage))
|
||||
+ }
|
||||
+
|
||||
protected fun createNotification(remoteMessage: RemoteMessage): Notification {
|
||||
val identifier = getNotificationIdentifier(remoteMessage)
|
||||
val payload = JSONObject(remoteMessage.data as Map<*, *>)
|
||||
@@ -0,0 +1,169 @@
|
||||
diff --git a/node_modules/expo-notifications/android/build.gradle b/node_modules/expo-notifications/android/build.gradle
|
||||
index b8dcff8..701196c 100644
|
||||
--- a/node_modules/expo-notifications/android/build.gradle
|
||||
+++ b/node_modules/expo-notifications/android/build.gradle
|
||||
@@ -46,6 +46,7 @@ dependencies {
|
||||
implementation 'com.google.firebase:firebase-messaging:24.0.1'
|
||||
|
||||
implementation 'me.leolin:ShortcutBadger:1.1.22@aar'
|
||||
+ implementation project(':expo-background-notification-handler')
|
||||
|
||||
if (project.findProject(':expo-modules-test-core')) {
|
||||
testImplementation project(':expo-modules-test-core')
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/interfaces/INotificationContent.kt b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/interfaces/INotificationContent.kt
|
||||
index 7b99e6c..45a450d 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/interfaces/INotificationContent.kt
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/interfaces/INotificationContent.kt
|
||||
@@ -15,6 +15,7 @@ import org.json.JSONObject
|
||||
* This interface exists to provide a common API for both classes.
|
||||
* */
|
||||
interface INotificationContent : Parcelable {
|
||||
+ val channelId: String?
|
||||
val title: String?
|
||||
val text: String?
|
||||
val subText: String?
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationContent.java b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationContent.java
|
||||
index 06dfe5a..e2b0559 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationContent.java
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationContent.java
|
||||
@@ -34,6 +34,7 @@ import kotlin.coroutines.Continuation;
|
||||
* Refactoring this class may require a migration strategy for the data stored in SharedPreferences.
|
||||
*/
|
||||
public class NotificationContent implements Parcelable, Serializable, INotificationContent {
|
||||
+ private String mChannelId;
|
||||
private String mTitle;
|
||||
private String mText;
|
||||
private String mSubtitle;
|
||||
@@ -64,6 +65,11 @@ public class NotificationContent implements Parcelable, Serializable, INotificat
|
||||
}
|
||||
};
|
||||
|
||||
+ @Nullable
|
||||
+ public String getChannelId() {
|
||||
+ return mChannelId;
|
||||
+ }
|
||||
+
|
||||
@Nullable
|
||||
public String getTitle() {
|
||||
return mTitle;
|
||||
@@ -157,6 +163,7 @@ public class NotificationContent implements Parcelable, Serializable, INotificat
|
||||
}
|
||||
|
||||
protected NotificationContent(Parcel in) {
|
||||
+ mChannelId = in.readString();
|
||||
mTitle = in.readString();
|
||||
mText = in.readString();
|
||||
mSubtitle = in.readString();
|
||||
@@ -182,6 +189,7 @@ public class NotificationContent implements Parcelable, Serializable, INotificat
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
+ dest.writeString(mChannelId);
|
||||
dest.writeString(mTitle);
|
||||
dest.writeString(mText);
|
||||
dest.writeString(mSubtitle);
|
||||
@@ -202,6 +210,7 @@ public class NotificationContent implements Parcelable, Serializable, INotificat
|
||||
private static final long serialVersionUID = 397666843266836802L;
|
||||
|
||||
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
|
||||
+ out.writeObject(mChannelId);
|
||||
out.writeObject(mTitle);
|
||||
out.writeObject(mText);
|
||||
out.writeObject(mSubtitle);
|
||||
@@ -284,6 +293,11 @@ public class NotificationContent implements Parcelable, Serializable, INotificat
|
||||
useDefaultVibrationPattern();
|
||||
}
|
||||
|
||||
+ public Builder setChannelId(String channelId) {
|
||||
+ content.mChannelId = channelId;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
public Builder setTitle(String title) {
|
||||
content.mTitle = title;
|
||||
return this;
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationData.kt b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationData.kt
|
||||
index 39b5aad..e50797d 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationData.kt
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/NotificationData.kt
|
||||
@@ -11,6 +11,9 @@ import org.json.JSONObject
|
||||
* */
|
||||
@JvmInline
|
||||
value class NotificationData(private val data: Map<String, String>) {
|
||||
+ val channelId: String?
|
||||
+ get() = data["channelId"]
|
||||
+
|
||||
val title: String?
|
||||
get() = data["title"]
|
||||
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/RemoteNotificationContent.kt b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/RemoteNotificationContent.kt
|
||||
index d2cc6cf..6a48ff2 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/RemoteNotificationContent.kt
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/model/RemoteNotificationContent.kt
|
||||
@@ -31,6 +31,8 @@ class RemoteNotificationContent(private val remoteMessage: RemoteMessage) : INot
|
||||
return remoteMessage.notification?.imageUrl != null
|
||||
}
|
||||
|
||||
+ override val channelId = remoteMessage.notification?.channelId ?: notificationData.channelId
|
||||
+
|
||||
override val title = remoteMessage.notification?.title ?: notificationData.title
|
||||
|
||||
override val text = remoteMessage.notification?.body ?: notificationData.message
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.kt b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.kt
|
||||
index 0b0435e..eb47ddb 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.kt
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.kt
|
||||
@@ -99,6 +99,9 @@ open class ExpoNotificationBuilder(
|
||||
builder.setOngoing(content.isSticky)
|
||||
|
||||
// see "Notification anatomy" https://developer.android.com/develop/ui/views/notifications#Templates
|
||||
+ content.channelId?.let {
|
||||
+ builder.setChannelId(it)
|
||||
+ }
|
||||
builder.setContentTitle(content.title)
|
||||
builder.setContentText(content.text)
|
||||
builder.setSubText(content.subText)
|
||||
diff --git a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt
|
||||
index 9f22441..5f92f80 100644
|
||||
--- a/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt
|
||||
+++ b/node_modules/expo-notifications/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt
|
||||
@@ -2,6 +2,9 @@ package expo.modules.notifications.service.delegates
|
||||
|
||||
import android.content.Context
|
||||
import com.google.firebase.messaging.RemoteMessage
|
||||
+import expo.modules.backgroundnotificationhandler.BackgroundNotificationHandler
|
||||
+import expo.modules.backgroundnotificationhandler.BackgroundNotificationHandlerInterface
|
||||
+import expo.modules.backgroundnotificationhandler.ExpoBackgroundNotificationHandlerModule
|
||||
import expo.modules.interfaces.taskManager.TaskServiceProviderHelper
|
||||
import expo.modules.notifications.notifications.RemoteMessageSerializer
|
||||
import expo.modules.notifications.notifications.background.BackgroundRemoteNotificationTaskConsumer
|
||||
@@ -17,7 +20,8 @@ import expo.modules.notifications.tokens.interfaces.FirebaseTokenListener
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
|
||||
-open class FirebaseMessagingDelegate(protected val context: Context) : FirebaseMessagingDelegate {
|
||||
+open class FirebaseMessagingDelegate(protected val context: Context) : FirebaseMessagingDelegate,
|
||||
+ BackgroundNotificationHandlerInterface {
|
||||
companion object {
|
||||
// Unfortunately we cannot save state between instances of a service other way
|
||||
// than by static properties. Fortunately, using weak references we can
|
||||
@@ -94,8 +98,17 @@ open class FirebaseMessagingDelegate(protected val context: Context) : FirebaseM
|
||||
DebugLogging.logRemoteMessage("FirebaseMessagingDelegate.onMessageReceived: message", remoteMessage)
|
||||
val notification = createNotification(remoteMessage)
|
||||
DebugLogging.logNotification("FirebaseMessagingDelegate.onMessageReceived: notification", notification)
|
||||
- NotificationsService.receive(context, notification)
|
||||
- runTaskManagerTasks(remoteMessage)
|
||||
+
|
||||
+ if (!ExpoBackgroundNotificationHandlerModule.isForegrounded) {
|
||||
+ BackgroundNotificationHandler(context, this).handleMessage(remoteMessage)
|
||||
+ } else {
|
||||
+ showMessage(remoteMessage)
|
||||
+ runTaskManagerTasks(remoteMessage)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ override fun showMessage(remoteMessage: RemoteMessage) {
|
||||
+ NotificationsService.receive(context, createNotification(remoteMessage))
|
||||
}
|
||||
|
||||
private fun runTaskManagerTasks(remoteMessage: RemoteMessage) {
|
||||
@@ -1,44 +0,0 @@
|
||||
diff --git a/node_modules/metro/src/ModuleGraph/worker/JsFileWrapping.js b/node_modules/metro/src/ModuleGraph/worker/JsFileWrapping.js
|
||||
index 48a1409..ef185c9 100644
|
||||
--- a/node_modules/metro/src/ModuleGraph/worker/JsFileWrapping.js
|
||||
+++ b/node_modules/metro/src/ModuleGraph/worker/JsFileWrapping.js
|
||||
@@ -70,14 +70,19 @@ function wrapModule(
|
||||
importDefaultName,
|
||||
importAllName,
|
||||
dependencyMapName,
|
||||
- globalPrefix
|
||||
+ globalPrefix,
|
||||
+ moduleFactoryName
|
||||
) {
|
||||
const params = buildParameters(
|
||||
importDefaultName,
|
||||
importAllName,
|
||||
dependencyMapName
|
||||
);
|
||||
- const factory = functionFromProgram(fileAst.program, params);
|
||||
+ const factory = functionFromProgram(
|
||||
+ fileAst.program,
|
||||
+ params,
|
||||
+ moduleFactoryName
|
||||
+ );
|
||||
const def = t.callExpression(t.identifier(`${globalPrefix}__d`), [factory]);
|
||||
const ast = t.file(t.program([t.expressionStatement(def)]));
|
||||
const requireName = renameRequires(ast);
|
||||
@@ -107,7 +112,16 @@ function wrapJson(source, globalPrefix) {
|
||||
"});",
|
||||
].join("\n");
|
||||
}
|
||||
-function functionFromProgram(program, parameters) {
|
||||
+const JS_INVALID_IDENT_RE = /[^a-zA-Z0-9$_]/g;
|
||||
+function functionFromProgram(program, parameters, moduleFactoryName) {
|
||||
+ let identifier;
|
||||
+ if (typeof moduleFactoryName === "string" && moduleFactoryName !== "") {
|
||||
+ // Keep the name readable so it shows up in profiler traces.
|
||||
+ // Add an unlikely suffix to avoid collisions with the module code.
|
||||
+ identifier = t.identifier(
|
||||
+ `${moduleFactoryName.replace(JS_INVALID_IDENT_RE, "_")}__module_factory__`
|
||||
+ );
|
||||
+ }
|
||||
return t.functionExpression(
|
||||
undefined,
|
||||
parameters.map(makeIdentifier),
|
||||
@@ -1,50 +0,0 @@
|
||||
diff --git a/node_modules/metro-runtime/src/polyfills/require.js b/node_modules/metro-runtime/src/polyfills/require.js
|
||||
index ce67cb4..eeeae84 100644
|
||||
--- a/node_modules/metro-runtime/src/polyfills/require.js
|
||||
+++ b/node_modules/metro-runtime/src/polyfills/require.js
|
||||
@@ -22,6 +22,13 @@ global.__c = clear;
|
||||
global.__registerSegment = registerSegment;
|
||||
var modules = clear();
|
||||
|
||||
+if (__DEV__) {
|
||||
+ // Added by Dan for module init logging.
|
||||
+ global.__INIT_LOGS__ = []
|
||||
+ var initModuleCounter = 0
|
||||
+ var initModuleStack = []
|
||||
+}
|
||||
+
|
||||
// Don't use a Symbol here, it would pull in an extra polyfill with all sorts of
|
||||
// additional stuff (e.g. Array.from).
|
||||
const EMPTY = {};
|
||||
@@ -303,7 +310,30 @@ function loadModuleImplementation(moduleId, module) {
|
||||
throw module.error;
|
||||
}
|
||||
if (__DEV__) {
|
||||
- var Systrace = requireSystrace();
|
||||
+ // Added by Dan for module init logging.
|
||||
+ var Systrace = {
|
||||
+ beginEvent(label) {
|
||||
+ let fullLabel = initModuleCounter++ + ' ' + label
|
||||
+ global.__INIT_LOGS__.push(
|
||||
+ ' '.repeat(initModuleStack.length) +
|
||||
+ ' ENTER ' + fullLabel
|
||||
+ )
|
||||
+ initModuleStack.push({
|
||||
+ fullLabel,
|
||||
+ startTime: nativePerformanceNow(),
|
||||
+ })
|
||||
+ },
|
||||
+ endEvent() {
|
||||
+ const res = initModuleStack.pop()
|
||||
+ const fullLabel = res.fullLabel
|
||||
+ const startTime = res.startTime
|
||||
+ const timeElapsed = Math.round(nativePerformanceNow() - startTime)
|
||||
+ global.__INIT_LOGS__.push(
|
||||
+ ' '.repeat(initModuleStack.length) +
|
||||
+ ' LEAVE ' + fullLabel + ' [' + timeElapsed + 'ms]',
|
||||
+ )
|
||||
+ }
|
||||
+ };
|
||||
var Refresh = requireRefresh();
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
diff --git a/node_modules/metro-transform-worker/src/index.js b/node_modules/metro-transform-worker/src/index.js
|
||||
index 9f2e3d2..5222c8e 100644
|
||||
--- a/node_modules/metro-transform-worker/src/index.js
|
||||
+++ b/node_modules/metro-transform-worker/src/index.js
|
||||
@@ -189,6 +189,10 @@ async function transformJS(file, { config, options, projectRoot }) {
|
||||
let dependencyMapName = "";
|
||||
let dependencies;
|
||||
let wrappedAst;
|
||||
+ const minify =
|
||||
+ options.minify &&
|
||||
+ options.unstable_transformProfile !== "hermes-canary" &&
|
||||
+ options.unstable_transformProfile !== "hermes-stable";
|
||||
|
||||
// If the module to transform is a script (meaning that is not part of the
|
||||
// dependency graph and it code will just be prepended to the bundle modules),
|
||||
@@ -228,19 +232,20 @@ async function transformJS(file, { config, options, projectRoot }) {
|
||||
if (config.unstable_disableModuleWrapping === true) {
|
||||
wrappedAst = ast;
|
||||
} else {
|
||||
+ let moduleFactoryName;
|
||||
+ if (options.dev && !minify) {
|
||||
+ moduleFactoryName = file.filename;
|
||||
+ }
|
||||
({ ast: wrappedAst } = JsFileWrapping.wrapModule(
|
||||
ast,
|
||||
importDefault,
|
||||
importAll,
|
||||
dependencyMapName,
|
||||
- config.globalPrefix
|
||||
+ config.globalPrefix,
|
||||
+ moduleFactoryName
|
||||
));
|
||||
}
|
||||
}
|
||||
- const minify =
|
||||
- options.minify &&
|
||||
- options.unstable_transformProfile !== "hermes-canary" &&
|
||||
- options.unstable_transformProfile !== "hermes-stable";
|
||||
const reserved = [];
|
||||
if (config.unstable_dependencyMapReservedName != null) {
|
||||
reserved.push(config.unstable_dependencyMapReservedName);
|
||||
@@ -1,283 +0,0 @@
|
||||
diff --git a/node_modules/react-native/Libraries/Blob/RCTFileReaderModule.mm b/node_modules/react-native/Libraries/Blob/RCTFileReaderModule.mm
|
||||
index caa5540..c5d4e67 100644
|
||||
--- a/node_modules/react-native/Libraries/Blob/RCTFileReaderModule.mm
|
||||
+++ b/node_modules/react-native/Libraries/Blob/RCTFileReaderModule.mm
|
||||
@@ -73,7 +73,7 @@ @implementation RCTFileReaderModule
|
||||
} else {
|
||||
NSString *type = [RCTConvert NSString:blob[@"type"]];
|
||||
NSString *text = [NSString stringWithFormat:@"data:%@;base64,%@",
|
||||
- type != nil && [type length] > 0 ? type : @"application/octet-stream",
|
||||
+ ![type isEqual:[NSNull null]] && [type length] > 0 ? type : @"application/octet-stream",
|
||||
[data base64EncodedStringWithOptions:0]];
|
||||
|
||||
resolve(text);
|
||||
diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm
|
||||
index b0d71dc..41b9a0e 100644
|
||||
--- a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm
|
||||
+++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm
|
||||
@@ -377,10 +377,6 @@ - (void)textInputDidBeginEditing
|
||||
self.backedTextInputView.attributedText = [NSAttributedString new];
|
||||
}
|
||||
|
||||
- if (_selectTextOnFocus) {
|
||||
- [self.backedTextInputView selectAll:nil];
|
||||
- }
|
||||
-
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus
|
||||
reactTag:self.reactTag
|
||||
text:[self.backedTextInputView.attributedText.string copy]
|
||||
@@ -611,6 +607,10 @@ - (UIView *)reactAccessibilityElement
|
||||
- (void)reactFocus
|
||||
{
|
||||
[self.backedTextInputView reactFocus];
|
||||
+
|
||||
+ if (_selectTextOnFocus) {
|
||||
+ [self.backedTextInputView selectAll:nil];
|
||||
+ }
|
||||
}
|
||||
|
||||
- (void)reactBlur
|
||||
diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
index e9b330f..ec5f58c 100644
|
||||
--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
@@ -15,5 +15,8 @@
|
||||
@property (nonatomic, copy) NSString *title;
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onRefresh;
|
||||
@property (nonatomic, weak) UIScrollView *scrollView;
|
||||
+@property (nonatomic, copy) UIColor *customTintColor;
|
||||
+
|
||||
+- (void)forwarderBeginRefreshing;
|
||||
|
||||
@end
|
||||
diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m
|
||||
index b09e653..d2b4e05 100644
|
||||
--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m
|
||||
+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m
|
||||
@@ -22,6 +22,7 @@ @implementation RCTRefreshControl {
|
||||
NSString *_title;
|
||||
UIColor *_titleColor;
|
||||
CGFloat _progressViewOffset;
|
||||
+ UIColor *_customTintColor;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
@@ -56,6 +57,12 @@ - (void)layoutSubviews
|
||||
_isInitialRender = false;
|
||||
}
|
||||
|
||||
+- (void)didMoveToSuperview
|
||||
+{
|
||||
+ [super didMoveToSuperview];
|
||||
+ [self setTintColor:_customTintColor];
|
||||
+}
|
||||
+
|
||||
- (void)beginRefreshingProgrammatically
|
||||
{
|
||||
UInt64 beginRefreshingTimestamp = _currentRefreshingStateTimestamp;
|
||||
@@ -203,4 +210,58 @@ - (void)refreshControlValueChanged
|
||||
}
|
||||
}
|
||||
|
||||
+- (void)setCustomTintColor:(UIColor *)customTintColor
|
||||
+{
|
||||
+ _customTintColor = customTintColor;
|
||||
+ [self setTintColor:customTintColor];
|
||||
+}
|
||||
+
|
||||
+// Fix for https://github.com/facebook/react-native/issues/43388
|
||||
+// A bug in iOS 17.4 causes the haptic to not play when refreshing if the tintColor
|
||||
+// is set before the refresh control gets added to the scrollview. We'll call this
|
||||
+// function whenever the superview changes. We'll also call it if the value of customTintColor
|
||||
+// changes.
|
||||
+- (void)setTintColor:(UIColor *)tintColor
|
||||
+{
|
||||
+ if ([self.superview isKindOfClass:[UIScrollView class]] && self.tintColor != tintColor) {
|
||||
+ [super setTintColor:tintColor];
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ This method is used by Bluesky's ExpoScrollForwarder. This allows other React Native
|
||||
+ libraries to perform a refresh of a scrollview and access the refresh control's onRefresh
|
||||
+ function.
|
||||
+ */
|
||||
+- (void)forwarderBeginRefreshing
|
||||
+{
|
||||
+ _refreshingProgrammatically = NO;
|
||||
+
|
||||
+ [self sizeToFit];
|
||||
+
|
||||
+ if (!self.scrollView) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ UIScrollView *scrollView = (UIScrollView *)self.scrollView;
|
||||
+
|
||||
+ [UIView animateWithDuration:0.3
|
||||
+ delay:0
|
||||
+ options:UIViewAnimationOptionBeginFromCurrentState
|
||||
+ animations:^(void) {
|
||||
+ // Whenever we call this method, the scrollview will always be at a position of
|
||||
+ // -130 or less. Scrolling back to -65 simulates the default behavior of RCTRefreshControl
|
||||
+ [scrollView setContentOffset:CGPointMake(0, -65)];
|
||||
+ }
|
||||
+ completion:^(__unused BOOL finished) {
|
||||
+ [super beginRefreshing];
|
||||
+ [self setCurrentRefreshingState:super.refreshing];
|
||||
+
|
||||
+ if (self->_onRefresh) {
|
||||
+ self->_onRefresh(nil);
|
||||
+ }
|
||||
+ }
|
||||
+ ];
|
||||
+}
|
||||
+
|
||||
@end
|
||||
diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m
|
||||
index 40aaf9c..1c60164 100644
|
||||
--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m
|
||||
+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m
|
||||
@@ -22,11 +22,12 @@ - (UIView *)view
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(onRefresh, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(refreshing, BOOL)
|
||||
-RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
|
||||
RCT_EXPORT_VIEW_PROPERTY(title, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(titleColor, UIColor)
|
||||
RCT_EXPORT_VIEW_PROPERTY(progressViewOffset, CGFloat)
|
||||
|
||||
+RCT_REMAP_VIEW_PROPERTY(tintColor, customTintColor, UIColor)
|
||||
+
|
||||
RCT_EXPORT_METHOD(setNativeRefreshing : (nonnull NSNumber *)viewTag toRefreshing : (BOOL)refreshing)
|
||||
{
|
||||
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
||||
diff --git a/node_modules/react-native/React/Views/ScrollView/RCTScrollView.m b/node_modules/react-native/React/Views/ScrollView/RCTScrollView.m
|
||||
index 1aead51..39e6244 100644
|
||||
--- a/node_modules/react-native/React/Views/ScrollView/RCTScrollView.m
|
||||
+++ b/node_modules/react-native/React/Views/ScrollView/RCTScrollView.m
|
||||
@@ -159,31 +159,6 @@ - (BOOL)touchesShouldCancelInContentView:(__unused UIView *)view
|
||||
return !shouldDisableScrollInteraction;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Automatically centers the content such that if the content is smaller than the
|
||||
- * ScrollView, we force it to be centered, but when you zoom or the content otherwise
|
||||
- * becomes larger than the ScrollView, there is no padding around the content but it
|
||||
- * can still fill the whole view.
|
||||
- */
|
||||
-- (void)setContentOffset:(CGPoint)contentOffset
|
||||
-{
|
||||
- UIView *contentView = [self contentView];
|
||||
- if (contentView && _centerContent && !CGSizeEqualToSize(contentView.frame.size, CGSizeZero)) {
|
||||
- CGSize subviewSize = contentView.frame.size;
|
||||
- CGSize scrollViewSize = self.bounds.size;
|
||||
- if (subviewSize.width <= scrollViewSize.width) {
|
||||
- contentOffset.x = -(scrollViewSize.width - subviewSize.width) / 2.0;
|
||||
- }
|
||||
- if (subviewSize.height <= scrollViewSize.height) {
|
||||
- contentOffset.y = -(scrollViewSize.height - subviewSize.height) / 2.0;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- super.contentOffset = CGPointMake(
|
||||
- RCTSanitizeNaNValue(contentOffset.x, @"scrollView.contentOffset.x"),
|
||||
- RCTSanitizeNaNValue(contentOffset.y, @"scrollView.contentOffset.y"));
|
||||
-}
|
||||
-
|
||||
- (void)setFrame:(CGRect)frame
|
||||
{
|
||||
// Preserving and revalidating `contentOffset`.
|
||||
@@ -427,6 +402,11 @@ - (void)setRemoveClippedSubviews:(__unused BOOL)removeClippedSubviews
|
||||
// Does nothing
|
||||
}
|
||||
|
||||
+- (void)setFrame:(CGRect)frame {
|
||||
+ [super setFrame:frame];
|
||||
+ [self centerContentIfNeeded];
|
||||
+}
|
||||
+
|
||||
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex
|
||||
{
|
||||
[super insertReactSubview:view atIndex:atIndex];
|
||||
@@ -444,6 +424,8 @@ - (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex
|
||||
RCTApplyTransformationAccordingLayoutDirection(_contentView, self.reactLayoutDirection);
|
||||
[_scrollView addSubview:view];
|
||||
}
|
||||
+
|
||||
+ [self centerContentIfNeeded];
|
||||
}
|
||||
|
||||
- (void)removeReactSubview:(UIView *)subview
|
||||
@@ -652,9 +634,46 @@ -(void)delegateMethod : (UIScrollView *)scrollView \
|
||||
}
|
||||
|
||||
RCT_SCROLL_EVENT_HANDLER(scrollViewWillBeginDecelerating, onMomentumScrollBegin)
|
||||
-RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, onScroll)
|
||||
RCT_SCROLL_EVENT_HANDLER(scrollViewDidScrollToTop, onScrollToTop)
|
||||
|
||||
+-(void)scrollViewDidZoom : (UIScrollView *)scrollView
|
||||
+{
|
||||
+ [self centerContentIfNeeded];
|
||||
+
|
||||
+ RCT_SEND_SCROLL_EVENT(onScroll, nil);
|
||||
+ RCT_FORWARD_SCROLL_EVENT(scrollViewDidZoom : scrollView);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Automatically centers the content such that if the content is smaller than the
|
||||
+ * ScrollView, we force it to be centered, but when you zoom or the content otherwise
|
||||
+ * becomes larger than the ScrollView, there is no padding around the content but it
|
||||
+ * can still fill the whole view.
|
||||
+ *
|
||||
+ * PATCHED: This deviates from the original React Native implementation to fix two issues:
|
||||
+ *
|
||||
+ * - The scroll view was swallowing any taps immediately after pinching
|
||||
+ * - The scroll view was jittering when crossing the full screen threshold while pinching
|
||||
+ *
|
||||
+ * This implementation is based on https://petersteinberger.com/blog/2013/how-to-center-uiscrollview/.
|
||||
+ */
|
||||
+-(void)centerContentIfNeeded
|
||||
+{
|
||||
+ if (_scrollView.centerContent &&
|
||||
+ !CGSizeEqualToSize(self.contentSize, CGSizeZero) &&
|
||||
+ !CGSizeEqualToSize(self.bounds.size, CGSizeZero)
|
||||
+ ) {
|
||||
+ CGFloat top = 0, left = 0;
|
||||
+ if (self.contentSize.width < self.bounds.size.width) {
|
||||
+ left = (self.bounds.size.width - self.contentSize.width) * 0.5f;
|
||||
+ }
|
||||
+ if (self.contentSize.height < self.bounds.size.height) {
|
||||
+ top = (self.bounds.size.height - self.contentSize.height) * 0.5f;
|
||||
+ }
|
||||
+ _scrollView.contentInset = UIEdgeInsetsMake(top, left, top, left);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
- (void)addScrollListener:(NSObject<UIScrollViewDelegate> *)scrollListener
|
||||
{
|
||||
[_scrollListeners addObject:scrollListener];
|
||||
@@ -913,6 +932,7 @@ - (void)updateContentSizeIfNeeded
|
||||
CGSize contentSize = self.contentSize;
|
||||
if (!CGSizeEqualToSize(_scrollView.contentSize, contentSize)) {
|
||||
_scrollView.contentSize = contentSize;
|
||||
+ [self centerContentIfNeeded];
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.java
|
||||
index 5f5e1ab..aac00b6 100644
|
||||
--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.java
|
||||
+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.java
|
||||
@@ -99,8 +99,9 @@ public class JavaTimerManager {
|
||||
}
|
||||
|
||||
// If the JS thread is busy for multiple frames we cancel any other pending runnable.
|
||||
- if (mCurrentIdleCallbackRunnable != null) {
|
||||
- mCurrentIdleCallbackRunnable.cancel();
|
||||
+ IdleCallbackRunnable currentRunnable = mCurrentIdleCallbackRunnable;
|
||||
+ if (currentRunnable != null) {
|
||||
+ currentRunnable.cancel();
|
||||
}
|
||||
|
||||
mCurrentIdleCallbackRunnable = new IdleCallbackRunnable(frameTimeNanos);
|
||||
@@ -0,0 +1,146 @@
|
||||
diff --git a/node_modules/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts b/node_modules/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts
|
||||
index 62f52a7..ca30165 100644
|
||||
--- a/node_modules/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts
|
||||
+++ b/node_modules/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts
|
||||
@@ -426,9 +426,10 @@ export interface ViewStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle {
|
||||
*/
|
||||
pointerEvents?: 'box-none' | 'none' | 'box-only' | 'auto' | undefined;
|
||||
isolation?: 'auto' | 'isolate' | undefined;
|
||||
- cursor?: CursorValue | undefined;
|
||||
+ cursor?: CursorValue | string | undefined;
|
||||
boxShadow?: ReadonlyArray<BoxShadowValue> | string | undefined;
|
||||
filter?: ReadonlyArray<FilterFunction> | string | undefined;
|
||||
+ transformOrigin?: string | (string | number)[] | undefined;
|
||||
}
|
||||
|
||||
export type FontVariant =
|
||||
@@ -536,7 +537,11 @@ export interface TextStyle extends TextStyleIOS, TextStyleAndroid, ViewStyle {
|
||||
textShadowOffset?: {width: number; height: number} | undefined;
|
||||
textShadowRadius?: number | undefined;
|
||||
textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase' | undefined;
|
||||
- userSelect?: 'auto' | 'none' | 'text' | 'contain' | 'all' | undefined;
|
||||
+ userSelect?: 'auto' | 'none' | 'text' | 'contain' | 'all' | string | undefined;
|
||||
+ cursor?: CursorValue | string | undefined;
|
||||
+ boxShadow?: ReadonlyArray<BoxShadowValue> | string | undefined;
|
||||
+ filter?: ReadonlyArray<FilterFunction> | string | undefined;
|
||||
+ transformOrigin?: string | (string | number)[] | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -558,5 +563,8 @@ export interface ImageStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle {
|
||||
tintColor?: ColorValue | undefined;
|
||||
opacity?: AnimatableNumericValue | undefined;
|
||||
objectFit?: 'cover' | 'contain' | 'fill' | 'scale-down' | undefined;
|
||||
- cursor?: CursorValue | undefined;
|
||||
+ cursor?: CursorValue | string | undefined;
|
||||
+ boxShadow?: ReadonlyArray<BoxShadowValue> | string | undefined;
|
||||
+ filter?: ReadonlyArray<FilterFunction> | string | undefined;
|
||||
+ transformOrigin?: string | (string | number)[] | undefined;
|
||||
}
|
||||
diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
index e9b330f..ec5f58c 100644
|
||||
--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
@@ -15,5 +15,8 @@
|
||||
@property (nonatomic, copy) NSString *title;
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onRefresh;
|
||||
@property (nonatomic, weak) UIScrollView *scrollView;
|
||||
+@property (nonatomic, copy) UIColor *customTintColor;
|
||||
+
|
||||
+- (void)forwarderBeginRefreshing;
|
||||
|
||||
@end
|
||||
diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m
|
||||
index 53bfd04..ff1b1ed 100644
|
||||
--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m
|
||||
+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m
|
||||
@@ -23,6 +23,7 @@ @implementation RCTRefreshControl {
|
||||
UIColor *_titleColor;
|
||||
CGFloat _progressViewOffset;
|
||||
BOOL _hasMovedToWindow;
|
||||
+ UIColor *_customTintColor;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
@@ -58,6 +59,12 @@ - (void)layoutSubviews
|
||||
_isInitialRender = false;
|
||||
}
|
||||
|
||||
+- (void)didMoveToSuperview
|
||||
+{
|
||||
+ [super didMoveToSuperview];
|
||||
+ [self setTintColor:_customTintColor];
|
||||
+}
|
||||
+
|
||||
- (void)didMoveToWindow
|
||||
{
|
||||
[super didMoveToWindow];
|
||||
@@ -221,4 +228,50 @@ - (void)refreshControlValueChanged
|
||||
}
|
||||
}
|
||||
|
||||
+// Fix for https://github.com/facebook/react-native/issues/43388
|
||||
+// A bug in iOS 17.4 causes the haptic to not play when refreshing if the tintColor
|
||||
+// is set before the refresh control gets added to the scrollview. We'll call this
|
||||
+// function whenever the superview changes. We'll also call it if the value of customTintColor
|
||||
+// changes.
|
||||
+- (void)setTintColor:(UIColor *)tintColor
|
||||
+{
|
||||
+ if ([self.superview isKindOfClass:[UIScrollView class]] && self.tintColor != tintColor) {
|
||||
+ [super setTintColor:tintColor];
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+// This method is used by Bluesky's ExpoScrollForwarder. This allows other React Native
|
||||
+// libraries to perform a refresh of a scrollview and access the refresh control's onRefresh
|
||||
+// function.
|
||||
+- (void)forwarderBeginRefreshing
|
||||
+{
|
||||
+ _refreshingProgrammatically = NO;
|
||||
+
|
||||
+ [self sizeToFit];
|
||||
+
|
||||
+ if (!self.scrollView) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ UIScrollView *scrollView = (UIScrollView *)self.scrollView;
|
||||
+
|
||||
+ [UIView animateWithDuration:0.3
|
||||
+ delay:0
|
||||
+ options:UIViewAnimationOptionBeginFromCurrentState
|
||||
+ animations:^(void) {
|
||||
+ // Whenever we call this method, the scrollview will always be at a position of
|
||||
+ // -130 or less. Scrolling back to -65 simulates the default behavior of RCTRefreshControl
|
||||
+ [scrollView setContentOffset:CGPointMake(0, -65)];
|
||||
+ }
|
||||
+ completion:^(__unused BOOL finished) {
|
||||
+ [super beginRefreshing];
|
||||
+ [self setCurrentRefreshingState:super.refreshing];
|
||||
+
|
||||
+ if (self->_onRefresh) {
|
||||
+ self->_onRefresh(nil);
|
||||
+ }
|
||||
+ }
|
||||
+ ];
|
||||
+}
|
||||
+
|
||||
@end
|
||||
diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m
|
||||
index 40aaf9c..1c60164 100644
|
||||
--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m
|
||||
+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControlManager.m
|
||||
@@ -22,11 +22,12 @@ - (UIView *)view
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(onRefresh, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(refreshing, BOOL)
|
||||
-RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
|
||||
RCT_EXPORT_VIEW_PROPERTY(title, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(titleColor, UIColor)
|
||||
RCT_EXPORT_VIEW_PROPERTY(progressViewOffset, CGFloat)
|
||||
|
||||
+RCT_REMAP_VIEW_PROPERTY(tintColor, customTintColor, UIColor)
|
||||
+
|
||||
RCT_EXPORT_METHOD(setNativeRefreshing : (nonnull NSNumber *)viewTag toRefreshing : (BOOL)refreshing)
|
||||
{
|
||||
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
||||
@@ -0,0 +1,16 @@
|
||||
diff --git a/node_modules/react-native-compressor/package.json b/node_modules/react-native-compressor/package.json
|
||||
index 8adf7dc..8dd43a6 100644
|
||||
--- a/node_modules/react-native-compressor/package.json
|
||||
+++ b/node_modules/react-native-compressor/package.json
|
||||
@@ -197,11 +197,6 @@
|
||||
"name": "RNCompressorSpec",
|
||||
"type": "modules",
|
||||
"jsSrcsDir": "src"
|
||||
- },
|
||||
- {
|
||||
- "name": "RNVideoCompressorSpec",
|
||||
- "type": "modules",
|
||||
- "jsSrcsDir": "src"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
diff --git a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
|
||||
index 5de0845..fa477e7 100644
|
||||
--- a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
|
||||
+++ b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
|
||||
@@ -21,6 +21,7 @@ import android.webkit.MimeTypeMap;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
+import androidx.exifinterface.media.ExifInterface;
|
||||
|
||||
import com.facebook.react.bridge.ActivityEventListener;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
@@ -678,6 +679,15 @@ class PickerModule extends ReactContextBaseJavaModule implements ActivityEventLi
|
||||
throw new Exception("Cannot select remote files");
|
||||
}
|
||||
BitmapFactory.Options original = validateImage(path);
|
||||
+ ExifInterface originalExif = new ExifInterface(path);
|
||||
+ int orientation = originalExif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
|
||||
+ boolean invertDimensions = (
|
||||
+ orientation == ExifInterface.ORIENTATION_ROTATE_90 ||
|
||||
+ orientation == ExifInterface.ORIENTATION_ROTATE_270 ||
|
||||
+ orientation == ExifInterface.ORIENTATION_TRANSPOSE ||
|
||||
+ orientation == ExifInterface.ORIENTATION_TRANSVERSE
|
||||
+ );
|
||||
+
|
||||
|
||||
// if compression options are provided image will be compressed. If none options is provided,
|
||||
// then original image will be returned
|
||||
@@ -687,8 +697,8 @@ class PickerModule extends ReactContextBaseJavaModule implements ActivityEventLi
|
||||
long modificationDate = new File(path).lastModified();
|
||||
|
||||
image.putString("path", "file://" + compressedImagePath);
|
||||
- image.putInt("width", options.outWidth);
|
||||
- image.putInt("height", options.outHeight);
|
||||
+ image.putInt("width", invertDimensions ? options.outHeight : options.outWidth);
|
||||
+ image.putInt("height", invertDimensions ? options.outWidth : options.outHeight);
|
||||
image.putString("mime", options.outMimeType);
|
||||
image.putInt("size", (int) new File(compressedImagePath).length());
|
||||
image.putString("modificationDate", String.valueOf(modificationDate));
|
||||
@@ -0,0 +1,19 @@
|
||||
diff --git a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
|
||||
index c45adc0..338a571 100644
|
||||
--- a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
|
||||
+++ b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
|
||||
@@ -42,10 +42,10 @@ open class ScreenViewManager : ViewGroupManager<Screen>(), RNSScreenManagerInter
|
||||
props: ReactStylesDiffMap?,
|
||||
stateWrapper: StateWrapper?
|
||||
): Any? {
|
||||
- if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
- // fabricViewStateManager should never be null in Fabric. The null check is only for Paper's empty impl.
|
||||
- view.fabricViewStateManager?.setStateWrapper(stateWrapper)
|
||||
- }
|
||||
+// if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
+// // fabricViewStateManager should never be null in Fabric. The null check is only for Paper's empty impl.
|
||||
+// view.fabricViewStateManager?.setStateWrapper(stateWrapper)
|
||||
+// }
|
||||
return super.updateState(view, props, stateWrapper)
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
diff --git a/node_modules/react-native-svg/android/src/main/java/com/horcrux/svg/PathView.java b/node_modules/react-native-svg/android/src/main/java/com/horcrux/svg/PathView.java
|
||||
index 06829bd..1b15818 100644
|
||||
--- a/node_modules/react-native-svg/android/src/main/java/com/horcrux/svg/PathView.java
|
||||
+++ b/node_modules/react-native-svg/android/src/main/java/com/horcrux/svg/PathView.java
|
||||
@@ -14,17 +14,33 @@ import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.HashMap;
|
||||
+
|
||||
+class ParsedPath {
|
||||
+ final Path path;
|
||||
+ final ArrayList<PathElement> elements;
|
||||
+
|
||||
+ ParsedPath(Path path, ArrayList<PathElement> elements) {
|
||||
+ this.path = path;
|
||||
+ this.elements = elements;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
@SuppressLint("ViewConstructor")
|
||||
class PathView extends RenderableView {
|
||||
private Path mPath;
|
||||
|
||||
+ // This grows forever but for our use case (static icons) it's ok.
|
||||
+ private static final HashMap<String, ParsedPath> sPathCache = new HashMap<>();
|
||||
+
|
||||
public PathView(ReactContext reactContext) {
|
||||
super(reactContext);
|
||||
PathParser.mScale = mScale;
|
||||
mPath = new Path();
|
||||
}
|
||||
|
||||
- public void setD(String d) {
|
||||
+ void setDByParsing(String d) {
|
||||
mPath = PathParser.parse(d);
|
||||
elements = PathParser.elements;
|
||||
for (PathElement elem : elements) {
|
||||
@@ -33,6 +49,17 @@ class PathView extends RenderableView {
|
||||
point.y *= mScale;
|
||||
}
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ public void setD(String d) {
|
||||
+ ParsedPath cached = sPathCache.get(d);
|
||||
+ if (cached != null) {
|
||||
+ mPath = cached.path;
|
||||
+ elements = cached.elements;
|
||||
+ } else {
|
||||
+ setDByParsing(d);
|
||||
+ sPathCache.put(d, new ParsedPath(mPath, elements));
|
||||
+ }
|
||||
invalidate();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user