Skip to content

Commit bb2004d

Browse files
authored
Android RTL fix for RN73 and above (#2631)
* CalendarList and WeekCalendar - fix android rtl issue for RN73 and above. InfinitList and TimelineList - fix memo and deps * asCalendarConsumer - fix import * fix undefined error
1 parent e94d511 commit bb2004d

File tree

6 files changed

+23
-27
lines changed

6 files changed

+23
-27
lines changed

src/calendar-list/index.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import findIndex from 'lodash/findIndex';
22
import PropTypes from 'prop-types';
33
import XDate from 'xdate';
4-
54
import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
65
import {FlatList, FlatListProps, View, ViewStyle} from 'react-native';
7-
86
import {extractCalendarProps, extractHeaderProps} from '../componentUpdater';
97
import {parseDate, toMarkingFormat, xdateToData} from '../interface';
108
import {page, sameDate, sameMonth} from '../dateutils';
@@ -112,7 +110,7 @@ const CalendarList = (props: CalendarListProps & ContextProp, ref: any) => {
112110

113111
const [currentMonth, setCurrentMonth] = useState(parseDate(current));
114112

115-
const shouldUseAndroidRTLFix = useMemo(() => constants.isAndroidRTL && horizontal, [horizontal]);
113+
const shouldFixRTL = useMemo(() => !constants.isRN73() && constants.isAndroidRTL && horizontal, [horizontal]);
116114
/**
117115
* we render a lot of months in the calendar list and we need to measure the header only once
118116
* so we use this ref to limit the header measurement to the first render
@@ -194,12 +192,12 @@ const CalendarList = (props: CalendarListProps & ContextProp, ref: any) => {
194192
const scrollToMonth = useCallback((date: XDate | string) => {
195193
const scrollTo = parseDate(date);
196194
const diffMonths = Math.round(initialDate?.current?.clone().setDate(1).diffMonths(scrollTo?.clone().setDate(1)));
197-
const scrollAmount = calendarSize * (shouldUseAndroidRTLFix ? pastScrollRange - diffMonths : pastScrollRange + diffMonths);
195+
const scrollAmount = calendarSize * (shouldFixRTL ? pastScrollRange - diffMonths : pastScrollRange + diffMonths);
198196

199197
if (scrollAmount !== 0) {
200198
list?.current?.scrollToOffset({offset: scrollAmount, animated: animateScroll});
201199
}
202-
}, [calendarSize, shouldUseAndroidRTLFix, pastScrollRange, animateScroll]);
200+
}, [calendarSize, shouldFixRTL, pastScrollRange, animateScroll]);
203201

204202
const addMonth = useCallback((count: number) => {
205203
const day = currentMonth?.clone().addMonths(count, true);
@@ -289,7 +287,7 @@ const CalendarList = (props: CalendarListProps & ContextProp, ref: any) => {
289287

290288
const onViewableItemsChanged = useCallback(({viewableItems}: any) => {
291289
const newVisibleMonth = parseDate(viewableItems[0]?.item);
292-
if (shouldUseAndroidRTLFix) {
290+
if (shouldFixRTL) {
293291
const centerIndex = items.findIndex((item) => isEqual(parseDate(current), item));
294292
const adjustedOffset = centerIndex - items.findIndex((item) => isEqual(newVisibleMonth, item));
295293
visibleMonth.current = items[centerIndex + adjustedOffset];
@@ -300,7 +298,7 @@ const CalendarList = (props: CalendarListProps & ContextProp, ref: any) => {
300298
setCurrentMonth(visibleMonth.current);
301299
}
302300
}
303-
}, [items, shouldUseAndroidRTLFix, current]);
301+
}, [items, shouldFixRTL, current]);
304302

305303
const viewabilityConfigCallbackPairs = useRef([
306304
{
@@ -313,7 +311,7 @@ const CalendarList = (props: CalendarListProps & ContextProp, ref: any) => {
313311
<View style={style.current.flatListContainer} testID={testID}>
314312
<FlatList
315313
ref={list}
316-
windowSize={shouldUseAndroidRTLFix ? pastScrollRange + futureScrollRange + 1 : undefined}
314+
windowSize={shouldFixRTL ? pastScrollRange + futureScrollRange + 1 : undefined}
317315
style={listStyle}
318316
showsVerticalScrollIndicator={showScrollIndicator}
319317
showsHorizontalScrollIndicator={showScrollIndicator}

src/commons/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const isIOS = Platform.OS === 'ios';
88
const screenAspectRatio = screenWidth < screenHeight ? screenHeight / screenWidth : screenWidth / screenHeight;
99
const isTablet = (Platform as PlatformIOSStatic).isPad || (screenAspectRatio < 1.6 && Math.max(screenWidth, screenHeight) >= 900);
1010
const isAndroidRTL = isAndroid && isRTL;
11-
const isRN73 = () => Platform.constants.reactNativeVersion.minor >= 73;
11+
const isRN73 = () => Platform.constants.reactNativeVersion?.minor >= 73;
1212

1313
export default {
1414
screenWidth,

src/expandableCalendar/Context/asCalendarConsumer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, {Component, Ref} from 'react';
22
import hoistNonReactStatic from 'hoist-non-react-statics';
3-
import CalendarContext from '.';
3+
import CalendarContext from './index';
44

55

66
function asCalendarConsumer<PROPS>(WrappedComponent: React.ComponentType<any>): React.ComponentClass<PROPS> {

src/expandableCalendar/WeekCalendar/index.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import XDate from 'xdate';
2-
32
import React, {useCallback, useContext, useMemo, useRef, useState} from 'react';
43
import {FlatList, View, ViewToken} from 'react-native';
5-
64
import {sameWeek, onSameDateRange, getWeekDates} from '../../dateutils';
75
import {toMarkingFormat} from '../../interface';
86
import {DateData, MarkedDates} from '../../types';
@@ -50,6 +48,8 @@ const WeekCalendar = (props: WeekCalendarProps) => {
5048
const list = useRef<FlatList>(null);
5149
const currentIndex = useRef(NUMBER_OF_PAGES);
5250

51+
const shouldFixRTL = useMemo(() => !constants.isRN73() && constants.isAndroidRTL, []);
52+
5353
useDidUpdate(() => {
5454
items.current = getDatesArray(date, firstDay, numberOfDays);
5555
setListData(items.current);
@@ -69,7 +69,7 @@ const WeekCalendar = (props: WeekCalendarProps) => {
6969
}) :
7070
sameWeek(item, date, firstDay));
7171
if (pageIndex !== currentIndex.current) {
72-
const adjustedIndexFrScroll = (constants.isAndroidRTL && !constants.isRN73()) ? NUM_OF_ITEMS - 1 - pageIndex : pageIndex;
72+
const adjustedIndexFrScroll = shouldFixRTL ? NUM_OF_ITEMS - 1 - pageIndex : pageIndex;
7373
if (pageIndex >= 0) {
7474
visibleWeek.current = items.current[adjustedIndexFrScroll];
7575
currentIndex.current = adjustedIndexFrScroll;
@@ -80,7 +80,7 @@ const WeekCalendar = (props: WeekCalendarProps) => {
8080
pageIndex <= 0 ? onEndReached() : list?.current?.scrollToIndex({index: adjustedIndexFrScroll, animated: false});
8181
}
8282
}
83-
}, [date, updateSource]);
83+
}, [date, updateSource, shouldFixRTL]);
8484

8585
const containerWidth = useMemo(() => {
8686
return calendarWidth ?? constants.screenWidth;
@@ -179,7 +179,7 @@ const WeekCalendar = (props: WeekCalendarProps) => {
179179
const currItems = items.current;
180180
const newDate = viewableItems[0]?.item;
181181
if (newDate !== visibleWeek.current) {
182-
if (constants.isAndroidRTL) {
182+
if (shouldFixRTL) {
183183
//in android RTL the item we see is the one in the opposite direction
184184
const newDateOffset = -1 * (NUMBER_OF_PAGES - currItems.indexOf(newDate));
185185
const adjustedNewDate = currItems[NUMBER_OF_PAGES - newDateOffset];
@@ -198,7 +198,7 @@ const WeekCalendar = (props: WeekCalendarProps) => {
198198
}
199199
}
200200
}
201-
}, [onEndReached]);
201+
}, [onEndReached, shouldFixRTL]);
202202

203203
const viewabilityConfigCallbackPairs = useRef([{
204204
viewabilityConfig: {

src/infinite-list/index.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import inRange from 'lodash/inRange';
22
import debounce from 'lodash/debounce';
33
import noop from 'lodash/noop';
4-
54
import React, {forwardRef, useCallback, useEffect, useMemo, useRef} from 'react';
65
import {ScrollViewProps} from 'react-native';
76
import {DataProvider, LayoutProvider, RecyclerListView, RecyclerListViewProps} from 'recyclerlistview';
8-
97
import constants from '../commons/constants';
108
import {useCombinedRefs} from '../hooks';
119

@@ -70,10 +68,10 @@ const InfiniteList = (props: InfiniteListProps, ref: any) => {
7068
}
7169
)
7270
);
73-
71+
7472
const shouldFixRTL = useMemo(() => {
7573
return isHorizontal && constants.isRTL && (constants.isRN73() || constants.isAndroid);
76-
}, []);
74+
}, [isHorizontal]);
7775

7876
const listRef = useCombinedRefs(ref);
7977
const pageIndex = useRef<number>();
@@ -93,7 +91,7 @@ const InfiniteList = (props: InfiniteListProps, ref: any) => {
9391
// @ts-expect-error
9492
listRef.current?.scrollToOffset?.(x, y, false);
9593
}, 0);
96-
}, [data, disableScrollOnDataChange]);
94+
}, [data, disableScrollOnDataChange, isHorizontal]);
9795

9896
const _onScroll = useCallback(
9997
(event, offsetX, offsetY) => {
@@ -133,7 +131,7 @@ const InfiniteList = (props: InfiniteListProps, ref: any) => {
133131

134132
onScroll?.(event, offsetX, offsetY);
135133
},
136-
[onScroll, onPageChange, data.length, reloadPagesDebounce]
134+
[onScroll, onPageChange, data.length, reloadPagesDebounce, isHorizontal, shouldFixRTL]
137135
);
138136

139137
const onMomentumScrollEnd = useCallback(

src/timeline-list/index.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import throttle from 'lodash/throttle';
22
import flatten from 'lodash/flatten';
33
import dropRight from 'lodash/dropRight';
4-
54
import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
6-
75
import {isToday, generateDay} from '../dateutils';
86
import InfiniteList from '../infinite-list';
97
import Context from '../expandableCalendar/Context';
@@ -53,7 +51,7 @@ export interface TimelineListProps {
5351

5452
const TimelineList = (props: TimelineListProps) => {
5553
const {timelineProps, events, renderItem, showNowIndicator, scrollToFirst, scrollToNow, initialTime} = props;
56-
const shouldFixRTL = constants.isRTL && (constants.isRN73() || constants.isAndroid); // isHorizontal = true
54+
const shouldFixRTL = useMemo(() => constants.isRTL && (constants.isRN73() || constants.isAndroid), []); // isHorizontal = true
5755
const {date, updateSource, setDate, numberOfDays = 1, timelineLeftInset} = useContext(Context);
5856
const listRef = useRef<any>();
5957
const prevDate = useRef(date);
@@ -75,7 +73,9 @@ const TimelineList = (props: TimelineListProps) => {
7573
prevDate.current = date;
7674
}, [updateSource]);
7775

78-
const initialOffset = useMemo(() => shouldFixRTL ? constants.screenWidth * (PAGES_COUNT - INITIAL_PAGE - 1) : constants.screenWidth * INITIAL_PAGE, []);
76+
const initialOffset = useMemo(() => {
77+
return shouldFixRTL ? constants.screenWidth * (PAGES_COUNT - INITIAL_PAGE - 1) : constants.screenWidth * INITIAL_PAGE;
78+
}, [shouldFixRTL]);
7979

8080
useEffect(() => {
8181
if (date !== prevDate.current) {
@@ -102,7 +102,7 @@ const TimelineList = (props: TimelineListProps) => {
102102
setDate(newDate, UpdateSources.LIST_DRAG);
103103
}
104104
}, 0),
105-
[pages]
105+
[pages, shouldFixRTL]
106106
);
107107

108108
const onReachNearEdge = useCallback(() => {

0 commit comments

Comments
 (0)