Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(hot)fix ANR: Add runOnJS prop #297

Merged
merged 3 commits into from
Feb 25, 2023
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
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"react/no-array-index-key": 0,
"react/destructuring-assignment": 0,
"react/sort-comp": 0,
"react-hooks/exhaustive-deps": "warn"
"react-hooks/exhaustive-deps": "warn",
"no-unused-vars": "warn"
},
"ignorePatterns": [
"example/**/*.js"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ See [CHANGELOG.md](docs/CHANGELOG.md) for details.
| `updateCellsBatchingPeriod` | _Number_ | 50 | See in [_optimizing FlatList docs_](https://reactnative.dev/docs/optimizing-flatlist-configuration#updatecellsbatchingperiod) |
| **_Other props <br> (patch RN bugs)_** |
| `prependMostRecent` | _Boolean_ | `false` | If `true`, the horizontal prepending is done in the most recent dates when scrolling. See [known issues](#glitch-when-swiping-to-new-pages) |
| `runOnJS` | _Boolean_ | `false` | Passed to react-native-gesture-handler. Details in [this issue]([this issue](https://github.com/hoangnm/react-native-week-view/issues/259)) |

### Event Item
```js
Expand Down
8 changes: 6 additions & 2 deletions example/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const sampleEvents = [

// Next week
buildEvent(24 * 7, 2, 'magenta'),
buildEvent(24 * 7 - 48, 3, 'lightblue', {
buildEvent(24 * 7 - 48, 3, 'green', {
style: {
borderWidth: 5,
},
Expand All @@ -45,6 +45,9 @@ const sampleEvents = [
// Two more weeks
buildEvent(48 * 7, 2, 'pink'),
buildEvent(48 * 7 - 54, 4, 'green'),
// ...Array.from({length: 1000}, (_, i) =>
// buildEvent(24 + i * 5, 2, 'lightblue'),
// ),
];

const sampleFixedEvents = [
Expand Down Expand Up @@ -198,7 +201,7 @@ const App = ({}) => {
pageStartAt={PAGE_START_AT}
onEventPress={handlePressEvent}
onEventLongPress={handleLongPressEvent}
onGridClick={handlePressGrid}
onGridLongPress={handlePressGrid}
headerStyle={styles.header}
headerTextStyle={styles.headerText}
hourTextStyle={styles.hourText}
Expand All @@ -225,6 +228,7 @@ const App = ({}) => {
onEditEvent={onEditEvent}
editEventConfig={EDIT_EVENT_CONFIG}
dragEventConfig={DRAG_EVENT_CONFIG}
runOnJS
/>
</SafeAreaView>
</>
Expand Down
47 changes: 18 additions & 29 deletions src/Event/Event.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { View, Text } from 'react-native';
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
Expand All @@ -17,6 +17,7 @@ import {
EditEventConfigPropType,
DragEventConfigPropType,
} from '../utils/types';
import { RunGesturesOnJSContext } from '../utils/gestures';

const DEFAULT_COLOR = 'red';
const UPDATE_EVENT_ANIMATION_DURATION = 150;
Expand Down Expand Up @@ -87,34 +88,14 @@ const Event = ({
const isDragEnabled =
!!onDrag && editingEventId == null && !event.disableDrag;

const runGesturesOnJS = React.useContext(RunGesturesOnJSContext);

// Wrappers are needed due to RN-reanimated runOnJS behavior. See docs:
// https://docs.swmansion.com/react-native-reanimated/docs/api/miscellaneous/runOnJS
const onPressWrapper = useCallback(() => onPress && onPress(event), [
event,
onPress,
]);
const onLongPressWrapper = useCallback(
() => onLongPress && onLongPress(event),
[event, onLongPress],
);

const onDragRelease = useCallback(
(dx, dy) => {
if (!onDrag) {
return;
}

const newX = left + dx;
const newY = top + dy;
onDrag(event, newX, newY, width);
},
[event, left, top, width, onDrag],
);

const onEditRelease = useCallback(
(params) => onEdit && onEdit(event, params),
[event, onEdit],
);
const onPressWrapper = () => onPress && onPress(event);
const onLongPressWrapper = () => onLongPress && onLongPress(event);
const onDragWrapper = (...args) => onDrag && onDrag(event, ...args);
const onEditWrapper = (params) => onEdit && onEdit(event, params);

const resizeByEdit = {
bottom: useSharedValue(0),
Expand Down Expand Up @@ -168,6 +149,7 @@ const Event = ({
const dragGesture = Gesture.Pan()
.enabled(isDragEnabled)
.withTestId(`dragGesture-${event.id}`)
.runOnJS(runGesturesOnJS)
.onTouchesDown(() => {
dragStatus.value = DRAG_STATUS.PRESSING;
})
Expand All @@ -191,7 +173,11 @@ const Event = ({
currentLeft.value += translationX;
translatedByDrag.value = { x: 0, y: 0 };

runOnJS(onDragRelease)(translationX, translationY);
runOnJS(onDragWrapper)(
currentLeft.value,
currentTop.value,
currentWidth.value,
);
})
.onFinalize(() => {
dragStatus.value = DRAG_STATUS.STATIC;
Expand All @@ -213,6 +199,7 @@ const Event = ({
.enabled(
dragAfterLongPress === 0 && !!onLongPress && !event.disableLongPress,
)
.runOnJS(runGesturesOnJS)
.maxDistance(20)
.onTouchesDown(() => {
isLongPressing.value = true;
Expand All @@ -228,6 +215,7 @@ const Event = ({

const pressGesture = Gesture.Tap()
.enabled(!!onPress && !event.disablePress)
.runOnJS(runGesturesOnJS)
.withTestId(`pressGesture-${event.id}`)
.onTouchesDown(() => {
isPressing.value = true;
Expand All @@ -249,6 +237,7 @@ const Event = ({

const buildCircleGesture = (side) =>
Gesture.Pan()
.runOnJS(runGesturesOnJS)
.onUpdate((panEvt) => {
const { translationX, translationY } = panEvt;
switch (side) {
Expand Down Expand Up @@ -306,7 +295,7 @@ const Event = ({
default:
}

runOnJS(onEditRelease)(params);
runOnJS(onEditWrapper)(params);
});

return (
Expand Down
146 changes: 76 additions & 70 deletions src/WeekView/WeekView.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
getRawDayOffset,
DEFAULT_WINDOW_SIZE,
} from '../utils/pages';
import { RunGesturesOnJSContext } from '../utils/gestures';

/** For some reason, this sign is necessary in all cases. */
const VIEW_OFFSET_SIGN = -1;
Expand Down Expand Up @@ -579,6 +580,7 @@ export default class WeekView extends Component {
updateCellsBatchingPeriod,
removeClippedSubviews,
disableVirtualization,
runOnJS,
} = this.props;
const {
currentMoment,
Expand Down Expand Up @@ -701,78 +703,80 @@ export default class WeekView extends Component {
timeLabelHeight={timeLabelHeight}
width={timeLabelsWidth}
/>
<VirtualizedList
data={initialDates}
getItem={(data, index) => data[index]}
getItemCount={(data) => data.length}
getItemLayout={this.getListItemLayout}
keyExtractor={(item) => item}
initialScrollIndex={PAGES_OFFSET}
scrollEnabled={!fixedHorizontally}
onStartShouldSetResponderCapture={() => false}
onMoveShouldSetResponderCapture={() => false}
onResponderTerminationRequest={() => false}
renderItem={({ item }) => {
return (
<Events
times={times}
eventsByDate={eventsByDate}
initialDate={item}
numberOfDays={numberOfDays}
onEventPress={onEventPress}
onEventLongPress={onEventLongPress}
onGridClick={onGridClick}
onGridLongPress={onGridLongPress}
beginAgendaAt={beginAgendaAt}
timeLabelHeight={timeLabelHeight}
EventComponent={EventComponent}
eventContainerStyle={eventContainerStyle}
gridRowStyle={gridRowStyle}
gridColumnStyle={gridColumnStyle}
rightToLeft={rightToLeft}
showNowLine={showNowLine}
nowLineColor={nowLineColor}
onDragEvent={onDragEvent}
pageWidth={pageWidth}
dayWidth={dayWidth}
verticalResolution={verticalResolution}
onEditEvent={onEditEvent}
editingEventId={editingEvent}
editEventConfig={editEventConfig}
dragEventConfig={dragEventConfig}
/>
);
}}
horizontal
// eslint-disable-next-line react/jsx-props-no-spreading
{...horizontalScrollProps}
inverted={horizontalInverted}
onMomentumScrollBegin={this.scrollBegun}
onMomentumScrollEnd={this.scrollEnded}
scrollEventThrottle={32}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
x: this.eventsGridScrollX,
<RunGesturesOnJSContext.Provider value={runOnJS}>
<VirtualizedList
data={initialDates}
getItem={(data, index) => data[index]}
getItemCount={(data) => data.length}
getItemLayout={this.getListItemLayout}
keyExtractor={(item) => item}
initialScrollIndex={PAGES_OFFSET}
scrollEnabled={!fixedHorizontally}
onStartShouldSetResponderCapture={() => false}
onMoveShouldSetResponderCapture={() => false}
onResponderTerminationRequest={() => false}
renderItem={({ item }) => {
return (
<Events
times={times}
eventsByDate={eventsByDate}
initialDate={item}
numberOfDays={numberOfDays}
onEventPress={onEventPress}
onEventLongPress={onEventLongPress}
onGridClick={onGridClick}
onGridLongPress={onGridLongPress}
beginAgendaAt={beginAgendaAt}
timeLabelHeight={timeLabelHeight}
EventComponent={EventComponent}
eventContainerStyle={eventContainerStyle}
gridRowStyle={gridRowStyle}
gridColumnStyle={gridColumnStyle}
rightToLeft={rightToLeft}
showNowLine={showNowLine}
nowLineColor={nowLineColor}
onDragEvent={onDragEvent}
pageWidth={pageWidth}
dayWidth={dayWidth}
verticalResolution={verticalResolution}
onEditEvent={onEditEvent}
editingEventId={editingEvent}
editEventConfig={editEventConfig}
dragEventConfig={dragEventConfig}
/>
);
}}
horizontal
// eslint-disable-next-line react/jsx-props-no-spreading
{...horizontalScrollProps}
inverted={horizontalInverted}
onMomentumScrollBegin={this.scrollBegun}
onMomentumScrollEnd={this.scrollEnded}
scrollEventThrottle={32}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
x: this.eventsGridScrollX,
},
},
},
},
],
{ useNativeDriver: false },
)}
ref={this.eventsGridRef}
windowSize={windowSize}
initialNumToRender={initialNumToRender}
maxToRenderPerBatch={maxToRenderPerBatch}
updateCellsBatchingPeriod={updateCellsBatchingPeriod}
removeClippedSubviews={removeClippedSubviews}
disableVirtualization={disableVirtualization}
accessible
accessibilityLabel="Grid with horizontal scroll"
accessibilityHint="Grid with horizontal scroll"
/>
],
{ useNativeDriver: false },
)}
ref={this.eventsGridRef}
windowSize={windowSize}
initialNumToRender={initialNumToRender}
maxToRenderPerBatch={maxToRenderPerBatch}
updateCellsBatchingPeriod={updateCellsBatchingPeriod}
removeClippedSubviews={removeClippedSubviews}
disableVirtualization={disableVirtualization}
accessible
accessibilityLabel="Grid with horizontal scroll"
accessibilityHint="Grid with horizontal scroll"
/>
</RunGesturesOnJSContext.Provider>
</View>
</ScrollView>
</GestureHandlerRootView>
Expand Down Expand Up @@ -832,6 +836,7 @@ WeekView.propTypes = {
updateCellsBatchingPeriod: PropTypes.number,
removeClippedSubviews: PropTypes.bool,
disableVirtualization: PropTypes.bool,
runOnJS: PropTypes.bool,
};

WeekView.defaultProps = {
Expand All @@ -854,4 +859,5 @@ WeekView.defaultProps = {
updateCellsBatchingPeriod: 50, // RN default
removeClippedSubviews: true,
disableVirtualization: false,
runOnJS: false,
};
Loading