Skip to content

Commit 71667a7

Browse files
authored
FlashList padding and styles fix (#920)
* Only include styles that flash list supports * Code reuse through hook * Fix flashlist to support percentage paddings
1 parent 0f8630b commit 71667a7

File tree

5 files changed

+72
-19
lines changed

5 files changed

+72
-19
lines changed

packages/core/src/components/BottomSheet/BottomSheet.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import BottomSheetComponent, {
1111
BottomSheetScrollView,
1212
} from "@gorhom/bottom-sheet";
1313
import { useTheme } from "@draftbit/theme";
14-
import { useDeepCompareMemo } from "../../utilities";
14+
import { extractPercentNumber, useDeepCompareMemo } from "../../utilities";
1515

1616
type SnapPosition = "top" | "middle" | "bottom";
1717

@@ -145,18 +145,6 @@ function convertSnapPointsForNewImplementation(
145145
});
146146
}
147147

148-
function extractPercentNumber(percentString: string) {
149-
const percentRegex = /(\d+)?%/;
150-
const matches = percentString.match(percentRegex);
151-
if (matches?.length) {
152-
const percentNumber = Number(matches[1]);
153-
if (!isNaN(percentNumber)) {
154-
return percentNumber;
155-
}
156-
}
157-
return undefined;
158-
}
159-
160148
const styles = StyleSheet.create({
161149
contentContainerStyle: {
162150
paddingHorizontal: 16,

packages/core/src/components/SimpleStyleScrollables/SimpleStyleFlashList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
22
import { FlashList } from "@shopify/flash-list";
33
import type { FlashListProps, ContentStyle } from "@shopify/flash-list";
4-
import useSplitContentContainerStyles from "./useSplitContentContainerStyles";
4+
import { useFlashListSplitContentContainerStyles } from "./useSplitContentContainerStyles";
55

66
/**
77
* A FlashList wrapper that takes a single `style` prop and internally extracts
@@ -17,7 +17,7 @@ const SimpleStyleFlashList = React.forwardRef(
1717
ref: React.Ref<FlashList<any>>
1818
) => {
1919
const { style, contentContainerStyle } =
20-
useSplitContentContainerStyles(styleProp);
20+
useFlashListSplitContentContainerStyles(styleProp);
2121

2222
return (
2323
<FlashList

packages/core/src/components/SimpleStyleScrollables/SimpleStyleMasonryFlashList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type {
55
ContentStyle,
66
MasonryFlashListRef,
77
} from "@shopify/flash-list";
8-
import useSplitContentContainerStyles from "./useSplitContentContainerStyles";
8+
import { useFlashListSplitContentContainerStyles } from "./useSplitContentContainerStyles";
99

1010
/**
1111
* A MasonryFlashList wrapper that takes a single `style` prop and internally extracts
@@ -21,7 +21,7 @@ const SimpleStyleMasonryFlashList = React.forwardRef(
2121
ref: React.Ref<MasonryFlashListRef<any>>
2222
) => {
2323
const { style, contentContainerStyle } =
24-
useSplitContentContainerStyles(styleProp);
24+
useFlashListSplitContentContainerStyles(styleProp);
2525

2626
return (
2727
<MasonryFlashList

packages/core/src/components/SimpleStyleScrollables/useSplitContentContainerStyles.ts

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import { StyleProp, ViewStyle, StyleSheet } from "react-native";
1+
import { StyleProp, ViewStyle, StyleSheet, Dimensions } from "react-native";
22
import { pick, omit } from "lodash";
3-
import { useDeepCompareMemo } from "../../utilities";
3+
import { extractPercentNumber, useDeepCompareMemo } from "../../utilities";
4+
5+
const DEVICE_WIDTH = Dimensions.get("window").width;
6+
const DEVICE_HEIGHT = Dimensions.get("window").width;
47

58
interface Styles {
69
style?: StyleProp<ViewStyle>;
@@ -57,3 +60,53 @@ export default function useSplitContentContainerStyles(
5760
};
5861
}, [originalStyle]);
5962
}
63+
64+
export function useFlashListSplitContentContainerStyles(
65+
originalStyle: StyleProp<ViewStyle>
66+
): Styles {
67+
const { style, contentContainerStyle } =
68+
useSplitContentContainerStyles(originalStyle);
69+
70+
// FlashList only supports a subset of contentContainerStyles
71+
// See https://shopify.github.io/flash-list/docs/usage/#contentcontainerstyle
72+
const flashListContentContainerStyle = pick(contentContainerStyle, [
73+
"backgroundColor",
74+
"paddingTop",
75+
"paddingLeft",
76+
"paddingRight",
77+
"paddingBottom",
78+
"padding",
79+
"paddingVertical",
80+
"paddingHorizontal",
81+
]) as { [key: string]: any };
82+
83+
// FlashList percentage paddings cause it to freeze and crash
84+
// This converts them to numbers based on device width/height
85+
for (const [key, value] of Object.entries(flashListContentContainerStyle)) {
86+
if (typeof value === "string" && key.includes("padding")) {
87+
const asNumber = extractPercentNumber(value);
88+
if (asNumber !== undefined) {
89+
switch (key) {
90+
case "padding":
91+
case "paddingLeft":
92+
case "paddingRight":
93+
case "paddingHorizontal":
94+
flashListContentContainerStyle[key] =
95+
DEVICE_WIDTH * (asNumber / 100);
96+
break;
97+
case "paddingTop":
98+
case "paddingBottom":
99+
case "paddingVertical":
100+
flashListContentContainerStyle[key] =
101+
DEVICE_HEIGHT * (asNumber / 100);
102+
break;
103+
}
104+
}
105+
}
106+
}
107+
108+
return {
109+
style,
110+
contentContainerStyle: flashListContentContainerStyle,
111+
};
112+
}

packages/core/src/utilities.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,15 @@ export function useDeepCompareEffect(
305305
// eslint-disable-next-line react-hooks/exhaustive-deps
306306
return React.useEffect(effect, deps?.map(useDeepCompareMemoize));
307307
}
308+
309+
export function extractPercentNumber(percentString: string) {
310+
const percentRegex = /(\d+)?%/;
311+
const matches = percentString.match(percentRegex);
312+
if (matches?.length) {
313+
const percentNumber = Number(matches[1]);
314+
if (!isNaN(percentNumber)) {
315+
return percentNumber;
316+
}
317+
}
318+
return undefined;
319+
}

0 commit comments

Comments
 (0)