delete old packages
This commit is contained in:
+1
-4
@@ -27,7 +27,6 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "is-ci || husky install",
|
"prepare": "is-ci || husky install",
|
||||||
"postinstall": "patch-package && pnpm intl:compile-if-needed",
|
|
||||||
"prebuild": "EXPO_NO_GIT_STATUS=1 expo prebuild --clean",
|
"prebuild": "EXPO_NO_GIT_STATUS=1 expo prebuild --clean",
|
||||||
"android": "expo run:android",
|
"android": "expo run:android",
|
||||||
"android:prod": "expo run:android --variant release",
|
"android:prod": "expo run:android --variant release",
|
||||||
@@ -66,7 +65,6 @@
|
|||||||
"intl:extract": "lingui extract --clean --locale en",
|
"intl:extract": "lingui extract --clean --locale en",
|
||||||
"intl:extract:all": "lingui extract --clean",
|
"intl:extract:all": "lingui extract --clean",
|
||||||
"intl:compile": "lingui compile",
|
"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:pull": "crowdin download translations --verbose -b main",
|
||||||
"intl:push": "crowdin push translations --verbose -b main",
|
"intl:push": "crowdin push translations --verbose -b main",
|
||||||
"intl:push-sources": "crowdin push sources --verbose -b main",
|
"intl:push-sources": "crowdin push sources --verbose -b main",
|
||||||
@@ -172,7 +170,7 @@
|
|||||||
"expo-location": "~19.0.8",
|
"expo-location": "~19.0.8",
|
||||||
"expo-media-library": "~18.2.1",
|
"expo-media-library": "~18.2.1",
|
||||||
"expo-notifications": "~0.32.17",
|
"expo-notifications": "~0.32.17",
|
||||||
"expo-paste-input": "^0.1.15",
|
"expo-paste-input": "^0.2.1",
|
||||||
"expo-privacy-sensitive": "^0.1.0",
|
"expo-privacy-sensitive": "^0.1.0",
|
||||||
"expo-screen-orientation": "~9.0.8",
|
"expo-screen-orientation": "~9.0.8",
|
||||||
"expo-sharing": "~14.0.8",
|
"expo-sharing": "~14.0.8",
|
||||||
@@ -199,7 +197,6 @@
|
|||||||
"multiformats": "9.9.0",
|
"multiformats": "9.9.0",
|
||||||
"nanoid": "^5.0.5",
|
"nanoid": "^5.0.5",
|
||||||
"normalize-url": "^8.0.0",
|
"normalize-url": "^8.0.0",
|
||||||
"patch-package": "^8.0.1",
|
|
||||||
"psl": "1.9.0",
|
"psl": "1.9.0",
|
||||||
"radix-ui": "^1.4.3",
|
"radix-ui": "^1.4.3",
|
||||||
"react": "19.1.0",
|
"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
|
"esbuild": true
|
||||||
"unrs-resolver": true
|
"unrs-resolver": true
|
||||||
patchedDependencies:
|
patchedDependencies:
|
||||||
'@discord/bottom-sheet@4.6.1': patches/@discord__bottom-sheet@4.6.1.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
|
"@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-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-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-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-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-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-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-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
|
||||||
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-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-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-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-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-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-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-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-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-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
|
||||||
react-native@0.81.5: patches/react-native@0.81.5.patch
|
"sonner-native@0.21.0": patches/sonner-native@0.21.0.patch
|
||||||
sonner-native@0.21.0: patches/sonner-native@0.21.0.patch
|
|
||||||
|
|||||||
Reference in New Issue
Block a user