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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions patches/expo-image-manipulator/details.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,19 @@
- Upstream PR/issue: https://github.com/expo/expo/pull/50011 (open), fixes https://github.com/expo/expo/issues/49953. Alternative fix under review in https://github.com/expo/expo/pull/50009
- E/App issue: https://github.com/Expensify/App/issues/100133
- PR introducing patch: https://github.com/Expensify/App/pull/101102

### [expo-image-manipulator+57.0.6+003+web-typings.patch](expo-image-manipulator+57.0.6+003+web-typings.patch)

- Reason:

```
Two web typing bugs:
1. `NativeImageManipulatorModule.web.d.ts` types its default export as the class (`typeof ImageManipulator`),
while `registerWebModule` returns an instance. So `ImageManipulator.manipulate()` doesn't compile on web.
2. The web `ImageManipulatorContext.resize()` requires both `width` and `height`, while the native one makes them
optional and the web implementation already keeps the aspect ratio when one is missing.
```

- Upstream PR/issue: 1 is fixed in `expo-modules-core` by https://github.com/expo/expo/pull/49197, and the generated `.d.ts` picks it up on the next `expo-image-manipulator` release. 2: 🛑, upstream PR to be opened.
- E/App issue: https://github.com/Expensify/App/issues/99287
- PR introducing patch: https://github.com/Expensify/App/pull/105816
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
diff --git a/node_modules/expo-image-manipulator/build/NativeImageManipulatorModule.web.d.ts b/node_modules/expo-image-manipulator/build/NativeImageManipulatorModule.web.d.ts
index 627ef30..e93a4bf 100644
--- a/node_modules/expo-image-manipulator/build/NativeImageManipulatorModule.web.d.ts
+++ b/node_modules/expo-image-manipulator/build/NativeImageManipulatorModule.web.d.ts
@@ -7,6 +7,6 @@ declare class ImageManipulator extends NativeModule {
Image: typeof ImageManipulatorImageRef;
manipulate(source: string | SharedRef<'image'>): ImageManipulatorContext;
}
-declare const _default: typeof ImageManipulator;
+declare const _default: ImageManipulator;
export default _default;
//# sourceMappingURL=NativeImageManipulatorModule.web.d.ts.map
\ No newline at end of file
diff --git a/node_modules/expo-image-manipulator/build/web/ImageManipulatorContext.web.d.ts b/node_modules/expo-image-manipulator/build/web/ImageManipulatorContext.web.d.ts
index 9991c3b..60f3aa8 100644
--- a/node_modules/expo-image-manipulator/build/web/ImageManipulatorContext.web.d.ts
+++ b/node_modules/expo-image-manipulator/build/web/ImageManipulatorContext.web.d.ts
@@ -9,8 +9,8 @@ export default class ImageManipulatorContext extends SharedObject {
set currentTask(task: Promise<HTMLCanvasElement>);
constructor(loader?: ContextLoader);
resize(size: {
- width: number;
- height: number;
+ width?: number;
+ height?: number;
}): ImageManipulatorContext;
rotate(degrees: number): ImageManipulatorContext;
flip(flipType: FlipType): ImageManipulatorContext;
16 changes: 16 additions & 0 deletions patches/expo-video/details.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,19 @@
### [expo-video+57.0.2+001+catch_play_abort_error.patch](expo-video+57.0.2+001+catch_play_abort_error.patch)

- Reason: When rapidly seeking a video via the progress bar on web, `HTMLVideoElement.play()` returns a Promise that gets rejected with `AbortError` if `pause()` is called before it resolves. This patch wraps all 5 `video.play()` call sites in `VideoPlayer.web.js` with `.catch()` to silently swallow `AbortError` while re-throwing any other errors. This is the [standard fix recommended by Chrome](https://developer.chrome.com/blog/play-request-was-interrupted).

### [expo-video+57.0.2+002+web-videoview-types.patch](expo-video+57.0.2+002+web-videoview-types.patch)

- Reason:

```
The web `VideoView` declaration types its ref as `unknown` and only exports `VideoView` as a value, while native
exports a class. Its `player` prop is also typed as the web implementation class instead of the public
`VideoPlayer` type that `useVideoPlayer` returns. The patch types the ref handle the way the web implementation
builds it (`enterFullscreen`, `exitFullscreen`, `startPictureInPicture`, `stopPictureInPicture`, `nativeRef`),
exports it as the `VideoView` type, and accepts the public `VideoPlayer` type for `player`.
```

- Upstream PR/issue: 🛑, upstream PR to be opened.
- E/App issue: https://github.com/Expensify/App/issues/99287
- PR introducing patch: https://github.com/Expensify/App/pull/105816
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
diff --git a/node_modules/expo-video/build/VideoView.web.d.ts b/node_modules/expo-video/build/VideoView.web.d.ts
index 55c6d82..48eda21 100644
--- a/node_modules/expo-video/build/VideoView.web.d.ts
+++ b/node_modules/expo-video/build/VideoView.web.d.ts
@@ -1,9 +1,16 @@
import React from 'react';
-import type VideoPlayer from './VideoPlayer.web';
+import type { VideoPlayer } from './VideoPlayer.types';
import type { VideoViewProps } from './VideoView.types';
export declare function isPictureInPictureSupported(): boolean;
+export type VideoView = {
+ enterFullscreen(): Promise<void>;
+ exitFullscreen(): Promise<void>;
+ startPictureInPicture(): Promise<void>;
+ stopPictureInPicture(): Promise<void>;
+ nativeRef: React.RefObject<HTMLVideoElement | null>;
+};
export declare const VideoView: React.ForwardRefExoticComponent<{
player?: VideoPlayer;
-} & VideoViewProps & React.RefAttributes<unknown>>;
+} & VideoViewProps & React.RefAttributes<VideoView>>;
export default VideoView;
//# sourceMappingURL=VideoView.web.d.ts.map
\ No newline at end of file
16 changes: 16 additions & 0 deletions patches/react-native-gesture-handler/details.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,19 @@
- Upstream PR/issue: https://github.com/software-mansion/react-native-gesture-handler/pull/4624
- E/App issue: https://github.com/Expensify/App/issues/102782
- PR introducing patch: https://github.com/Expensify/App/pull/103457

### [react-native-gesture-handler+3.3.0+002+web-v3-component-types.patch](react-native-gesture-handler+3.3.0+002+web-v3-component-types.patch)

- Reason:

```
On native, `v3/components/GestureComponents.d.ts` exports `TextInput` and `FlatList` both as values and as types,
and `FlatList` takes a `ref`. The web declarations only export the values and leave `ref` out of `FlatList`, so
`useRef<TextInput>` and `<FlatList ref={…}>` stop compiling once the web tsconfig resolves `.web.d.ts` files.
The web `FlatList` spreads its props onto React Native's `FlatList`, so the ref already works at runtime.
The patch adds the matching type exports and the `ref` prop.
```

- Upstream PR/issue: 🛑, upstream PR to be opened.
- E/App issue: https://github.com/Expensify/App/issues/99287
- PR introducing patch: https://github.com/Expensify/App/pull/105816
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
diff --git a/node_modules/react-native-gesture-handler/lib/typescript/v3/components/GestureComponents.web.d.ts b/node_modules/react-native-gesture-handler/lib/typescript/v3/components/GestureComponents.web.d.ts
index 23d00f1..9d98034 100644
--- a/node_modules/react-native-gesture-handler/lib/typescript/v3/components/GestureComponents.web.d.ts
+++ b/node_modules/react-native-gesture-handler/lib/typescript/v3/components/GestureComponents.web.d.ts
@@ -1,5 +1,5 @@
import * as React from 'react';
-import type { FlatListProps } from 'react-native';
+import type { FlatList as RNFlatList, FlatListProps, TextInput as RNTextInput } from 'react-native';
export declare const ScrollView: {
(props: Omit<import("react-native").ScrollViewProps, "ref"> & {
ref?: React.Ref<import("react-native").ScrollViewInstance> | undefined;
@@ -117,6 +117,7 @@ export declare const TextInput: {
} & import("../types").GestureCallbacks<import("../hooks/gestures/native/NativeTypes").NativeHandlerData> & import("../hooks/gestures/native/NativeTypes").NativeGestureNativeProperties & import("../types").ExternalRelations & import("../types/NativeWrapperType").WrapperSpecificProperties<unknown>): React.JSX.Element;
displayName: any;
};
+export type TextInput = typeof TextInput & RNTextInput;
export declare const DrawerLayoutAndroid: () => React.JSX.Element;
export declare const RefreshControl: {
(props: Omit<import("react-native").ViewProps, "ref"> & {
@@ -157,5 +158,8 @@ export declare const RefreshControl: {
} & import("../types").GestureCallbacks<import("../hooks/gestures/native/NativeTypes").NativeHandlerData> & import("../hooks/gestures/native/NativeTypes").NativeGestureNativeProperties & import("../types").ExternalRelations & import("../types/NativeWrapperType").WrapperSpecificProperties<unknown>): React.JSX.Element;
displayName: any;
};
-export declare const FlatList: <ItemT>(props: FlatListProps<ItemT>) => React.JSX.Element;
+export declare const FlatList: <ItemT>(props: FlatListProps<ItemT> & {
+ ref?: React.Ref<RNFlatList<ItemT> | null>;
+}) => React.JSX.Element;
+export type FlatList<ItemT = any> = typeof FlatList & RNFlatList<ItemT>;
//# sourceMappingURL=GestureComponents.web.d.ts.map
\ No newline at end of file
15 changes: 15 additions & 0 deletions patches/react-native-nitro-fetch/details.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,18 @@
- Upstream PR/issue: None. The certificate hosts and public-key pins are specific to Expensify's application configuration and are not appropriate defaults for react-native-nitro-fetch.
- E/App issue: https://github.com/Expensify/App/issues/90023
- PR Introducing Patch: https://github.com/Expensify/App/pull/95518

### [react-native-nitro-fetch+1.6.2+002+redirect-accepts-url.patch](react-native-nitro-fetch+1.6.2+002+redirect-accepts-url.patch)

- Reason:

```
`Response.redirect()` only accepts a string, while the standard signature (and React Native's global `Response`
type) accepts `string | URL`. That makes `globalThis.Response = NitroResponse` fail to typecheck once native code
no longer sees the DOM types. The patch accepts `string | URL` and converts it with `String(url)` before setting
the `location` header.
```

- Upstream PR/issue: 🛑, upstream PR to be opened.
- E/App issue: https://github.com/Expensify/App/issues/99287
- PR introducing patch: https://github.com/Expensify/App/pull/105816
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
diff --git a/node_modules/react-native-nitro-fetch/lib/module/Response.js b/node_modules/react-native-nitro-fetch/lib/module/Response.js
index 5c2fa6c..893e7b7 100644
--- a/node_modules/react-native-nitro-fetch/lib/module/Response.js
+++ b/node_modules/react-native-nitro-fetch/lib/module/Response.js
@@ -252,7 +252,7 @@ export class NitroResponse {
throw new RangeError(`Invalid redirect status: ${status}. Must be one of ${validStatuses.join(', ')}`);
}
const headers = new NitroHeaders();
- headers.set('location', url);
+ headers.set('location', String(url));
return new NitroResponse({
url: '',
status,
diff --git a/node_modules/react-native-nitro-fetch/lib/typescript/src/Response.d.ts b/node_modules/react-native-nitro-fetch/lib/typescript/src/Response.d.ts
index 3ec41b1..9f0ec15 100644
--- a/node_modules/react-native-nitro-fetch/lib/typescript/src/Response.d.ts
+++ b/node_modules/react-native-nitro-fetch/lib/typescript/src/Response.d.ts
@@ -46,6 +46,6 @@ export declare class NitroResponse {
statusText?: string;
headers?: Record<string, string> | [string, string][];
}): NitroResponse;
- static redirect(url: string, status?: number): NitroResponse;
+ static redirect(url: string | URL, status?: number): NitroResponse;
}
//# sourceMappingURL=Response.d.ts.map
\ No newline at end of file
diff --git a/node_modules/react-native-nitro-fetch/src/Response.ts b/node_modules/react-native-nitro-fetch/src/Response.ts
index 9601775..35dc82e 100644
--- a/node_modules/react-native-nitro-fetch/src/Response.ts
+++ b/node_modules/react-native-nitro-fetch/src/Response.ts
@@ -329,7 +329,7 @@ export class NitroResponse {
});
}

- static redirect(url: string, status: number = 302): NitroResponse {
+ static redirect(url: string | URL, status: number = 302): NitroResponse {
const validStatuses = [301, 302, 303, 307, 308];
if (!validStatuses.includes(status)) {
throw new RangeError(
@@ -337,7 +337,7 @@ export class NitroResponse {
);
}
const headers = new NitroHeaders();
- headers.set('location', url);
+ headers.set('location', String(url));
return new NitroResponse({
url: '',
status,
29 changes: 29 additions & 0 deletions patches/react-native-svg/details.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# `react-native-svg` patches

### [react-native-svg+15.15.5+001+web-defs-children.patch](react-native-svg+15.15.5+001+web-defs-children.patch)

- Reason:

```
The web declaration of `Defs` (`elements.web.d.ts`) extends bare `WebShape`, so it accepts no `children`, unlike
its native declaration and every other element in the same file. Once the web tsconfig resolves `.web.d.ts`
files, `<Defs>{children}</Defs>` stops compiling. The patch adds `children` to the web `Defs` props.
```

- Upstream PR/issue: https://github.com/software-mansion/react-native-svg/pull/3056 (merged, not released yet). Remove this patch when upgrading past 15.15.5.
- E/App issue: https://github.com/Expensify/App/issues/99287
- PR introducing patch: https://github.com/Expensify/App/pull/105816

### [react-native-svg+15.15.5+002+web-style-prop.patch](react-native-svg+15.15.5+002+web-style-prop.patch)

- Reason:

```
The web `BaseProps` type declares `style?: Iterable<unknown>`, so a plain style object doesn't compile on web.
The web runtime (`lib/resolve.js`) accepts both a style object and an array, so the type is only too narrow.
The patch types `style` as `unknown`, which leaves each element's own `style` type in charge.
```

- Upstream PR/issue: 🛑, upstream PR to be opened.
- E/App issue: https://github.com/Expensify/App/issues/99287
- PR introducing patch: https://github.com/Expensify/App/pull/105816
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git a/node_modules/react-native-svg/lib/typescript/elements.web.d.ts b/node_modules/react-native-svg/lib/typescript/elements.web.d.ts
index cf4083f..3de5794 100644
--- a/node_modules/react-native-svg/lib/typescript/elements.web.d.ts
+++ b/node_modules/react-native-svg/lib/typescript/elements.web.d.ts
@@ -52,7 +52,9 @@ export declare class Circle extends WebShape<BaseProps & CircleProps> {
export declare class ClipPath extends WebShape<BaseProps & ClipPathProps> {
tag: "clipPath";
}
-export declare class Defs extends WebShape {
+export declare class Defs extends WebShape<BaseProps & {
+ children?: import("react").ReactNode;
+}> {
tag: "defs";
}
export declare class Ellipse extends WebShape<BaseProps & EllipseProps> {
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/node_modules/react-native-svg/lib/typescript/web/types.d.ts b/node_modules/react-native-svg/lib/typescript/web/types.d.ts
index ad1276e..67aa184 100644
--- a/node_modules/react-native-svg/lib/typescript/web/types.d.ts
+++ b/node_modules/react-native-svg/lib/typescript/web/types.d.ts
@@ -48,7 +48,7 @@ export interface BaseProps {
fontSize?: NumberProp;
fontFamily?: string;
forwardedRef?: React.RefCallback<SVGElement> | React.MutableRefObject<SVGElement | null>;
- style?: Iterable<unknown>;
+ style?: unknown;
gradientTransform?: TransformProps['transform'];
patternTransform?: TransformProps['transform'];
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type IconAsset from '@src/types/utils/IconAsset';
import type {ImageContentFit} from 'expo-image';
import type {SourceLoadEventPayload} from 'expo-video';
import type LottieView from 'lottie-react-native';
import type {ComponentRef} from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
import type {MergeExclusive} from 'type-fest';

Expand Down Expand Up @@ -92,7 +93,7 @@ function Illustration({
const {windowHeight} = useWindowDimensions();
const [measuredAspectRatio, setMeasuredAspectRatio] = useState(aspectRatioProp ?? VIDEO_ASPECT_RATIO);

const animationRef = useRef<LottieView | null>(null);
const animationRef = useRef<ComponentRef<typeof LottieView> | null>(null);
useEffect(() => {
if (isMobile() || !animationRef.current || isReduceMotionEnabled) {
return;
Expand Down
6 changes: 3 additions & 3 deletions src/components/Lottie/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@ import CONST from '@src/CONST';
import {useSplashScreenState} from '@src/SplashScreenStateContext';

import type {AnimationObject, LottieViewProps} from 'lottie-react-native';
import type {ForwardedRef} from 'react';
import type {ComponentRef, ForwardedRef} from 'react';

import {NavigationContainerRefContext, NavigationContext} from '@react-navigation/native';
import LottieView from 'lottie-react-native';
import React, {useContext, useEffect, useRef, useState} from 'react';
import {View} from 'react-native';

type Props = {
ref?: ForwardedRef<LottieView | null>;
ref?: ForwardedRef<ComponentRef<typeof LottieView> | null>;
source: DotLottieAnimation;
shouldLoadAfterInteractions?: boolean;
} & Omit<LottieViewProps, 'source'>;

function Lottie({ref, source, webStyle, shouldLoadAfterInteractions, ...props}: Props) {
const animationRef = useRef<LottieView | null>(null);
const animationRef = useRef<ComponentRef<typeof LottieView> | null>(null);
const appState = useAppState();
const {splashScreenState} = useSplashScreenState();
const styles = useThemeStyles();
Expand Down
2 changes: 1 addition & 1 deletion src/components/Modal/ReanimatedModal/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type GestureHandlerProps = {
onSwipeComplete?: () => void;

/** Threshold for swipe gesture. */
swipeThreshold: number;
swipeThreshold?: number;

/** Threshold for swipe gesture. */
swipeDirection?: SwipeDirection | SwipeDirection[];
Expand Down
5 changes: 4 additions & 1 deletion src/components/SkeletonRect.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import type {RectProps} from 'react-native-svg';
import type {ComponentProps} from 'react';

import React from 'react';
import {Rect} from 'react-native-svg';

// react-native-svg only exports `RectProps` from its native entry, so on web the props come from the component itself.
type RectProps = ComponentProps<typeof Rect>;

const BORDER_RADIUS_SMALL = 2; // text bars (height <= 8)
const BORDER_RADIUS_MEDIUM = 4; // content blocks (height > 8)
const HEIGHT_THRESHOLD = 8;
Expand Down
2 changes: 2 additions & 0 deletions src/hooks/useMarkdownStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ function useMarkdownStyle(hasMessageOnlyEmojis: boolean, excludeStyles: Array<ke
maxHeight: variables.inlineImagePreviewMaxSize,
borderRadius: variables.componentBorderRadius,
marginTop: 4,
// live-markdown's web style type requires this. 0 is the library's own default, so nothing changes visually.
marginBottom: 0,
},
loadingIndicator: {
primaryColor: theme.spinner,
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/usePressLoading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function usePressLoading({isLoading = false, resetOnFocus = true}: UsePressLoadi
const press = Symbol('press');
activePressRef.current = press;
setIsPressed(true);
await new Promise((resolve) => {
await new Promise<void>((resolve) => {
setTimeout(resolve, 0);
});
try {
Expand Down
Loading
Loading