delete old packages
This commit is contained in:
+1
-4
@@ -27,7 +27,6 @@
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "is-ci || husky install",
|
||||
"postinstall": "patch-package && pnpm intl:compile-if-needed",
|
||||
"prebuild": "EXPO_NO_GIT_STATUS=1 expo prebuild --clean",
|
||||
"android": "expo run:android",
|
||||
"android:prod": "expo run:android --variant release",
|
||||
@@ -66,7 +65,6 @@
|
||||
"intl:extract": "lingui extract --clean --locale en",
|
||||
"intl:extract:all": "lingui extract --clean",
|
||||
"intl:compile": "lingui compile",
|
||||
"intl:compile-if-needed": "is-ci || [ -f src/locale/locales/en/messages.ts ] || pnpm intl:compile",
|
||||
"intl:pull": "crowdin download translations --verbose -b main",
|
||||
"intl:push": "crowdin push translations --verbose -b main",
|
||||
"intl:push-sources": "crowdin push sources --verbose -b main",
|
||||
@@ -172,7 +170,7 @@
|
||||
"expo-location": "~19.0.8",
|
||||
"expo-media-library": "~18.2.1",
|
||||
"expo-notifications": "~0.32.17",
|
||||
"expo-paste-input": "^0.1.15",
|
||||
"expo-paste-input": "^0.2.1",
|
||||
"expo-privacy-sensitive": "^0.1.0",
|
||||
"expo-screen-orientation": "~9.0.8",
|
||||
"expo-sharing": "~14.0.8",
|
||||
@@ -199,7 +197,6 @@
|
||||
"multiformats": "9.9.0",
|
||||
"nanoid": "^5.0.5",
|
||||
"normalize-url": "^8.0.0",
|
||||
"patch-package": "^8.0.1",
|
||||
"psl": "1.9.0",
|
||||
"radix-ui": "^1.4.3",
|
||||
"react": "19.1.0",
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
diff --git a/node_modules/@discord/bottom-sheet/src/hooks/useStableCallback.ts b/node_modules/@discord/bottom-sheet/src/hooks/useStableCallback.ts
|
||||
index 1c788ab..d30f330 100644
|
||||
--- a/node_modules/@discord/bottom-sheet/src/hooks/useStableCallback.ts
|
||||
+++ b/node_modules/@discord/bottom-sheet/src/hooks/useStableCallback.ts
|
||||
@@ -6,7 +6,7 @@ type Callback = (...args: any[]) => any;
|
||||
* https://gist.github.com/JakeCoxon/c7ebf6e6496f8468226fd36b596e1985
|
||||
*/
|
||||
export const useStableCallback = (callback: Callback) => {
|
||||
- const callbackRef = useRef<Callback>();
|
||||
+ const callbackRef = useRef<Callback>(undefined);
|
||||
const memoCallback = useCallback(
|
||||
(...args: any) => callbackRef.current && callbackRef.current(...args),
|
||||
[]
|
||||
@@ -1,33 +0,0 @@
|
||||
diff --git a/node_modules/@sentry/react-native/dist/js/tools/sentryMetroSerializer.js b/node_modules/@sentry/react-native/dist/js/tools/sentryMetroSerializer.js
|
||||
index d7f2350..e9c0368 100644
|
||||
--- a/node_modules/@sentry/react-native/dist/js/tools/sentryMetroSerializer.js
|
||||
+++ b/node_modules/@sentry/react-native/dist/js/tools/sentryMetroSerializer.js
|
||||
@@ -12,12 +12,9 @@ exports.createSentryMetroSerializer = exports.unstable_beforeAssetSerializationP
|
||||
const crypto = require("crypto");
|
||||
const utils_1 = require("./utils");
|
||||
const utils_2 = require("./vendor/metro/utils");
|
||||
-let countLines;
|
||||
-try {
|
||||
- countLines = require('metro/private/lib/countLines');
|
||||
-}
|
||||
-catch (e) {
|
||||
- countLines = require('metro/src/lib/countLines');
|
||||
+const newline = /\r\n?|\n|\u2028|\u2029/g;
|
||||
+function countLines(string) {
|
||||
+ return (string.match(newline) || []).length + 1;
|
||||
}
|
||||
const DEBUG_ID_PLACE_HOLDER = '__debug_id_place_holder__';
|
||||
const DEBUG_ID_MODULE_PATH = '__debugid__';
|
||||
diff --git a/node_modules/@sentry/react-native/scripts/expo-upload-sourcemaps.js b/node_modules/@sentry/react-native/scripts/expo-upload-sourcemaps.js
|
||||
index b3783b5..d5e3e45 100755
|
||||
--- a/node_modules/@sentry/react-native/scripts/expo-upload-sourcemaps.js
|
||||
+++ b/node_modules/@sentry/react-native/scripts/expo-upload-sourcemaps.js
|
||||
@@ -218,7 +218,7 @@ for (const [assetGroupName, assets] of Object.entries(groupedAssets)) {
|
||||
|
||||
const isHermes = assets.find(asset => asset.endsWith('.hbc'));
|
||||
const windowsCallback = process.platform === "win32" ? 'node ' : '';
|
||||
- execSync(`${windowsCallback}${sentryCliBin} sourcemaps upload ${isHermes ? '--debug-id-reference' : ''} ${assets.join(' ')}`, {
|
||||
+ execSync(`${windowsCallback}${sentryCliBin} sourcemaps upload ${isHermes ? '--debug-id-reference' : ''} ${assets.join(' ')} --dist ${process.env.SENTRY_DIST}`, {
|
||||
env: {
|
||||
...process.env,
|
||||
[SENTRY_PROJECT]: sentryProject,
|
||||
@@ -1,16 +0,0 @@
|
||||
diff --git a/node_modules/expo-font/ios/FontLoaderModule.swift b/node_modules/expo-font/ios/FontLoaderModule.swift
|
||||
index 183480f..7b64f6e 100644
|
||||
--- a/node_modules/expo-font/ios/FontLoaderModule.swift
|
||||
+++ b/node_modules/expo-font/ios/FontLoaderModule.swift
|
||||
@@ -2,10 +2,9 @@ import ExpoModulesCore
|
||||
|
||||
public final class FontLoaderModule: Module {
|
||||
// could be a Set, but to be able to pass to JS we keep it as an array
|
||||
- private var registeredFonts: [String]
|
||||
+ private lazy var registeredFonts: [String] = queryCustomNativeFonts()
|
||||
|
||||
public required init(appContext: AppContext) {
|
||||
- self.registeredFonts = queryCustomNativeFonts()
|
||||
super.init(appContext: appContext)
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
diff --git a/node_modules/expo-glass-effect/ios/GlassContainer.swift b/node_modules/expo-glass-effect/ios/GlassContainer.swift
|
||||
index 61fb67c..b2d111e 100644
|
||||
--- a/node_modules/expo-glass-effect/ios/GlassContainer.swift
|
||||
+++ b/node_modules/expo-glass-effect/ios/GlassContainer.swift
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2022-present 650 Industries. All rights reserved.
|
||||
|
||||
import ExpoModulesCore
|
||||
+import React
|
||||
|
||||
public final class GlassContainer: ExpoView {
|
||||
private var containerEffect: Any?
|
||||
@@ -46,11 +47,19 @@ public final class GlassContainer: ExpoView {
|
||||
}
|
||||
}
|
||||
|
||||
- public override func mountChildComponentView(_ childComponentView: UIView, index: Int) {
|
||||
+ // Paper: redirect children into the container effect's contentView
|
||||
+ public override func didUpdateReactSubviews() {
|
||||
+ for subview in self.reactSubviews() {
|
||||
+ containerEffectView.contentView.addSubview(subview)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Fabric: redirect children into the container effect's contentView
|
||||
+ @objc public func mountChildComponentView(_ childComponentView: UIView, index: Int) {
|
||||
containerEffectView.contentView.insertSubview(childComponentView, at: index)
|
||||
}
|
||||
|
||||
- public override func unmountChildComponentView(_ childComponentView: UIView, index: Int) {
|
||||
+ @objc public func unmountChildComponentView(_ childComponentView: UIView, index: Int) {
|
||||
childComponentView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
diff --git a/node_modules/expo-glass-effect/ios/GlassView.swift b/node_modules/expo-glass-effect/ios/GlassView.swift
|
||||
index 35cd8f3..9587306 100644
|
||||
--- a/node_modules/expo-glass-effect/ios/GlassView.swift
|
||||
+++ b/node_modules/expo-glass-effect/ios/GlassView.swift
|
||||
@@ -271,11 +271,19 @@ public final class GlassView: ExpoView {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
- public override func mountChildComponentView(_ childComponentView: UIView, index: Int) {
|
||||
+ // Paper: redirect children into the glass effect's contentView
|
||||
+ public override func didUpdateReactSubviews() {
|
||||
+ for subview in self.reactSubviews() {
|
||||
+ glassEffectView.contentView.addSubview(subview)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Fabric: redirect children into the glass effect's contentView
|
||||
+ @objc public func mountChildComponentView(_ childComponentView: UIView, index: Int) {
|
||||
glassEffectView.contentView.insertSubview(childComponentView, at: index)
|
||||
}
|
||||
|
||||
- public override func unmountChildComponentView(_ childComponentView: UIView, index: Int) {
|
||||
+ @objc public func unmountChildComponentView(_ childComponentView: UIView, index: Int) {
|
||||
childComponentView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
diff --git a/node_modules/expo-haptics/android/src/main/java/expo/modules/haptics/HapticsModule.kt b/node_modules/expo-haptics/android/src/main/java/expo/modules/haptics/HapticsModule.kt
|
||||
index 1520465..6ea988a 100644
|
||||
--- a/node_modules/expo-haptics/android/src/main/java/expo/modules/haptics/HapticsModule.kt
|
||||
+++ b/node_modules/expo-haptics/android/src/main/java/expo/modules/haptics/HapticsModule.kt
|
||||
@@ -42,7 +42,7 @@ class HapticsModule : Module() {
|
||||
|
||||
private fun vibrate(type: HapticsVibrationType) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
- vibrator.vibrate(VibrationEffect.createWaveform(type.timings, type.amplitudes, -1))
|
||||
+ vibrator.vibrate(VibrationEffect.createWaveform(type.oldSDKPattern, intArrayOf(0, 100), -1))
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
vibrator.vibrate(type.oldSDKPattern, -1)
|
||||
@@ -1,103 +0,0 @@
|
||||
diff --git a/node_modules/expo-image/build/Image.types.d.ts b/node_modules/expo-image/build/Image.types.d.ts
|
||||
index 022ae48..416504f 100644
|
||||
--- a/node_modules/expo-image/build/Image.types.d.ts
|
||||
+++ b/node_modules/expo-image/build/Image.types.d.ts
|
||||
@@ -152,6 +152,16 @@ export interface ImageProps extends Omit<ViewProps, 'style' | 'children'> {
|
||||
* @default 'normal'
|
||||
*/
|
||||
priority?: 'low' | 'normal' | 'high' | null;
|
||||
+ /**
|
||||
+ * The loading behavior for the image. Maps to the native HTML `loading` attribute on web.
|
||||
+ *
|
||||
+ * - `'lazy'` - Defers loading until the image is near the viewport.
|
||||
+ * - `'eager'` - Loads the image immediately.
|
||||
+ *
|
||||
+ * @default undefined
|
||||
+ * @platform web
|
||||
+ */
|
||||
+ loading?: 'lazy' | 'eager' | null;
|
||||
/**
|
||||
* Determines whether to cache the image and where: on the disk, in the memory or both.
|
||||
*
|
||||
diff --git a/node_modules/expo-image/src/ExpoImage.web.tsx b/node_modules/expo-image/src/ExpoImage.web.tsx
|
||||
index 2a49ff0..1c3de93 100644
|
||||
--- a/node_modules/expo-image/src/ExpoImage.web.tsx
|
||||
+++ b/node_modules/expo-image/src/ExpoImage.web.tsx
|
||||
@@ -70,6 +70,7 @@ export default function ExpoImage({
|
||||
onLoadEnd,
|
||||
onDisplay,
|
||||
priority,
|
||||
+ loading,
|
||||
blurRadius,
|
||||
recyclingKey,
|
||||
style,
|
||||
@@ -118,6 +119,7 @@ export default function ExpoImage({
|
||||
accessibilityLabel={accessibilityLabel ?? alt}
|
||||
cachePolicy={cachePolicy}
|
||||
priority={priority}
|
||||
+ loading={loading}
|
||||
tintColor={tintColor}
|
||||
/>
|
||||
),
|
||||
@@ -149,6 +151,7 @@ export default function ExpoImage({
|
||||
className={className}
|
||||
cachePolicy={cachePolicy}
|
||||
priority={priority}
|
||||
+ loading={loading}
|
||||
contentPosition={selectedSource ? contentPosition : { top: '50%', left: '50%' }}
|
||||
hashPlaceholderContentPosition={contentPosition}
|
||||
hashPlaceholderStyle={imageHashStyle}
|
||||
diff --git a/node_modules/expo-image/src/Image.types.ts b/node_modules/expo-image/src/Image.types.ts
|
||||
index 9dec0e7..61c1621 100644
|
||||
--- a/node_modules/expo-image/src/Image.types.ts
|
||||
+++ b/node_modules/expo-image/src/Image.types.ts
|
||||
@@ -178,6 +178,17 @@ export interface ImageProps extends Omit<ViewProps, 'style' | 'children'> {
|
||||
*/
|
||||
priority?: 'low' | 'normal' | 'high' | null;
|
||||
|
||||
+ /**
|
||||
+ * The loading behavior for the image. Maps to the native HTML `loading` attribute on web.
|
||||
+ *
|
||||
+ * - `'lazy'` - Defers loading until the image is near the viewport.
|
||||
+ * - `'eager'` - Loads the image immediately.
|
||||
+ *
|
||||
+ * @default undefined
|
||||
+ * @platform web
|
||||
+ */
|
||||
+ loading?: 'lazy' | 'eager' | null;
|
||||
+
|
||||
/**
|
||||
* Determines whether to cache the image and where: on the disk, in the memory or both.
|
||||
*
|
||||
diff --git a/node_modules/expo-image/src/web/ImageWrapper.tsx b/node_modules/expo-image/src/web/ImageWrapper.tsx
|
||||
index e8f891d..89a5cb1 100644
|
||||
--- a/node_modules/expo-image/src/web/ImageWrapper.tsx
|
||||
+++ b/node_modules/expo-image/src/web/ImageWrapper.tsx
|
||||
@@ -30,6 +30,7 @@ const ImageWrapper = React.forwardRef(
|
||||
contentPosition,
|
||||
hashPlaceholderContentPosition,
|
||||
priority,
|
||||
+ loading,
|
||||
style,
|
||||
hashPlaceholderStyle,
|
||||
tintColor,
|
||||
@@ -82,6 +83,7 @@ const ImageWrapper = React.forwardRef(
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line react/no-unknown-property
|
||||
fetchPriority={getFetchPriorityFromImagePriority(priority || 'normal')}
|
||||
+ loading={loading || undefined}
|
||||
{...getImageWrapperEventHandler(events, sourceWithHeaders)}
|
||||
{...getImgPropsFromSource(source)}
|
||||
{...props}
|
||||
diff --git a/node_modules/expo-image/src/web/ImageWrapper.types.ts b/node_modules/expo-image/src/web/ImageWrapper.types.ts
|
||||
index 19bbe2f..179837f 100644
|
||||
--- a/node_modules/expo-image/src/web/ImageWrapper.types.ts
|
||||
+++ b/node_modules/expo-image/src/web/ImageWrapper.types.ts
|
||||
@@ -29,6 +29,7 @@ export type ImageWrapperProps = {
|
||||
contentPosition?: ImageContentPositionObject;
|
||||
hashPlaceholderContentPosition?: ImageContentPositionObject;
|
||||
priority?: string | null;
|
||||
+ loading?: 'lazy' | 'eager' | null;
|
||||
style: CSSProperties;
|
||||
tintColor?: string | null;
|
||||
hashPlaceholderStyle?: CSSProperties;
|
||||
@@ -1,29 +0,0 @@
|
||||
diff --git a/node_modules/expo-image-picker/ios/MediaHandler.swift b/node_modules/expo-image-picker/ios/MediaHandler.swift
|
||||
index 6e4fbe1..e334abb 100644
|
||||
--- a/node_modules/expo-image-picker/ios/MediaHandler.swift
|
||||
+++ b/node_modules/expo-image-picker/ios/MediaHandler.swift
|
||||
@@ -310,10 +310,12 @@ internal struct MediaHandler {
|
||||
let fileExtension = getFileExtension(from: originalFilename)
|
||||
let destinationUrl = try generateUrl(withFileExtension: fileExtension)
|
||||
|
||||
+ let resourceOptions = PHAssetResourceRequestOptions()
|
||||
+ resourceOptions.isNetworkAccessAllowed = true
|
||||
try await PHAssetResourceManager.default().writeData(
|
||||
for: resource,
|
||||
toFile: destinationUrl,
|
||||
- options: nil
|
||||
+ options: resourceOptions
|
||||
)
|
||||
|
||||
let mimeType = getMimeType(from: destinationUrl.pathExtension)
|
||||
@@ -389,7 +391,9 @@ internal struct MediaHandler {
|
||||
|
||||
// Stream the resource into our cache directory. This API is asynchronous but doesn't require
|
||||
// a temporary file like `loadFileRepresentation`.
|
||||
- try await PHAssetResourceManager.default().writeData(for: resource, toFile: destinationUrl, options: nil)
|
||||
+ let resourceOptions = PHAssetResourceRequestOptions()
|
||||
+ resourceOptions.isNetworkAccessAllowed = true
|
||||
+ try await PHAssetResourceManager.default().writeData(for: resource, toFile: destinationUrl, options: resourceOptions)
|
||||
|
||||
// Build and return the result using the helper.
|
||||
let mimeType = getMimeType(from: destinationUrl.pathExtension)
|
||||
@@ -0,0 +1,3 @@
|
||||
## Expo Image
|
||||
|
||||
Patches in https://github.com/expo/expo/pull/41442
|
||||
@@ -1,13 +0,0 @@
|
||||
diff --git a/node_modules/expo-media-library/android/src/main/java/expo/modules/medialibrary/MediaLibraryModule.kt b/node_modules/expo-media-library/android/src/main/java/expo/modules/medialibrary/MediaLibraryModule.kt
|
||||
index 2dc1db2..ee844e8 100644
|
||||
--- a/node_modules/expo-media-library/android/src/main/java/expo/modules/medialibrary/MediaLibraryModule.kt
|
||||
+++ b/node_modules/expo-media-library/android/src/main/java/expo/modules/medialibrary/MediaLibraryModule.kt
|
||||
@@ -105,7 +105,7 @@ class MediaLibraryModule : Module() {
|
||||
}
|
||||
|
||||
AsyncFunction("createAssetAsync") Coroutine { localUri: String, albumId: String? ->
|
||||
- requireSystemPermissions()
|
||||
+ // requireSystemPermissions()
|
||||
return@Coroutine createAssetWithAlbumId(context, localUri, true, albumId)
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Unclear why this is needed
|
||||
@@ -1,15 +0,0 @@
|
||||
diff --git a/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/devtools/ExpoNetworkInspectOkHttpInterceptors.kt b/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/devtools/ExpoNetworkInspectOkHttpInterceptors.kt
|
||||
index 47c4d15..afe138d 100644
|
||||
--- a/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/devtools/ExpoNetworkInspectOkHttpInterceptors.kt
|
||||
+++ b/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/devtools/ExpoNetworkInspectOkHttpInterceptors.kt
|
||||
@@ -125,6 +125,10 @@ internal fun peekResponseBody(
|
||||
}
|
||||
|
||||
internal fun shouldParseBody(response: Response): Boolean {
|
||||
+ if (response.request.url.encodedPath == "/bitdrift_public.protobuf.client.v1.ApiService/Mux") {
|
||||
+ return false
|
||||
+ }
|
||||
+
|
||||
// Check for Content-Type
|
||||
val skipContentTypes = listOf(
|
||||
"text/event-stream", // Server Sent Events
|
||||
@@ -1,170 +0,0 @@
|
||||
diff --git a/node_modules/expo-notifications/android/build.gradle b/node_modules/expo-notifications/android/build.gradle
|
||||
index bc479ee..1ebfa00 100644
|
||||
--- a/node_modules/expo-notifications/android/build.gradle
|
||||
+++ b/node_modules/expo-notifications/android/build.gradle
|
||||
@@ -42,6 +42,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 191b64e..fe8b3c5 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
|
||||
@@ -35,6 +35,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;
|
||||
@@ -65,6 +66,11 @@ public class NotificationContent implements Parcelable, Serializable, INotificat
|
||||
}
|
||||
};
|
||||
|
||||
+ @Nullable
|
||||
+ public String getChannelId() {
|
||||
+ return mChannelId;
|
||||
+ }
|
||||
+
|
||||
@Nullable
|
||||
public String getTitle() {
|
||||
return mTitle;
|
||||
@@ -158,6 +164,7 @@ public class NotificationContent implements Parcelable, Serializable, INotificat
|
||||
}
|
||||
|
||||
protected NotificationContent(Parcel in) {
|
||||
+ mChannelId = in.readString();
|
||||
mTitle = in.readString();
|
||||
mText = in.readString();
|
||||
mSubtitle = in.readString();
|
||||
@@ -183,6 +190,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);
|
||||
@@ -203,6 +211,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);
|
||||
@@ -285,6 +294,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 3af254c..3c77e9d 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 98f003f..2f745e8 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
|
||||
@@ -101,6 +101,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 90ca4ff..9d4cb09 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
|
||||
@@ -3,6 +3,9 @@ package expo.modules.notifications.service.delegates
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
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
|
||||
@@ -18,7 +21,7 @@ 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
|
||||
@@ -105,8 +108,19 @@ 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(context.applicationContext, RemoteMessageSerializer.toBundle(remoteMessage))
|
||||
+ if (!ExpoBackgroundNotificationHandlerModule.isForegrounded) {
|
||||
+ BackgroundNotificationHandler(context, this).handleMessage(remoteMessage)
|
||||
+ } else {
|
||||
+ NotificationsService.receive(context, notification)
|
||||
+ runTaskManagerTasks(
|
||||
+ context.applicationContext,
|
||||
+ RemoteMessageSerializer.toBundle(remoteMessage)
|
||||
+ )
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ override fun showMessage(remoteMessage: RemoteMessage) {
|
||||
+ NotificationsService.receive(context, createNotification(remoteMessage))
|
||||
}
|
||||
|
||||
protected fun createNotification(remoteMessage: RemoteMessage): Notification {
|
||||
@@ -1,136 +0,0 @@
|
||||
diff --git a/node_modules/expo-paste-input/ios/ExpoPasteInputView.swift b/node_modules/expo-paste-input/ios/ExpoPasteInputView.swift
|
||||
index 2164aec4ec1d..d216db6d2927 100644
|
||||
--- a/node_modules/expo-paste-input/ios/ExpoPasteInputView.swift
|
||||
+++ b/node_modules/expo-paste-input/ios/ExpoPasteInputView.swift
|
||||
@@ -511,14 +511,17 @@ class ExpoPasteInputView: ExpoView {
|
||||
var attachmentRanges: [NSRange] = []
|
||||
var mediaPayloads: [MediaPayload] = []
|
||||
|
||||
+ // Only track ranges for attachments we successfully extract a real payload
|
||||
+ // from. Attachments without a payload (e.g. iOS dictation placeholders)
|
||||
+ // are left alone — sanitizing them would delete characters the system
|
||||
+ // manages itself, and emitting "unsupported" would raise a spurious error.
|
||||
attributedText.enumerateAttribute(.attachment, in: NSRange(location: 0, length: attributedText.length), options: []) { value, range, _ in
|
||||
guard let attachment = value as? NSTextAttachment else {
|
||||
return
|
||||
}
|
||||
|
||||
- attachmentRanges.append(range)
|
||||
-
|
||||
if let payload = self.extractMediaPayload(from: attachment, textView: textView, range: range) {
|
||||
+ attachmentRanges.append(range)
|
||||
mediaPayloads.append(payload)
|
||||
}
|
||||
}
|
||||
@@ -529,9 +532,8 @@ class ExpoPasteInputView: ExpoView {
|
||||
return
|
||||
}
|
||||
|
||||
- attachmentRanges.append(range)
|
||||
-
|
||||
if let payload = self.extractMediaPayload(from: adaptiveGlyph) {
|
||||
+ attachmentRanges.append(range)
|
||||
mediaPayloads.append(payload)
|
||||
}
|
||||
}
|
||||
@@ -539,17 +541,12 @@ class ExpoPasteInputView: ExpoView {
|
||||
|
||||
attachmentRanges = uniqueRanges(attachmentRanges)
|
||||
|
||||
- guard !attachmentRanges.isEmpty else {
|
||||
- return
|
||||
- }
|
||||
-
|
||||
- sanitizeAttachments(in: textView, ranges: attachmentRanges)
|
||||
-
|
||||
guard !mediaPayloads.isEmpty else {
|
||||
- handleUnsupportedPaste()
|
||||
return
|
||||
}
|
||||
|
||||
+ sanitizeAttachments(in: textView, ranges: attachmentRanges)
|
||||
+
|
||||
emitImagesAsync(for: mediaPayloads)
|
||||
}
|
||||
|
||||
@@ -651,6 +648,11 @@ class ExpoPasteInputView: ExpoView {
|
||||
}
|
||||
|
||||
private func extractMediaPayload(from attachment: NSTextAttachment, textView: UITextView, range: NSRange) -> MediaPayload? {
|
||||
+ // Only accept attachments that carry real image payloads. We intentionally
|
||||
+ // do not fall back to `image(forBounds:)` or rendering the text view's
|
||||
+ // hierarchy, because system-inserted attachments (e.g. the iOS dictation
|
||||
+ // placeholder) draw themselves via those paths and would cause us to
|
||||
+ // emit a screenshot of the composer as a "pasted image".
|
||||
if let fileWrapperData = attachment.fileWrapper?.regularFileContents,
|
||||
let payload = extractMediaPayload(fromData: fileWrapperData) {
|
||||
return payload
|
||||
@@ -667,20 +669,6 @@ class ExpoPasteInputView: ExpoView {
|
||||
return .image(image)
|
||||
}
|
||||
|
||||
- let attachmentBounds = attachment.bounds.size.width > 0 && attachment.bounds.size.height > 0
|
||||
- ? attachment.bounds
|
||||
- : CGRect(origin: .zero, size: CGSize(width: 128, height: 128))
|
||||
-
|
||||
- if let image = attachment.image(forBounds: attachmentBounds, textContainer: textView.textContainer, characterIndex: range.location),
|
||||
- image.size.width > 0,
|
||||
- image.size.height > 0 {
|
||||
- return .image(image)
|
||||
- }
|
||||
-
|
||||
- if let renderedImage = renderTextAttachment(in: textView, range: range) {
|
||||
- return .image(renderedImage)
|
||||
- }
|
||||
-
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -701,47 +689,6 @@ class ExpoPasteInputView: ExpoView {
|
||||
return .imageData(data)
|
||||
}
|
||||
|
||||
- private func renderTextAttachment(in textView: UITextView, range: NSRange) -> UIImage? {
|
||||
- let glyphRange = textView.layoutManager.glyphRange(forCharacterRange: range, actualCharacterRange: nil)
|
||||
- var rect = textView.layoutManager.boundingRect(forGlyphRange: glyphRange, in: textView.textContainer)
|
||||
-
|
||||
- rect.origin.x += textView.textContainerInset.left - textView.contentOffset.x
|
||||
- rect.origin.y += textView.textContainerInset.top - textView.contentOffset.y
|
||||
- rect = rect.integral
|
||||
-
|
||||
- guard rect.width > 1, rect.height > 1 else {
|
||||
- return nil
|
||||
- }
|
||||
-
|
||||
- let format = UIGraphicsImageRendererFormat.default()
|
||||
- format.scale = textView.window?.screen.scale ?? UIScreen.main.scale
|
||||
- format.opaque = false
|
||||
-
|
||||
- let image = UIGraphicsImageRenderer(size: rect.size, format: format).image { _ in
|
||||
- let drawRect = CGRect(
|
||||
- origin: CGPoint(x: -rect.origin.x, y: -rect.origin.y),
|
||||
- size: textView.bounds.size
|
||||
- )
|
||||
-
|
||||
- if textView.window != nil {
|
||||
- textView.drawHierarchy(in: drawRect, afterScreenUpdates: false)
|
||||
- } else {
|
||||
- guard let context = UIGraphicsGetCurrentContext() else {
|
||||
- return
|
||||
- }
|
||||
-
|
||||
- context.translateBy(x: -rect.origin.x, y: -rect.origin.y)
|
||||
- textView.layer.render(in: context)
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- guard image.size.width > 0, image.size.height > 0 else {
|
||||
- return nil
|
||||
- }
|
||||
-
|
||||
- return image
|
||||
- }
|
||||
-
|
||||
@available(iOS 18.0, *)
|
||||
private func handleAdaptiveImageGlyphInsertion(_ adaptiveGlyph: NSAdaptiveImageGlyph) -> Bool {
|
||||
guard let payload = extractMediaPayload(from: adaptiveGlyph) else {
|
||||
@@ -1,22 +0,0 @@
|
||||
# Expo Paste Input Patch
|
||||
|
||||
`expo-paste-input` observes `UITextView.textDidChangeNotification` and treats any
|
||||
`NSTextAttachment` in the text view's `attributedText` as a pasted image. When
|
||||
it can't find a real image payload on an attachment, it falls back to
|
||||
`image(forBounds:)` and, failing that, to a `drawHierarchy` screenshot of the
|
||||
text view at the attachment's glyph rect.
|
||||
|
||||
iOS Dictation inserts its own `NSTextAttachment` (the shimmer/cursor indicator)
|
||||
into the text view during dictation. Those attachments don't carry real image
|
||||
data, so the fallbacks would fire — emitting a zoomed-in screenshot of the
|
||||
composer as if the user had pasted an image at the end of dictation.
|
||||
|
||||
This patch:
|
||||
|
||||
- Removes the `image(forBounds:)` and `renderTextAttachment` fallbacks in
|
||||
`extractMediaPayload` so the library only accepts attachments carrying a real
|
||||
payload (`fileWrapper`, `contents`, or `image`).
|
||||
- Only sanitizes (deletes) attachment ranges that produced a payload, and
|
||||
skips the "unsupported" toast when an attachment has no payload. Unknown
|
||||
system attachments like the dictation placeholder are left alone rather
|
||||
than being ripped out from under iOS.
|
||||
@@ -1,135 +0,0 @@
|
||||
diff --git a/ios/ExpoPasteInputView.swift b/ios/ExpoPasteInputView.swift
|
||||
index 2164aec4ec1d8380fd690850aec0931e4f65194d..d216db6d2927c9cbb1eb5e10783ff1cc83c103e7 100644
|
||||
--- a/ios/ExpoPasteInputView.swift
|
||||
+++ b/ios/ExpoPasteInputView.swift
|
||||
@@ -511,14 +511,17 @@ class ExpoPasteInputView: ExpoView {
|
||||
var attachmentRanges: [NSRange] = []
|
||||
var mediaPayloads: [MediaPayload] = []
|
||||
|
||||
+ // Only track ranges for attachments we successfully extract a real payload
|
||||
+ // from. Attachments without a payload (e.g. iOS dictation placeholders)
|
||||
+ // are left alone — sanitizing them would delete characters the system
|
||||
+ // manages itself, and emitting "unsupported" would raise a spurious error.
|
||||
attributedText.enumerateAttribute(.attachment, in: NSRange(location: 0, length: attributedText.length), options: []) { value, range, _ in
|
||||
guard let attachment = value as? NSTextAttachment else {
|
||||
return
|
||||
}
|
||||
|
||||
- attachmentRanges.append(range)
|
||||
-
|
||||
if let payload = self.extractMediaPayload(from: attachment, textView: textView, range: range) {
|
||||
+ attachmentRanges.append(range)
|
||||
mediaPayloads.append(payload)
|
||||
}
|
||||
}
|
||||
@@ -529,9 +532,8 @@ class ExpoPasteInputView: ExpoView {
|
||||
return
|
||||
}
|
||||
|
||||
- attachmentRanges.append(range)
|
||||
-
|
||||
if let payload = self.extractMediaPayload(from: adaptiveGlyph) {
|
||||
+ attachmentRanges.append(range)
|
||||
mediaPayloads.append(payload)
|
||||
}
|
||||
}
|
||||
@@ -539,17 +541,12 @@ class ExpoPasteInputView: ExpoView {
|
||||
|
||||
attachmentRanges = uniqueRanges(attachmentRanges)
|
||||
|
||||
- guard !attachmentRanges.isEmpty else {
|
||||
+ guard !mediaPayloads.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
sanitizeAttachments(in: textView, ranges: attachmentRanges)
|
||||
|
||||
- guard !mediaPayloads.isEmpty else {
|
||||
- handleUnsupportedPaste()
|
||||
- return
|
||||
- }
|
||||
-
|
||||
emitImagesAsync(for: mediaPayloads)
|
||||
}
|
||||
|
||||
@@ -651,6 +648,11 @@ class ExpoPasteInputView: ExpoView {
|
||||
}
|
||||
|
||||
private func extractMediaPayload(from attachment: NSTextAttachment, textView: UITextView, range: NSRange) -> MediaPayload? {
|
||||
+ // Only accept attachments that carry real image payloads. We intentionally
|
||||
+ // do not fall back to `image(forBounds:)` or rendering the text view's
|
||||
+ // hierarchy, because system-inserted attachments (e.g. the iOS dictation
|
||||
+ // placeholder) draw themselves via those paths and would cause us to
|
||||
+ // emit a screenshot of the composer as a "pasted image".
|
||||
if let fileWrapperData = attachment.fileWrapper?.regularFileContents,
|
||||
let payload = extractMediaPayload(fromData: fileWrapperData) {
|
||||
return payload
|
||||
@@ -667,20 +669,6 @@ class ExpoPasteInputView: ExpoView {
|
||||
return .image(image)
|
||||
}
|
||||
|
||||
- let attachmentBounds = attachment.bounds.size.width > 0 && attachment.bounds.size.height > 0
|
||||
- ? attachment.bounds
|
||||
- : CGRect(origin: .zero, size: CGSize(width: 128, height: 128))
|
||||
-
|
||||
- if let image = attachment.image(forBounds: attachmentBounds, textContainer: textView.textContainer, characterIndex: range.location),
|
||||
- image.size.width > 0,
|
||||
- image.size.height > 0 {
|
||||
- return .image(image)
|
||||
- }
|
||||
-
|
||||
- if let renderedImage = renderTextAttachment(in: textView, range: range) {
|
||||
- return .image(renderedImage)
|
||||
- }
|
||||
-
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -701,47 +689,6 @@ class ExpoPasteInputView: ExpoView {
|
||||
return .imageData(data)
|
||||
}
|
||||
|
||||
- private func renderTextAttachment(in textView: UITextView, range: NSRange) -> UIImage? {
|
||||
- let glyphRange = textView.layoutManager.glyphRange(forCharacterRange: range, actualCharacterRange: nil)
|
||||
- var rect = textView.layoutManager.boundingRect(forGlyphRange: glyphRange, in: textView.textContainer)
|
||||
-
|
||||
- rect.origin.x += textView.textContainerInset.left - textView.contentOffset.x
|
||||
- rect.origin.y += textView.textContainerInset.top - textView.contentOffset.y
|
||||
- rect = rect.integral
|
||||
-
|
||||
- guard rect.width > 1, rect.height > 1 else {
|
||||
- return nil
|
||||
- }
|
||||
-
|
||||
- let format = UIGraphicsImageRendererFormat.default()
|
||||
- format.scale = textView.window?.screen.scale ?? UIScreen.main.scale
|
||||
- format.opaque = false
|
||||
-
|
||||
- let image = UIGraphicsImageRenderer(size: rect.size, format: format).image { _ in
|
||||
- let drawRect = CGRect(
|
||||
- origin: CGPoint(x: -rect.origin.x, y: -rect.origin.y),
|
||||
- size: textView.bounds.size
|
||||
- )
|
||||
-
|
||||
- if textView.window != nil {
|
||||
- textView.drawHierarchy(in: drawRect, afterScreenUpdates: false)
|
||||
- } else {
|
||||
- guard let context = UIGraphicsGetCurrentContext() else {
|
||||
- return
|
||||
- }
|
||||
-
|
||||
- context.translateBy(x: -rect.origin.x, y: -rect.origin.y)
|
||||
- textView.layer.render(in: context)
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- guard image.size.width > 0, image.size.height > 0 else {
|
||||
- return nil
|
||||
- }
|
||||
-
|
||||
- return image
|
||||
- }
|
||||
-
|
||||
@available(iOS 18.0, *)
|
||||
private func handleAdaptiveImageGlyphInsertion(_ adaptiveGlyph: NSAdaptiveImageGlyph) -> Bool {
|
||||
guard let payload = extractMediaPayload(from: adaptiveGlyph) else {
|
||||
@@ -1,26 +0,0 @@
|
||||
diff --git a/node_modules/expo-updates/ios/EXUpdates/Update/ExpoUpdatesUpdate.swift b/node_modules/expo-updates/ios/EXUpdates/Update/ExpoUpdatesUpdate.swift
|
||||
index 68086bd..78c7761 100644
|
||||
--- a/node_modules/expo-updates/ios/EXUpdates/Update/ExpoUpdatesUpdate.swift
|
||||
+++ b/node_modules/expo-updates/ios/EXUpdates/Update/ExpoUpdatesUpdate.swift
|
||||
@@ -78,13 +78,20 @@ public final class ExpoUpdatesUpdate: Update {
|
||||
status = UpdateStatus.StatusPending
|
||||
}
|
||||
|
||||
+ // Instead of relying on various hacks to get the correct format for the specific
|
||||
+ // platform on the backend, we can just add this little patch..
|
||||
+ let dateFormatter = DateFormatter()
|
||||
+ dateFormatter.locale = Locale(identifier: "en_US_POSIX")
|
||||
+ dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
||||
+ let date = dateFormatter.date(from:commitTime) ?? RCTConvert.nsDate(commitTime)!
|
||||
+
|
||||
return Update(
|
||||
manifest: manifest,
|
||||
config: config,
|
||||
database: database,
|
||||
updateId: uuid,
|
||||
scopeKey: config.scopeKey,
|
||||
- commitTime: RCTConvert.nsDate(commitTime),
|
||||
+ commitTime: date,
|
||||
runtimeVersion: runtimeVersion,
|
||||
keep: true,
|
||||
status: status,
|
||||
@@ -1,71 +0,0 @@
|
||||
diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
index e9b330f..5fbb2e0 100644
|
||||
--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
@@ -15,5 +15,6 @@
|
||||
@property (nonatomic, copy) NSString *title;
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onRefresh;
|
||||
@property (nonatomic, weak) UIScrollView *scrollView;
|
||||
+@property (nonatomic, copy) UIColor *customTintColor;
|
||||
|
||||
@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..e2e0c9f 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,16 @@ - (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];
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
@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) {
|
||||
@@ -1,67 +0,0 @@
|
||||
diff --git a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h
|
||||
index 914a249..0deac55 100644
|
||||
--- a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h
|
||||
+++ b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.h
|
||||
@@ -19,6 +19,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@interface RCTPullToRefreshViewComponentView : RCTViewComponentView <RCTCustomPullToRefreshViewProtocol>
|
||||
|
||||
+- (void)beginRefreshingProgrammatically;
|
||||
+
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
diff --git a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
index 5fbb2e0..ec5f58c 100644
|
||||
--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.h
|
||||
@@ -17,4 +17,6 @@
|
||||
@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 e2e0c9f..ff1b1ed 100644
|
||||
--- a/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m
|
||||
+++ b/node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.m
|
||||
@@ -240,4 +240,38 @@ - (void)setTintColor:(UIColor *)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
|
||||
@@ -1,16 +0,0 @@
|
||||
diff --git a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm
|
||||
index d029337..0f63ea3 100644
|
||||
--- a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm
|
||||
+++ b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm
|
||||
@@ -1038,6 +1038,11 @@ - (void)_adjustForMaintainVisibleContentPosition
|
||||
}
|
||||
}
|
||||
|
||||
++ (BOOL)shouldBeRecycled
|
||||
+{
|
||||
+ return NO;
|
||||
+}
|
||||
+
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTScrollViewCls(void)
|
||||
@@ -1,16 +0,0 @@
|
||||
diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.kt b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.kt
|
||||
index 8b65716..27c97bf 100644
|
||||
--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.kt
|
||||
+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.kt
|
||||
@@ -313,8 +313,9 @@ public open class JavaTimerManager(
|
||||
// We also capture the idleCallbackRunnable to tentatively fix:
|
||||
// https://github.com/facebook/react-native/issues/44842
|
||||
currentIdleCallbackRunnable?.cancel()
|
||||
- currentIdleCallbackRunnable = IdleCallbackRunnable(frameTimeNanos)
|
||||
- reactApplicationContext.runOnJSQueueThread(currentIdleCallbackRunnable)
|
||||
+ val idleCallbackRunnable = IdleCallbackRunnable(frameTimeNanos)
|
||||
+ currentIdleCallbackRunnable = idleCallbackRunnable
|
||||
+ reactApplicationContext.runOnJSQueueThread(idleCallbackRunnable)
|
||||
reactChoreographer.postFrameCallback(ReactChoreographer.CallbackType.IDLE_EVENT, this)
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
diff --git a/node_modules/react-native/third-party-podspecs/fmt.podspec b/node_modules/react-native/third-party-podspecs/fmt.podspec
|
||||
index 2f38990..9b02e48 100644
|
||||
--- a/node_modules/react-native/third-party-podspecs/fmt.podspec
|
||||
+++ b/node_modules/react-native/third-party-podspecs/fmt.podspec
|
||||
@@ -26,4 +26,11 @@ Pod::Spec.new do |spec|
|
||||
spec.public_header_files = "include/fmt/*.h"
|
||||
spec.header_mappings_dir = "include"
|
||||
spec.source_files = ["include/fmt/*.h", "src/format.cc"]
|
||||
+
|
||||
+ # TODO: Remove after upgrading React Native past 0.83.x
|
||||
+ # Fix fmt 11.0.2 consteval build error with Xcode 26.4 (facebook/react-native#55601)
|
||||
+ # Fixed in RN 0.84+ which bumps fmt to a compatible version.
|
||||
+ spec.prepare_command = <<~SCRIPT
|
||||
+ perl -i -pe 's/^# define FMT_USE_CONSTEVAL 1$/# define FMT_USE_CONSTEVAL 0/' include/fmt/base.h
|
||||
+ SCRIPT
|
||||
end
|
||||
@@ -1,516 +0,0 @@
|
||||
diff --git a/node_modules/react-native-compressor/android/build.gradle b/node_modules/react-native-compressor/android/build.gradle
|
||||
index 5071139..84bee34 100644
|
||||
--- a/node_modules/react-native-compressor/android/build.gradle
|
||||
+++ b/node_modules/react-native-compressor/android/build.gradle
|
||||
@@ -115,7 +115,6 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
|
||||
implementation 'org.mp4parser:isoparser:1.9.56'
|
||||
- implementation 'com.github.banketree:AndroidLame-kotlin:v0.0.1'
|
||||
implementation 'javazoom:jlayer:1.0.1'
|
||||
}
|
||||
|
||||
diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt
|
||||
deleted file mode 100644
|
||||
index 9292d3e..0000000
|
||||
--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt
|
||||
+++ /dev/null
|
||||
@@ -1,264 +0,0 @@
|
||||
-package com.reactnativecompressor.Audio
|
||||
-
|
||||
-
|
||||
-import android.annotation.SuppressLint
|
||||
-import com.facebook.react.bridge.Promise
|
||||
-import com.facebook.react.bridge.ReactApplicationContext
|
||||
-import com.facebook.react.bridge.ReadableMap
|
||||
-import com.naman14.androidlame.LameBuilder
|
||||
-import com.naman14.androidlame.WaveReader
|
||||
-import com.reactnativecompressor.Utils.MediaCache
|
||||
-import com.reactnativecompressor.Utils.Utils
|
||||
-import com.reactnativecompressor.Utils.Utils.addLog
|
||||
-import javazoom.jl.converter.Converter
|
||||
-import javazoom.jl.decoder.JavaLayerException
|
||||
-import java.io.BufferedOutputStream
|
||||
-import java.io.File
|
||||
-import java.io.FileNotFoundException
|
||||
-import java.io.FileOutputStream
|
||||
-import java.io.IOException
|
||||
-
|
||||
-class AudioCompressor {
|
||||
- companion object {
|
||||
- val TAG="AudioMain"
|
||||
- private const val OUTPUT_STREAM_BUFFER = 8192
|
||||
-
|
||||
- var outputStream: BufferedOutputStream? = null
|
||||
- var waveReader: WaveReader? = null
|
||||
- @JvmStatic
|
||||
- fun CompressAudio(
|
||||
- fileUrl: String,
|
||||
- optionMap: ReadableMap,
|
||||
- context: ReactApplicationContext,
|
||||
- promise: Promise,
|
||||
- ) {
|
||||
- val realPath = Utils.getRealPath(fileUrl, context)
|
||||
- var _fileUrl=realPath
|
||||
- val filePathWithoutFileUri = realPath!!.replace("file://", "")
|
||||
- try {
|
||||
- var wavPath=filePathWithoutFileUri;
|
||||
- var isNonWav:Boolean=false
|
||||
- if (fileUrl.endsWith(".mp4", ignoreCase = true))
|
||||
- {
|
||||
- addLog("mp4 file found")
|
||||
- val mp3Path= Utils.generateCacheFilePath("mp3", context)
|
||||
- AudioExtractor().genVideoUsingMuxer(fileUrl, mp3Path, -1, -1, true, false)
|
||||
- _fileUrl=Utils.slashifyFilePath(mp3Path)
|
||||
- wavPath= Utils.generateCacheFilePath("wav", context)
|
||||
- try {
|
||||
- val converter = Converter()
|
||||
- converter.convert(mp3Path, wavPath)
|
||||
- } catch (e: JavaLayerException) {
|
||||
- addLog("JavaLayerException error"+e.localizedMessage)
|
||||
- e.printStackTrace();
|
||||
- }
|
||||
- isNonWav=true
|
||||
- }
|
||||
- else if (!fileUrl.endsWith(".wav", ignoreCase = true))
|
||||
- {
|
||||
- addLog("non wav file found")
|
||||
- wavPath= Utils.generateCacheFilePath("wav", context)
|
||||
- try {
|
||||
- val converter = Converter()
|
||||
- converter.convert(filePathWithoutFileUri, wavPath)
|
||||
- } catch (e: JavaLayerException) {
|
||||
- addLog("JavaLayerException error"+e.localizedMessage)
|
||||
- e.printStackTrace();
|
||||
- }
|
||||
- isNonWav=true
|
||||
- }
|
||||
-
|
||||
-
|
||||
- autoCompressHelper(wavPath,filePathWithoutFileUri, optionMap,context) { mp3Path, finished ->
|
||||
- if (finished) {
|
||||
- val returnableFilePath:String="file://$mp3Path"
|
||||
- addLog("finished: " + returnableFilePath)
|
||||
- MediaCache.removeCompletedImagePath(fileUrl)
|
||||
- if(isNonWav)
|
||||
- {
|
||||
- File(wavPath).delete()
|
||||
- }
|
||||
- promise.resolve(returnableFilePath)
|
||||
- } else {
|
||||
- addLog("error: "+mp3Path)
|
||||
- promise.resolve(_fileUrl)
|
||||
- }
|
||||
- }
|
||||
- } catch (e: Exception) {
|
||||
- promise.resolve(_fileUrl)
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- @SuppressLint("WrongConstant")
|
||||
- private fun autoCompressHelper(
|
||||
- fileUrl: String,
|
||||
- actualFileUrl: String,
|
||||
- optionMap: ReadableMap,
|
||||
- context: ReactApplicationContext,
|
||||
- completeCallback: (String, Boolean) -> Unit
|
||||
- ) {
|
||||
-
|
||||
- val options = AudioHelper.fromMap(optionMap)
|
||||
- val quality = options.quality
|
||||
-
|
||||
- var isCompletedCallbackTriggered:Boolean=false
|
||||
- try {
|
||||
- var mp3Path = Utils.generateCacheFilePath("mp3", context)
|
||||
- val input = File(fileUrl)
|
||||
- val output = File(mp3Path)
|
||||
-
|
||||
- val CHUNK_SIZE = 8192
|
||||
- addLog("Initialising wav reader")
|
||||
-
|
||||
- waveReader = WaveReader(input)
|
||||
-
|
||||
- try {
|
||||
- waveReader!!.openWave()
|
||||
- } catch (e: IOException) {
|
||||
- e.printStackTrace()
|
||||
- }
|
||||
-
|
||||
- addLog("Intitialising encoder")
|
||||
-
|
||||
-
|
||||
- // for bitrate
|
||||
- var audioBitrate:Int
|
||||
- if(options.bitrate != -1)
|
||||
- {
|
||||
- audioBitrate= options.bitrate/1000
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- audioBitrate=AudioHelper.getDestinationBitrateByQuality(actualFileUrl, quality!!)
|
||||
- Utils.addLog("dest bitrate: $audioBitrate")
|
||||
- }
|
||||
-
|
||||
- var androidLame = LameBuilder();
|
||||
- androidLame.setOutBitrate(audioBitrate)
|
||||
-
|
||||
- // for channels
|
||||
- var audioChannels:Int
|
||||
- if(options.channels != -1){
|
||||
- audioChannels= options.channels!!
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- audioChannels=waveReader!!.channels
|
||||
- }
|
||||
- androidLame.setOutChannels(audioChannels)
|
||||
-
|
||||
- // for sample rate
|
||||
- androidLame.setInSampleRate(waveReader!!.sampleRate)
|
||||
- var audioSampleRate:Int
|
||||
- if(options.samplerate != -1){
|
||||
- audioSampleRate= options.samplerate!!
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- audioSampleRate=waveReader!!.sampleRate
|
||||
- }
|
||||
- androidLame.setOutSampleRate(audioSampleRate)
|
||||
- val androidLameBuild=androidLame.build()
|
||||
-
|
||||
- try {
|
||||
- outputStream = BufferedOutputStream(FileOutputStream(output), OUTPUT_STREAM_BUFFER)
|
||||
- } catch (e: FileNotFoundException) {
|
||||
- e.printStackTrace()
|
||||
- }
|
||||
-
|
||||
- var bytesRead = 0
|
||||
-
|
||||
- val buffer_l = ShortArray(CHUNK_SIZE)
|
||||
- val buffer_r = ShortArray(CHUNK_SIZE)
|
||||
- val mp3Buf = ByteArray(CHUNK_SIZE)
|
||||
-
|
||||
- val channels = waveReader!!.channels
|
||||
-
|
||||
- addLog("started encoding")
|
||||
- while (true) {
|
||||
- try {
|
||||
- if (channels == 2) {
|
||||
-
|
||||
- bytesRead = waveReader!!.read(buffer_l, buffer_r, CHUNK_SIZE)
|
||||
- addLog("bytes read=$bytesRead")
|
||||
-
|
||||
- if (bytesRead > 0) {
|
||||
-
|
||||
- var bytesEncoded = 0
|
||||
- bytesEncoded = androidLameBuild.encode(buffer_l, buffer_r, bytesRead, mp3Buf)
|
||||
- addLog("bytes encoded=$bytesEncoded")
|
||||
-
|
||||
- if (bytesEncoded > 0) {
|
||||
- try {
|
||||
- addLog("writing mp3 buffer to outputstream with $bytesEncoded bytes")
|
||||
- outputStream!!.write(mp3Buf, 0, bytesEncoded)
|
||||
- } catch (e: IOException) {
|
||||
- e.printStackTrace()
|
||||
- }
|
||||
-
|
||||
- }
|
||||
-
|
||||
- } else
|
||||
- break
|
||||
- } else {
|
||||
-
|
||||
- bytesRead = waveReader!!.read(buffer_l, CHUNK_SIZE)
|
||||
- addLog("bytes read=$bytesRead")
|
||||
-
|
||||
- if (bytesRead > 0) {
|
||||
- var bytesEncoded = 0
|
||||
-
|
||||
- bytesEncoded = androidLameBuild.encode(buffer_l, buffer_l, bytesRead, mp3Buf)
|
||||
- addLog("bytes encoded=$bytesEncoded")
|
||||
-
|
||||
- if (bytesEncoded > 0) {
|
||||
- try {
|
||||
- addLog("writing mp3 buffer to outputstream with $bytesEncoded bytes")
|
||||
- outputStream!!.write(mp3Buf, 0, bytesEncoded)
|
||||
- } catch (e: IOException) {
|
||||
- e.printStackTrace()
|
||||
- }
|
||||
-
|
||||
- }
|
||||
-
|
||||
- } else
|
||||
- break
|
||||
- }
|
||||
-
|
||||
-
|
||||
- } catch (e: IOException) {
|
||||
- e.printStackTrace()
|
||||
- }
|
||||
-
|
||||
- }
|
||||
-
|
||||
- addLog("flushing final mp3buffer")
|
||||
- val outputMp3buf = androidLameBuild.flush(mp3Buf)
|
||||
- addLog("flushed $outputMp3buf bytes")
|
||||
- if (outputMp3buf > 0) {
|
||||
- try {
|
||||
- addLog("writing final mp3buffer to outputstream")
|
||||
- outputStream!!.write(mp3Buf, 0, outputMp3buf)
|
||||
- addLog("closing output stream")
|
||||
- outputStream!!.close()
|
||||
- completeCallback(output.absolutePath, true)
|
||||
- isCompletedCallbackTriggered=true
|
||||
- } catch (e: IOException) {
|
||||
- completeCallback(e.localizedMessage, false)
|
||||
- e.printStackTrace()
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- } catch (e: IOException) {
|
||||
- completeCallback(e.localizedMessage, false)
|
||||
- }
|
||||
- if(!isCompletedCallbackTriggered)
|
||||
- {
|
||||
- completeCallback("something went wrong", false)
|
||||
- }
|
||||
- }
|
||||
-
|
||||
-
|
||||
-
|
||||
- }
|
||||
-}
|
||||
diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioExtractor.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioExtractor.kt
|
||||
deleted file mode 100644
|
||||
index c655182..0000000
|
||||
--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioExtractor.kt
|
||||
+++ /dev/null
|
||||
@@ -1,112 +0,0 @@
|
||||
-package com.reactnativecompressor.Audio
|
||||
-
|
||||
-import android.annotation.SuppressLint
|
||||
-import android.media.MediaCodec
|
||||
-import android.media.MediaExtractor
|
||||
-import android.media.MediaFormat
|
||||
-import android.media.MediaMetadataRetriever
|
||||
-import android.media.MediaMuxer
|
||||
-import android.util.Log
|
||||
-import java.io.IOException
|
||||
-import java.nio.ByteBuffer
|
||||
-
|
||||
-
|
||||
-class AudioExtractor {
|
||||
- /**
|
||||
- * @param srcPath the path of source video file.
|
||||
- * @param dstPath the path of destination video file.
|
||||
- * @param startMs starting time in milliseconds for trimming. Set to
|
||||
- * negative if starting from beginning.
|
||||
- * @param endMs end time for trimming in milliseconds. Set to negative if
|
||||
- * no trimming at the end.
|
||||
- * @param useAudio true if keep the audio track from the source.
|
||||
- * @param useVideo true if keep the video track from the source.
|
||||
- * @throws IOException
|
||||
- */
|
||||
- @SuppressLint("NewApi", "WrongConstant")
|
||||
- @Throws(IOException::class)
|
||||
- fun genVideoUsingMuxer(srcPath: String?, dstPath: String?, startMs: Int, endMs: Int, useAudio: Boolean, useVideo: Boolean) {
|
||||
- // Set up MediaExtractor to read from the source.
|
||||
- val extractor = MediaExtractor()
|
||||
- extractor.setDataSource(srcPath!!)
|
||||
- val trackCount = extractor.trackCount
|
||||
- // Set up MediaMuxer for the destination.
|
||||
- val muxer: MediaMuxer
|
||||
- muxer = MediaMuxer(dstPath!!, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
|
||||
- // Set up the tracks and retrieve the max buffer size for selected
|
||||
- // tracks.
|
||||
- val indexMap = HashMap<Int, Int>(trackCount)
|
||||
- var bufferSize = -1
|
||||
- for (i in 0 until trackCount) {
|
||||
- val format = extractor.getTrackFormat(i)
|
||||
- val mime = format.getString(MediaFormat.KEY_MIME)
|
||||
- var selectCurrentTrack = false
|
||||
- if (mime!!.startsWith("audio/") && useAudio) {
|
||||
- selectCurrentTrack = true
|
||||
- } else if (mime.startsWith("video/") && useVideo) {
|
||||
- selectCurrentTrack = true
|
||||
- }
|
||||
- if (selectCurrentTrack) {
|
||||
- extractor.selectTrack(i)
|
||||
- val dstIndex = muxer.addTrack(format)
|
||||
- indexMap[i] = dstIndex
|
||||
- if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
|
||||
- val newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE)
|
||||
- bufferSize = if (newSize > bufferSize) newSize else bufferSize
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- if (bufferSize < 0) {
|
||||
- bufferSize = DEFAULT_BUFFER_SIZE
|
||||
- }
|
||||
- // Set up the orientation and starting time for extractor.
|
||||
- val retrieverSrc = MediaMetadataRetriever()
|
||||
- retrieverSrc.setDataSource(srcPath)
|
||||
- val degreesString = retrieverSrc.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)
|
||||
- if (degreesString != null) {
|
||||
- val degrees = degreesString.toInt()
|
||||
- if (degrees >= 0) {
|
||||
- muxer.setOrientationHint(degrees)
|
||||
- }
|
||||
- }
|
||||
- if (startMs > 0) {
|
||||
- extractor.seekTo((startMs * 1000).toLong(), MediaExtractor.SEEK_TO_CLOSEST_SYNC)
|
||||
- }
|
||||
- // Copy the samples from MediaExtractor to MediaMuxer. We will loop
|
||||
- // for copying each sample and stop when we get to the end of the source
|
||||
- // file or exceed the end time of the trimming.
|
||||
- val offset = 0
|
||||
- var trackIndex = -1
|
||||
- val dstBuf = ByteBuffer.allocate(bufferSize)
|
||||
- val bufferInfo = MediaCodec.BufferInfo()
|
||||
- muxer.start()
|
||||
- while (true) {
|
||||
- bufferInfo.offset = offset
|
||||
- bufferInfo.size = extractor.readSampleData(dstBuf, offset)
|
||||
- if (bufferInfo.size < 0) {
|
||||
- Log.d(TAG, "Saw input EOS.")
|
||||
- bufferInfo.size = 0
|
||||
- break
|
||||
- } else {
|
||||
- bufferInfo.presentationTimeUs = extractor.sampleTime
|
||||
- if (endMs > 0 && bufferInfo.presentationTimeUs > endMs * 1000) {
|
||||
- Log.d(TAG, "The current sample is over the trim end time.")
|
||||
- break
|
||||
- } else {
|
||||
- bufferInfo.flags = extractor.sampleFlags
|
||||
- trackIndex = extractor.sampleTrackIndex
|
||||
- muxer.writeSampleData(indexMap[trackIndex]!!, dstBuf, bufferInfo)
|
||||
- extractor.advance()
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- muxer.stop()
|
||||
- muxer.release()
|
||||
- return
|
||||
- }
|
||||
-
|
||||
- companion object {
|
||||
- private const val DEFAULT_BUFFER_SIZE = 1 * 1024 * 1024
|
||||
- private const val TAG = "AudioExtractorDecoder"
|
||||
- }
|
||||
-}
|
||||
diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioHelper.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioHelper.kt
|
||||
deleted file mode 100644
|
||||
index 42040b4..0000000
|
||||
--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioHelper.kt
|
||||
+++ /dev/null
|
||||
@@ -1,72 +0,0 @@
|
||||
-package com.reactnativecompressor.Audio
|
||||
-
|
||||
-import android.media.MediaExtractor
|
||||
-import android.media.MediaFormat
|
||||
-import com.facebook.react.bridge.ReadableMap
|
||||
-import com.reactnativecompressor.Utils.Utils
|
||||
-import java.io.File
|
||||
-import java.io.IOException
|
||||
-
|
||||
-
|
||||
-class AudioHelper {
|
||||
-
|
||||
- var quality: String? = "medium"
|
||||
- var bitrate: Int = -1
|
||||
- var samplerate: Int = -1
|
||||
- var channels: Int = -1
|
||||
- var progressDivider: Int? = 0
|
||||
-
|
||||
- companion object {
|
||||
- fun fromMap(map: ReadableMap): AudioHelper {
|
||||
- val options = AudioHelper()
|
||||
- val iterator = map.keySetIterator()
|
||||
- while (iterator.hasNextKey()) {
|
||||
- val key = iterator.nextKey()
|
||||
- when (key) {
|
||||
- "quality" -> options.quality = map.getString(key)
|
||||
- "bitrate" -> {
|
||||
- val bitrate = map.getInt(key)
|
||||
- options.bitrate = if (bitrate > 320000 || bitrate < 64000) 64000 else bitrate
|
||||
- }
|
||||
- "samplerate" -> options.samplerate = map.getInt(key)
|
||||
- "channels" -> options.channels = map.getInt(key)
|
||||
- }
|
||||
- }
|
||||
- return options
|
||||
- }
|
||||
-
|
||||
-
|
||||
- fun getAudioBitrate(path: String): Int {
|
||||
- val file = File(path)
|
||||
- val fileSize = file.length() * 8 // size in bits
|
||||
-
|
||||
- val mex = MediaExtractor()
|
||||
- try {
|
||||
- mex.setDataSource(path)
|
||||
- } catch (e: IOException) {
|
||||
- e.printStackTrace()
|
||||
- }
|
||||
-
|
||||
- val mf = mex.getTrackFormat(0)
|
||||
- val durationUs = mf.getLong(MediaFormat.KEY_DURATION)
|
||||
- val durationSec = durationUs / 1_000_000.0 // convert duration to seconds
|
||||
-
|
||||
- return (fileSize / durationSec).toInt()/1000 // bitrate in bits per second
|
||||
- }
|
||||
- fun getDestinationBitrateByQuality(path: String, quality: String): Int {
|
||||
- val originalBitrate = getAudioBitrate(path)
|
||||
- var destinationBitrate = originalBitrate
|
||||
- Utils.addLog("source bitrate: $originalBitrate")
|
||||
-
|
||||
- when (quality.lowercase()) {
|
||||
- "low" -> destinationBitrate = maxOf(64, (originalBitrate * 0.3).toInt())
|
||||
- "medium" -> destinationBitrate = (originalBitrate * 0.5).toInt()
|
||||
- "high" -> destinationBitrate = minOf(320, (originalBitrate * 0.7).toInt())
|
||||
- else -> Utils.addLog("Invalid quality level. Please enter 'low', 'medium', or 'high'.")
|
||||
- }
|
||||
-
|
||||
- return destinationBitrate
|
||||
- }
|
||||
-
|
||||
- }
|
||||
-}
|
||||
diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt
|
||||
index 446d4fb..f021909 100644
|
||||
--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt
|
||||
+++ b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt
|
||||
@@ -11,7 +11,9 @@ class AudioMain(private val reactContext: ReactApplicationContext) {
|
||||
promise: Promise) {
|
||||
try {
|
||||
|
||||
- AudioCompressor.CompressAudio(fileUrl,optionMap,reactContext,promise)
|
||||
+ // Skip compression on Android to avoid libandroidlame dependency
|
||||
+ // Return the original file URL without compression
|
||||
+ promise.resolve(fileUrl)
|
||||
} catch (ex: Exception) {
|
||||
promise.reject(ex)
|
||||
}
|
||||
diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt
|
||||
index c14b727..1198908 100644
|
||||
--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt
|
||||
+++ b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt
|
||||
@@ -7,7 +7,6 @@ import android.provider.OpenableColumns
|
||||
import android.util.Log
|
||||
import com.facebook.react.bridge.Promise
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
-import com.reactnativecompressor.Audio.AudioCompressor
|
||||
import com.reactnativecompressor.Video.VideoCompressor.CompressionListener
|
||||
import com.reactnativecompressor.Video.VideoCompressor.VideoCompressorClass
|
||||
import java.io.FileNotFoundException
|
||||
@@ -152,10 +151,6 @@ object Utils {
|
||||
}
|
||||
}
|
||||
|
||||
- fun addLog(log: String) {
|
||||
- Log.d(AudioCompressor.TAG, log)
|
||||
- }
|
||||
-
|
||||
val exifAttributes = arrayOf(
|
||||
"FNumber",
|
||||
"ApertureValue",
|
||||
@@ -1,17 +0,0 @@
|
||||
diff --git a/node_modules/react-native-date-picker/ios/RNDatePicker.h b/node_modules/react-native-date-picker/ios/RNDatePicker.h
|
||||
index 480746e..470dc3a 100644
|
||||
--- a/node_modules/react-native-date-picker/ios/RNDatePicker.h
|
||||
+++ b/node_modules/react-native-date-picker/ios/RNDatePicker.h
|
||||
@@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_END
|
||||
#else
|
||||
#import "DatePicker.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
+#include <string>
|
||||
|
||||
@interface RNDatePicker : DatePicker
|
||||
|
||||
@@ -22,4 +23,3 @@ NS_ASSUME_NONNULL_END
|
||||
@end
|
||||
|
||||
#endif
|
||||
-
|
||||
@@ -1,38 +0,0 @@
|
||||
diff --git a/node_modules/react-native-drawer-layout/lib/module/views/Drawer.native.js b/node_modules/react-native-drawer-layout/lib/module/views/Drawer.native.js
|
||||
index 40fdcdb..770fd67 100644
|
||||
--- a/node_modules/react-native-drawer-layout/lib/module/views/Drawer.native.js
|
||||
+++ b/node_modules/react-native-drawer-layout/lib/module/views/Drawer.native.js
|
||||
@@ -124,15 +124,21 @@ export function Drawer({
|
||||
}
|
||||
onTransitionEnd?.(!open);
|
||||
});
|
||||
+ const animatingTo = useSharedValue(null)
|
||||
const toggleDrawer = React.useCallback((open, velocity) => {
|
||||
'worklet';
|
||||
|
||||
+ if (animatingTo.value === (open ? 'open' : 'close')) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
const translateX = getDrawerTranslationX(open);
|
||||
if (velocity === undefined) {
|
||||
runOnJS(onAnimationStart)(open);
|
||||
}
|
||||
touchStartX.value = 0;
|
||||
touchX.value = 0;
|
||||
+ animatingTo.value = open ? 'open' : 'close';
|
||||
translationX.value = withSpring(translateX, {
|
||||
velocity,
|
||||
stiffness: 1000,
|
||||
@@ -142,7 +148,10 @@ export function Drawer({
|
||||
restDisplacementThreshold: 0.01,
|
||||
restSpeedThreshold: 0.01,
|
||||
reduceMotion: ReduceMotion.Never
|
||||
- }, finished => runOnJS(onAnimationEnd)(open, finished));
|
||||
+ }, finished => {
|
||||
+ animatingTo.value = null;
|
||||
+ runOnJS(onAnimationEnd)(open, finished);
|
||||
+ });
|
||||
if (open) {
|
||||
runOnJS(onOpen)();
|
||||
} else {
|
||||
@@ -1,48 +0,0 @@
|
||||
diff --git a/node_modules/react-native-keyboard-controller/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts b/node_modules/react-native-keyboard-controller/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts
|
||||
index 24a25ae..2c5ff6d 100644
|
||||
--- a/node_modules/react-native-keyboard-controller/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts
|
||||
+++ b/node_modules/react-native-keyboard-controller/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts
|
||||
@@ -1,8 +1,6 @@
|
||||
import { useCallback } from "react";
|
||||
-import { Platform } from "react-native";
|
||||
import { scrollTo, useAnimatedReaction } from "react-native-reanimated";
|
||||
|
||||
-import { IS_FABRIC } from "../../../architecture";
|
||||
import { isScrollAtEnd, shouldShiftContent } from "../useChatKeyboard/helpers";
|
||||
|
||||
import type { KeyboardLiftBehavior } from "../useChatKeyboard/types";
|
||||
@@ -52,7 +50,6 @@ function useExtraContentPadding(options: UseExtraContentPaddingOptions): void {
|
||||
scroll,
|
||||
layout,
|
||||
size,
|
||||
- contentOffsetY,
|
||||
inverted,
|
||||
keyboardLiftBehavior,
|
||||
freeze,
|
||||
@@ -62,20 +59,14 @@ function useExtraContentPadding(options: UseExtraContentPaddingOptions): void {
|
||||
(target: number) => {
|
||||
"worklet";
|
||||
|
||||
- if (contentOffsetY && IS_FABRIC) {
|
||||
- // eslint-disable-next-line react-compiler/react-compiler
|
||||
- contentOffsetY.value = target;
|
||||
- } else if (Platform.OS === "android") {
|
||||
- // Defer scrollTo so the animatedProps inset commit lands first;
|
||||
- // otherwise the native ScrollView clamps to the old range.
|
||||
- requestAnimationFrame(() => {
|
||||
- scrollTo(scrollViewRef, 0, target, false);
|
||||
- });
|
||||
- } else {
|
||||
+ // Always defer scrollTo so the animatedProps inset commit lands first;
|
||||
+ // otherwise the native ScrollView clamps contentOffset to the old
|
||||
+ // contentInset range (iOS Fabric) or the old contentInsetBottom (Android).
|
||||
+ requestAnimationFrame(() => {
|
||||
scrollTo(scrollViewRef, 0, target, false);
|
||||
- }
|
||||
+ });
|
||||
},
|
||||
- [scrollViewRef, contentOffsetY],
|
||||
+ [scrollViewRef],
|
||||
);
|
||||
|
||||
useAnimatedReaction(
|
||||
@@ -1,30 +0,0 @@
|
||||
diff --git a/node_modules/react-native-pager-view/ios/RNCPagerView.m b/node_modules/react-native-pager-view/ios/RNCPagerView.m
|
||||
index adfc7c6..366df60 100644
|
||||
--- a/node_modules/react-native-pager-view/ios/RNCPagerView.m
|
||||
+++ b/node_modules/react-native-pager-view/ios/RNCPagerView.m
|
||||
@@ -498,6 +498,25 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecogni
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ // iOS 26+ full-screen back gesture (interactiveContentPopGestureRecognizer)
|
||||
+ if (@available(iOS 26, *)) {
|
||||
+ if (gestureRecognizer == self.panGestureRecognizer &&
|
||||
+ otherGestureRecognizer == self.reactViewController.navigationController.interactiveContentPopGestureRecognizer) {
|
||||
+ UIPanGestureRecognizer* panGestureRecognizer = (UIPanGestureRecognizer*) gestureRecognizer;
|
||||
+ CGPoint velocity = [panGestureRecognizer velocityInView:self];
|
||||
+ BOOL isLTR = [self isLtrLayout];
|
||||
+ BOOL isBackGesture = (isLTR && velocity.x > 0) || (!isLTR && velocity.x < 0);
|
||||
+
|
||||
+ if (self.currentIndex == 0 && isBackGesture) {
|
||||
+ self.scrollView.panGestureRecognizer.enabled = false;
|
||||
+ } else {
|
||||
+ self.scrollView.panGestureRecognizer.enabled = self.scrollEnabled;
|
||||
+ }
|
||||
+
|
||||
+ return YES;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
self.scrollView.panGestureRecognizer.enabled = self.scrollEnabled;
|
||||
return NO;
|
||||
}
|
||||
@@ -1,389 +0,0 @@
|
||||
diff --git a/node_modules/react-native-reanimated/lib/module/component/PerformanceMonitor.js b/node_modules/react-native-reanimated/lib/module/component/PerformanceMonitor.js
|
||||
index 9c98d6c..70ada9f 100644
|
||||
--- a/node_modules/react-native-reanimated/lib/module/component/PerformanceMonitor.js
|
||||
+++ b/node_modules/react-native-reanimated/lib/module/component/PerformanceMonitor.js
|
||||
@@ -1,125 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
-import React, { useEffect, useRef } from 'react';
|
||||
-import { StyleSheet, TextInput, View } from 'react-native';
|
||||
-import { addWhitelistedNativeProps } from "../ConfigHelper.js";
|
||||
-import { createAnimatedComponent } from "../createAnimatedComponent/index.js";
|
||||
-import { useAnimatedProps, useFrameCallback, useSharedValue } from "../hook/index.js";
|
||||
-function createCircularDoublesBuffer(size) {
|
||||
- 'worklet';
|
||||
-
|
||||
- return {
|
||||
- next: 0,
|
||||
- buffer: new Float32Array(size),
|
||||
- size,
|
||||
- count: 0,
|
||||
- push(value) {
|
||||
- const oldValue = this.buffer[this.next];
|
||||
- const oldCount = this.count;
|
||||
- this.buffer[this.next] = value;
|
||||
- this.next = (this.next + 1) % this.size;
|
||||
- this.count = Math.min(this.size, this.count + 1);
|
||||
- return oldCount === this.size ? oldValue : null;
|
||||
- },
|
||||
- front() {
|
||||
- const notEmpty = this.count > 0;
|
||||
- if (notEmpty) {
|
||||
- const current = this.next - 1;
|
||||
- const index = current < 0 ? this.size - 1 : current;
|
||||
- return this.buffer[index];
|
||||
- }
|
||||
- return null;
|
||||
- },
|
||||
- back() {
|
||||
- const notEmpty = this.count > 0;
|
||||
- return notEmpty ? this.buffer[this.next] : null;
|
||||
- }
|
||||
- };
|
||||
-}
|
||||
-const DEFAULT_BUFFER_SIZE = 20;
|
||||
-addWhitelistedNativeProps({
|
||||
- text: true
|
||||
-});
|
||||
-const AnimatedTextInput = createAnimatedComponent(TextInput);
|
||||
-function loopAnimationFrame(fn) {
|
||||
- let lastTime = 0;
|
||||
- function loop() {
|
||||
- requestAnimationFrame(time => {
|
||||
- if (lastTime > 0) {
|
||||
- fn(lastTime, time);
|
||||
- }
|
||||
- lastTime = time;
|
||||
- requestAnimationFrame(loop);
|
||||
- });
|
||||
- }
|
||||
- loop();
|
||||
-}
|
||||
-function getFps(renderTimeInMs) {
|
||||
- 'worklet';
|
||||
-
|
||||
- return 1000 / renderTimeInMs;
|
||||
-}
|
||||
-function completeBufferRoutine(buffer, timestamp) {
|
||||
- 'worklet';
|
||||
-
|
||||
- timestamp = Math.round(timestamp);
|
||||
- const droppedTimestamp = buffer.push(timestamp) ?? timestamp;
|
||||
- const measuredRangeDuration = timestamp - droppedTimestamp;
|
||||
- return getFps(measuredRangeDuration / buffer.count);
|
||||
-}
|
||||
-function JsPerformance({
|
||||
- smoothingFrames
|
||||
-}) {
|
||||
- const jsFps = useSharedValue(null);
|
||||
- const totalRenderTime = useSharedValue(0);
|
||||
- const circularBuffer = useRef(createCircularDoublesBuffer(smoothingFrames));
|
||||
- useEffect(() => {
|
||||
- loopAnimationFrame((_, timestamp) => {
|
||||
- timestamp = Math.round(timestamp);
|
||||
- const currentFps = completeBufferRoutine(circularBuffer.current, timestamp);
|
||||
-
|
||||
- // JS fps have to be measured every 2nd frame,
|
||||
- // thus 2x multiplication has to occur here
|
||||
- jsFps.value = (currentFps * 2).toFixed(0);
|
||||
- });
|
||||
- }, [jsFps, totalRenderTime]);
|
||||
- const animatedProps = useAnimatedProps(() => {
|
||||
- const text = 'JS: ' + (jsFps.value ?? 'N/A') + ' ';
|
||||
- return {
|
||||
- text,
|
||||
- defaultValue: text
|
||||
- };
|
||||
- });
|
||||
- return <View style={styles.container}>
|
||||
- <AnimatedTextInput style={styles.text} animatedProps={animatedProps} editable={false} />
|
||||
- </View>;
|
||||
-}
|
||||
-function UiPerformance({
|
||||
- smoothingFrames
|
||||
-}) {
|
||||
- const uiFps = useSharedValue(null);
|
||||
- const circularBuffer = useSharedValue(null);
|
||||
- useFrameCallback(({
|
||||
- timestamp
|
||||
- }) => {
|
||||
- if (circularBuffer.value === null) {
|
||||
- circularBuffer.value = createCircularDoublesBuffer(smoothingFrames);
|
||||
- }
|
||||
- timestamp = Math.round(timestamp);
|
||||
- const currentFps = completeBufferRoutine(circularBuffer.value, timestamp);
|
||||
- uiFps.value = currentFps.toFixed(0);
|
||||
- });
|
||||
- const animatedProps = useAnimatedProps(() => {
|
||||
- const text = 'UI: ' + (uiFps.value ?? 'N/A') + ' ';
|
||||
- return {
|
||||
- text,
|
||||
- defaultValue: text
|
||||
- };
|
||||
- });
|
||||
- return <View style={styles.container}>
|
||||
- <AnimatedTextInput style={styles.text} animatedProps={animatedProps} editable={false} />
|
||||
- </View>;
|
||||
-}
|
||||
/**
|
||||
* A component that lets you measure fps values on JS and UI threads on both the
|
||||
* Paper and Fabric architectures.
|
||||
@@ -127,38 +7,7 @@ function UiPerformance({
|
||||
* @param smoothingFrames - Determines amount of saved frames which will be used
|
||||
* for fps value smoothing.
|
||||
*/
|
||||
-export function PerformanceMonitor({
|
||||
- smoothingFrames = DEFAULT_BUFFER_SIZE
|
||||
-}) {
|
||||
- return <View style={styles.monitor}>
|
||||
- <JsPerformance smoothingFrames={smoothingFrames} />
|
||||
- <UiPerformance smoothingFrames={smoothingFrames} />
|
||||
- </View>;
|
||||
+export function PerformanceMonitor() {
|
||||
+ return null;
|
||||
}
|
||||
-const styles = StyleSheet.create({
|
||||
- monitor: {
|
||||
- flexDirection: 'row',
|
||||
- position: 'absolute',
|
||||
- backgroundColor: '#0006',
|
||||
- zIndex: 1000
|
||||
- },
|
||||
- header: {
|
||||
- fontSize: 14,
|
||||
- color: '#ffff',
|
||||
- paddingHorizontal: 5
|
||||
- },
|
||||
- text: {
|
||||
- fontSize: 13,
|
||||
- fontVariant: ['tabular-nums'],
|
||||
- color: '#ffff',
|
||||
- fontFamily: 'monospace',
|
||||
- paddingHorizontal: 3
|
||||
- },
|
||||
- container: {
|
||||
- alignItems: 'center',
|
||||
- justifyContent: 'center',
|
||||
- flexDirection: 'row',
|
||||
- flexWrap: 'wrap'
|
||||
- }
|
||||
-});
|
||||
//# sourceMappingURL=PerformanceMonitor.js.map
|
||||
diff --git a/node_modules/react-native-reanimated/src/component/PerformanceMonitor.tsx b/node_modules/react-native-reanimated/src/component/PerformanceMonitor.tsx
|
||||
index ff8fc8a..34dde79 100644
|
||||
--- a/node_modules/react-native-reanimated/src/component/PerformanceMonitor.tsx
|
||||
+++ b/node_modules/react-native-reanimated/src/component/PerformanceMonitor.tsx
|
||||
@@ -1,170 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
-import React, { useEffect, useRef } from 'react';
|
||||
-import { StyleSheet, TextInput, View } from 'react-native';
|
||||
-
|
||||
-import { addWhitelistedNativeProps } from '../ConfigHelper';
|
||||
-import { createAnimatedComponent } from '../createAnimatedComponent';
|
||||
-import type { FrameInfo } from '../frameCallback';
|
||||
-import { useAnimatedProps, useFrameCallback, useSharedValue } from '../hook';
|
||||
-
|
||||
-type CircularBuffer = ReturnType<typeof createCircularDoublesBuffer>;
|
||||
-function createCircularDoublesBuffer(size: number) {
|
||||
- 'worklet';
|
||||
-
|
||||
- return {
|
||||
- next: 0 as number,
|
||||
- buffer: new Float32Array(size),
|
||||
- size,
|
||||
- count: 0 as number,
|
||||
-
|
||||
- push(value: number): number | null {
|
||||
- const oldValue = this.buffer[this.next];
|
||||
- const oldCount = this.count;
|
||||
- this.buffer[this.next] = value;
|
||||
-
|
||||
- this.next = (this.next + 1) % this.size;
|
||||
- this.count = Math.min(this.size, this.count + 1);
|
||||
- return oldCount === this.size ? oldValue : null;
|
||||
- },
|
||||
-
|
||||
- front(): number | null {
|
||||
- const notEmpty = this.count > 0;
|
||||
- if (notEmpty) {
|
||||
- const current = this.next - 1;
|
||||
- const index = current < 0 ? this.size - 1 : current;
|
||||
- return this.buffer[index];
|
||||
- }
|
||||
- return null;
|
||||
- },
|
||||
-
|
||||
- back(): number | null {
|
||||
- const notEmpty = this.count > 0;
|
||||
- return notEmpty ? this.buffer[this.next] : null;
|
||||
- },
|
||||
- };
|
||||
-}
|
||||
-
|
||||
-const DEFAULT_BUFFER_SIZE = 20;
|
||||
-addWhitelistedNativeProps({ text: true });
|
||||
-const AnimatedTextInput = createAnimatedComponent(TextInput);
|
||||
-
|
||||
-function loopAnimationFrame(fn: (lastTime: number, time: number) => void) {
|
||||
- let lastTime = 0;
|
||||
-
|
||||
- function loop() {
|
||||
- requestAnimationFrame((time) => {
|
||||
- if (lastTime > 0) {
|
||||
- fn(lastTime, time);
|
||||
- }
|
||||
- lastTime = time;
|
||||
- requestAnimationFrame(loop);
|
||||
- });
|
||||
- }
|
||||
-
|
||||
- loop();
|
||||
-}
|
||||
-
|
||||
-function getFps(renderTimeInMs: number): number {
|
||||
- 'worklet';
|
||||
- return 1000 / renderTimeInMs;
|
||||
-}
|
||||
-
|
||||
-function completeBufferRoutine(
|
||||
- buffer: CircularBuffer,
|
||||
- timestamp: number
|
||||
-): number {
|
||||
- 'worklet';
|
||||
- timestamp = Math.round(timestamp);
|
||||
-
|
||||
- const droppedTimestamp = buffer.push(timestamp) ?? timestamp;
|
||||
-
|
||||
- const measuredRangeDuration = timestamp - droppedTimestamp;
|
||||
-
|
||||
- return getFps(measuredRangeDuration / buffer.count);
|
||||
-}
|
||||
-
|
||||
-function JsPerformance({ smoothingFrames }: { smoothingFrames: number }) {
|
||||
- const jsFps = useSharedValue<string | null>(null);
|
||||
- const totalRenderTime = useSharedValue(0);
|
||||
- const circularBuffer = useRef<CircularBuffer>(
|
||||
- createCircularDoublesBuffer(smoothingFrames)
|
||||
- );
|
||||
-
|
||||
- useEffect(() => {
|
||||
- loopAnimationFrame((_, timestamp) => {
|
||||
- timestamp = Math.round(timestamp);
|
||||
-
|
||||
- const currentFps = completeBufferRoutine(
|
||||
- circularBuffer.current,
|
||||
- timestamp
|
||||
- );
|
||||
-
|
||||
- // JS fps have to be measured every 2nd frame,
|
||||
- // thus 2x multiplication has to occur here
|
||||
- jsFps.value = (currentFps * 2).toFixed(0);
|
||||
- });
|
||||
- }, [jsFps, totalRenderTime]);
|
||||
-
|
||||
- const animatedProps = useAnimatedProps(() => {
|
||||
- const text = 'JS: ' + (jsFps.value ?? 'N/A') + ' ';
|
||||
- return { text, defaultValue: text };
|
||||
- });
|
||||
-
|
||||
- return (
|
||||
- <View style={styles.container}>
|
||||
- <AnimatedTextInput
|
||||
- style={styles.text}
|
||||
- animatedProps={animatedProps}
|
||||
- editable={false}
|
||||
- />
|
||||
- </View>
|
||||
- );
|
||||
-}
|
||||
-
|
||||
-function UiPerformance({ smoothingFrames }: { smoothingFrames: number }) {
|
||||
- const uiFps = useSharedValue<string | null>(null);
|
||||
- const circularBuffer = useSharedValue<CircularBuffer | null>(null);
|
||||
-
|
||||
- useFrameCallback(({ timestamp }: FrameInfo) => {
|
||||
- if (circularBuffer.value === null) {
|
||||
- circularBuffer.value = createCircularDoublesBuffer(smoothingFrames);
|
||||
- }
|
||||
-
|
||||
- timestamp = Math.round(timestamp);
|
||||
-
|
||||
- const currentFps = completeBufferRoutine(circularBuffer.value, timestamp);
|
||||
-
|
||||
- uiFps.value = currentFps.toFixed(0);
|
||||
- });
|
||||
-
|
||||
- const animatedProps = useAnimatedProps(() => {
|
||||
- const text = 'UI: ' + (uiFps.value ?? 'N/A') + ' ';
|
||||
- return { text, defaultValue: text };
|
||||
- });
|
||||
-
|
||||
- return (
|
||||
- <View style={styles.container}>
|
||||
- <AnimatedTextInput
|
||||
- style={styles.text}
|
||||
- animatedProps={animatedProps}
|
||||
- editable={false}
|
||||
- />
|
||||
- </View>
|
||||
- );
|
||||
-}
|
||||
-
|
||||
-export type PerformanceMonitorProps = {
|
||||
- /**
|
||||
- * Sets amount of previous frames used for smoothing at highest expectedFps.
|
||||
- *
|
||||
- * Automatically scales down at lower frame rates.
|
||||
- *
|
||||
- * Affects jumpiness of the FPS measurements value.
|
||||
- */
|
||||
- smoothingFrames?: number;
|
||||
-};
|
||||
-
|
||||
/**
|
||||
* A component that lets you measure fps values on JS and UI threads on both the
|
||||
* Paper and Fabric architectures.
|
||||
@@ -172,40 +7,6 @@ export type PerformanceMonitorProps = {
|
||||
* @param smoothingFrames - Determines amount of saved frames which will be used
|
||||
* for fps value smoothing.
|
||||
*/
|
||||
-export function PerformanceMonitor({
|
||||
- smoothingFrames = DEFAULT_BUFFER_SIZE,
|
||||
-}: PerformanceMonitorProps) {
|
||||
- return (
|
||||
- <View style={styles.monitor}>
|
||||
- <JsPerformance smoothingFrames={smoothingFrames} />
|
||||
- <UiPerformance smoothingFrames={smoothingFrames} />
|
||||
- </View>
|
||||
- );
|
||||
+export function PerformanceMonitor() {
|
||||
+ return null;
|
||||
}
|
||||
-
|
||||
-const styles = StyleSheet.create({
|
||||
- monitor: {
|
||||
- flexDirection: 'row',
|
||||
- position: 'absolute',
|
||||
- backgroundColor: '#0006',
|
||||
- zIndex: 1000,
|
||||
- },
|
||||
- header: {
|
||||
- fontSize: 14,
|
||||
- color: '#ffff',
|
||||
- paddingHorizontal: 5,
|
||||
- },
|
||||
- text: {
|
||||
- fontSize: 13,
|
||||
- fontVariant: ['tabular-nums'],
|
||||
- color: '#ffff',
|
||||
- fontFamily: 'monospace',
|
||||
- paddingHorizontal: 3,
|
||||
- },
|
||||
- container: {
|
||||
- alignItems: 'center',
|
||||
- justifyContent: 'center',
|
||||
- flexDirection: 'row',
|
||||
- flexWrap: 'wrap',
|
||||
- },
|
||||
-});
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
diff --git a/node_modules/react-native-uitextview/ios/RNUITextViewShadow.swift b/node_modules/react-native-uitextview/ios/RNUITextViewShadow.swift
|
||||
index c34ba71..3602856 100644
|
||||
--- a/node_modules/react-native-uitextview/ios/RNUITextViewShadow.swift
|
||||
+++ b/node_modules/react-native-uitextview/ios/RNUITextViewShadow.swift
|
||||
@@ -159,13 +159,25 @@ class RNUITextViewShadow: RCTShadowView {
|
||||
let maxSize = CGSize(width: CGFloat(maxWidth), height: CGFloat(MAXFLOAT))
|
||||
let textSize = self.attributedText.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, context: nil)
|
||||
|
||||
- var totalLines = self.lineHeight == 0.0 ? 0 : Int(ceil(textSize.height / self.lineHeight))
|
||||
-
|
||||
- if self.numberOfLines != 0, totalLines > self.numberOfLines {
|
||||
- totalLines = self.numberOfLines
|
||||
+ var finalHeight: CGFloat
|
||||
+
|
||||
+ if self.numberOfLines != 0 && self.lineHeight != 0.0 {
|
||||
+ // numberOfLines is set with custom line height - need to calculate lines and snap to lineHeight multiples
|
||||
+ // NOTE: this calculation can be inaccurate with fractional font sizes
|
||||
+ var totalLines = Int(ceil(textSize.height / self.lineHeight))
|
||||
+ if totalLines > self.numberOfLines {
|
||||
+ totalLines = self.numberOfLines
|
||||
+ }
|
||||
+ finalHeight = CGFloat(totalLines) * self.lineHeight
|
||||
+ } else {
|
||||
+ // Either no numberOfLines limit, or no custom lineHeight - use actual text height
|
||||
+ // (numberOfLines without custom lineHeight is handled by the UITextView's textContainer.maximumNumberOfLines)
|
||||
+ finalHeight = textSize.height
|
||||
}
|
||||
|
||||
- self.frameSize = CGSize(width: CGFloat(maxWidth), height: CGFloat(CGFloat(totalLines) * self.lineHeight))
|
||||
+ finalHeight = ceil(finalHeight)
|
||||
+
|
||||
+ self.frameSize = CGSize(width: CGFloat(maxWidth), height: finalHeight)
|
||||
return YGSize(width: Float(self.frameSize.width), height: Float(self.frameSize.height))
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
diff --git a/node_modules/react-native-view-shot/src/index.js b/node_modules/react-native-view-shot/src/index.js
|
||||
index fa76d7e..018b686 100644
|
||||
--- a/node_modules/react-native-view-shot/src/index.js
|
||||
+++ b/node_modules/react-native-view-shot/src/index.js
|
||||
@@ -125,13 +125,17 @@ export function captureRef<T: React$ElementType>(
|
||||
}
|
||||
}
|
||||
if (typeof view !== "number") {
|
||||
- const node = findNodeHandle(view);
|
||||
- if (!node) {
|
||||
- return Promise.reject(
|
||||
- new Error("findNodeHandle failed to resolve view=" + String(view))
|
||||
- );
|
||||
+ if (Platform.OS == 'web') {
|
||||
+ view = view;
|
||||
+ } else {
|
||||
+ const node = findNodeHandle(view);
|
||||
+ if (!node) {
|
||||
+ return Promise.reject(
|
||||
+ new Error("findNodeHandle failed to resolve view=" + String(view))
|
||||
+ );
|
||||
+ }
|
||||
+ view = node;
|
||||
}
|
||||
- view = node;
|
||||
}
|
||||
const { options, errors } = validateOptions(optionsObject);
|
||||
if (__DEV__ && errors.length > 0) {
|
||||
@@ -1,22 +0,0 @@
|
||||
diff --git a/node_modules/sonner-native/lib/commonjs/toast.js b/node_modules/sonner-native/lib/commonjs/toast.js
|
||||
index 121816a..0c3c7bd 100644
|
||||
--- a/node_modules/sonner-native/lib/commonjs/toast.js
|
||||
+++ b/node_modules/sonner-native/lib/commonjs/toast.js
|
||||
@@ -264,7 +264,7 @@ const Toast = exports.Toast = /*#__PURE__*/React.forwardRef(({
|
||||
...toastSwipeHandlerProps,
|
||||
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
||||
entering: entering,
|
||||
- exiting: exiting,
|
||||
+ exiting: _reactNative.Platform.OS === 'android' ? undefined : exiting,
|
||||
children: jsx
|
||||
})
|
||||
});
|
||||
@@ -274,7 +274,7 @@ const Toast = exports.Toast = /*#__PURE__*/React.forwardRef(({
|
||||
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
||||
style: [unstyled ? undefined : elevationStyle, defaultStyles.toast, toastStyleCtx, styles?.toast, style, wiggleAnimationStyle],
|
||||
entering: entering,
|
||||
- exiting: exiting,
|
||||
+ exiting: _reactNative.Platform.OS === 'android' ? undefined : exiting,
|
||||
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
||||
style: [defaultStyles.toastContent, toastContentStyleCtx, styles?.toastContent],
|
||||
children: [promiseOptions || variant === 'loading' ? 'loading' in icons ? icons.loading : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {}) : icon ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
||||
Generated
+392
-445
File diff suppressed because it is too large
Load Diff
+21
-22
@@ -18,25 +18,24 @@ allowBuilds:
|
||||
"esbuild": true
|
||||
"unrs-resolver": true
|
||||
patchedDependencies:
|
||||
'@discord/bottom-sheet@4.6.1': patches/@discord__bottom-sheet@4.6.1.patch
|
||||
'@sentry/react-native@6.20.0': patches/@sentry__react-native@6.20.0.patch
|
||||
expo-glass-effect@55.0.8: patches/expo-glass-effect@55.0.8.patch
|
||||
expo-haptics@15.0.8: patches/expo-haptics@15.0.8.patch
|
||||
expo-image-picker@17.0.11: patches/expo-image-picker@17.0.11.patch
|
||||
expo-image@3.0.11: patches/expo-image@3.0.11.patch
|
||||
expo-media-library@18.2.1: patches/expo-media-library@18.2.1.patch
|
||||
expo-modules-core@3.0.30: patches/expo-modules-core@3.0.30.patch
|
||||
expo-notifications@0.32.17: patches/expo-notifications@0.32.17.patch
|
||||
expo-paste-input@0.1.15: patches/expo-paste-input@0.1.15.patch
|
||||
expo-updates@29.0.17: patches/expo-updates@29.0.17.patch
|
||||
react-native-compressor@1.13.0: patches/react-native-compressor@1.13.0.patch
|
||||
react-native-date-picker@5.0.13: patches/react-native-date-picker@5.0.13.patch
|
||||
react-native-drawer-layout@4.2.3: patches/react-native-drawer-layout@4.2.3.patch
|
||||
react-native-keyboard-controller@1.21.7: patches/react-native-keyboard-controller@1.21.7.patch
|
||||
react-native-pager-view@6.8.0: patches/react-native-pager-view@6.8.0.patch
|
||||
react-native-reanimated@3.19.1: patches/react-native-reanimated@3.19.1.patch
|
||||
react-native-svg@15.12.1: patches/react-native-svg@15.12.1.patch
|
||||
react-native-uitextview@1.4.0: patches/react-native-uitextview@1.4.0.patch
|
||||
react-native-view-shot@4.0.3: patches/react-native-view-shot@4.0.3.patch
|
||||
react-native@0.81.5: patches/react-native@0.81.5.patch
|
||||
sonner-native@0.21.0: patches/sonner-native@0.21.0.patch
|
||||
"@discord/bottom-sheet@4.6.1": patches/@discord__bottom-sheet@4.6.1.patch
|
||||
"@sentry/react-native@6.20.0": patches/@sentry__react-native@6.20.0.patch
|
||||
"expo-glass-effect@55.0.8": patches/expo-glass-effect@55.0.8.patch
|
||||
"expo-haptics@15.0.8": patches/expo-haptics@15.0.8.patch
|
||||
"expo-image-picker@17.0.11": patches/expo-image-picker@17.0.11.patch
|
||||
"expo-image@3.0.11": patches/expo-image@3.0.11.patch
|
||||
"expo-media-library@18.2.1": patches/expo-media-library@18.2.1.patch
|
||||
"expo-modules-core@3.0.30": patches/expo-modules-core@3.0.30.patch
|
||||
"expo-notifications@0.32.17": patches/expo-notifications@0.32.17.patch
|
||||
"expo-updates@29.0.17": patches/expo-updates@29.0.17.patch
|
||||
"react-native-compressor@1.13.0": patches/react-native-compressor@1.13.0.patch
|
||||
"react-native-date-picker@5.0.13": patches/react-native-date-picker@5.0.13.patch
|
||||
"react-native-drawer-layout@4.2.3": patches/react-native-drawer-layout@4.2.3.patch
|
||||
"react-native-keyboard-controller@1.21.7": patches/react-native-keyboard-controller@1.21.7.patch
|
||||
"react-native-pager-view@6.8.0": patches/react-native-pager-view@6.8.0.patch
|
||||
"react-native-reanimated@3.19.1": patches/react-native-reanimated@3.19.1.patch
|
||||
"react-native-svg@15.12.1": patches/react-native-svg@15.12.1.patch
|
||||
"react-native-uitextview@1.4.0": patches/react-native-uitextview@1.4.0.patch
|
||||
"react-native-view-shot@4.0.3": patches/react-native-view-shot@4.0.3.patch
|
||||
"react-native@0.81.5": patches/react-native@0.81.5.patch
|
||||
"sonner-native@0.21.0": patches/sonner-native@0.21.0.patch
|
||||
|
||||
Reference in New Issue
Block a user