From 72fc5647fb9969f233acb66d56bc0c5cc599d1bb Mon Sep 17 00:00:00 2001 From: Carlos Barros <765936+barros001@users.noreply.github.com> Date: Mon, 20 Nov 2023 18:22:16 -0500 Subject: [PATCH 001/152] extract hardcoded weekStartsOn into a method inside DateUtils --- .../CalendarPicker/generateMonthMatrix.js | 8 ++++-- src/libs/DateUtils.ts | 26 ++++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js b/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js index a3497654feec..bb5a66c147a1 100644 --- a/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js +++ b/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js @@ -1,4 +1,5 @@ import {addDays, format, getDay, getDaysInMonth, startOfMonth} from 'date-fns'; +import {getWeekStartsAndEndsOn} from '@libs/DateUtils'; /** * Generates a matrix representation of a month's calendar given the year and month. @@ -24,6 +25,9 @@ export default function generateMonthMatrix(year, month) { throw new Error('Month cannot be greater than 11'); } + // Get the week day for the start and end of week + const {weekStartsOn, weekEndsOn} = getWeekStartsAndEndsOn(); + // Get the number of days in the month and the first day of the month const firstDayOfMonth = startOfMonth(new Date(year, month, 1)); const daysInMonth = getDaysInMonth(firstDayOfMonth); @@ -33,7 +37,7 @@ export default function generateMonthMatrix(year, month) { let currentWeek = []; // Add null values for days before the first day of the month - for (let i = 0; i < getDay(firstDayOfMonth); i++) { + for (let i = weekStartsOn; i < getDay(firstDayOfMonth); i++) { currentWeek.push(null); } @@ -43,7 +47,7 @@ export default function generateMonthMatrix(year, month) { currentWeek.push(Number(format(currentDate, 'd'))); // Start a new row when the current week is full - if (getDay(currentDate) === 6) { + if (getDay(currentDate) === weekEndsOn) { matrix.push(currentWeek); currentWeek = []; } diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 80eae24d9367..6dcfaf758725 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -29,6 +29,11 @@ import * as CurrentDate from './actions/CurrentDate'; import * as Localize from './Localize'; type Locale = ValueOf; +type WeekDay = 0 | 1 | 2 | 3 | 4 | 5 | 6; +type WeekStartsAndEndsOn = { + weekStartsOn: WeekDay; + weekEndsOn: WeekDay; +}; let currentUserAccountID: number | undefined; Onyx.connect({ @@ -60,6 +65,16 @@ Onyx.connect({ }, }); +/** + * Get the day of the week that the week starts and ends on + */ +function getWeekStartsAndEndsOn(): WeekStartsAndEndsOn { + return { + weekStartsOn: 1, // Assuming Monday is the start of the week + weekEndsOn: 0, // Assuming Sunday is the end of the week + }; +} + /** * Gets the locale string and setting default locale for date-fns */ @@ -145,9 +160,10 @@ function datetimeToCalendarTime(locale: Locale, datetime: string, includeTimeZon let tomorrowAt = Localize.translate(locale, 'common.tomorrowAt'); let yesterdayAt = Localize.translate(locale, 'common.yesterdayAt'); const at = Localize.translate(locale, 'common.conjunctionAt'); + const {weekStartsOn} = getWeekStartsAndEndsOn(); - const startOfCurrentWeek = startOfWeek(new Date(), {weekStartsOn: 1}); // Assuming Monday is the start of the week - const endOfCurrentWeek = endOfWeek(new Date(), {weekStartsOn: 1}); // Assuming Monday is the start of the week + const startOfCurrentWeek = startOfWeek(new Date(), {weekStartsOn}); + const endOfCurrentWeek = endOfWeek(new Date(), {weekStartsOn}); if (isLowercase) { todayAt = todayAt.toLowerCase(); @@ -284,8 +300,9 @@ function getDaysOfWeek(preferredLocale: Locale): string[] { if (preferredLocale) { setLocale(preferredLocale); } - const startOfCurrentWeek = startOfWeek(new Date(), {weekStartsOn: 1}); // Assuming Monday is the start of the week - const endOfCurrentWeek = endOfWeek(new Date(), {weekStartsOn: 1}); // Assuming Monday is the start of the week + const {weekStartsOn} = getWeekStartsAndEndsOn(); + const startOfCurrentWeek = startOfWeek(new Date(), {weekStartsOn}); + const endOfCurrentWeek = endOfWeek(new Date(), {weekStartsOn}); const daysOfWeek = eachDayOfInterval({start: startOfCurrentWeek, end: endOfCurrentWeek}); // eslint-disable-next-line rulesdir/prefer-underscore-method @@ -413,6 +430,7 @@ const DateUtils = { getMonthNames, getDaysOfWeek, formatWithUTCTimeZone, + weekStartsAndEndsOn: getWeekStartsAndEndsOn, }; export default DateUtils; From 3dd8f85bb79506399093a75a22e558f3d07f3aa7 Mon Sep 17 00:00:00 2001 From: Carlos Barros <765936+barros001@users.noreply.github.com> Date: Mon, 20 Nov 2023 18:26:56 -0500 Subject: [PATCH 002/152] fixed usage of DateUtils lib --- .../NewDatePicker/CalendarPicker/generateMonthMatrix.js | 4 ++-- src/libs/DateUtils.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js b/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js index bb5a66c147a1..600ac0b4fd21 100644 --- a/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js +++ b/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js @@ -1,5 +1,5 @@ import {addDays, format, getDay, getDaysInMonth, startOfMonth} from 'date-fns'; -import {getWeekStartsAndEndsOn} from '@libs/DateUtils'; +import DateUtils from '@libs/DateUtils'; /** * Generates a matrix representation of a month's calendar given the year and month. @@ -26,7 +26,7 @@ export default function generateMonthMatrix(year, month) { } // Get the week day for the start and end of week - const {weekStartsOn, weekEndsOn} = getWeekStartsAndEndsOn(); + const {weekStartsOn, weekEndsOn} = DateUtils.getWeekStartsAndEndsOn(); // Get the number of days in the month and the first day of the month const firstDayOfMonth = startOfMonth(new Date(year, month, 1)); diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 6dcfaf758725..d8803e301cee 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -430,7 +430,7 @@ const DateUtils = { getMonthNames, getDaysOfWeek, formatWithUTCTimeZone, - weekStartsAndEndsOn: getWeekStartsAndEndsOn, + getWeekStartsAndEndsOn, }; export default DateUtils; From a13abd6d8c1b3c954a02cfa3b3da6ce7fdd38bd4 Mon Sep 17 00:00:00 2001 From: Carlos Barros <765936+barros001@users.noreply.github.com> Date: Tue, 21 Nov 2023 10:42:50 -0500 Subject: [PATCH 003/152] moved week starts on into a constant --- src/CONST.ts | 1 + .../CalendarPicker/generateMonthMatrix.js | 3 +- src/libs/DateUtils.ts | 29 ++++++++++--------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index c29a7c51e6ef..d1f0ed6a56c2 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -858,6 +858,7 @@ const CONST = { MAX_PENDING_TIME_MS: 10 * 1000, MAX_REQUEST_RETRIES: 10, }, + WEEK_STARTS_ON: 1, // Monday DEFAULT_TIME_ZONE: {automatic: true, selected: 'America/Los_Angeles'}, DEFAULT_ACCOUNT_DATA: {errors: null, success: '', isLoading: false}, DEFAULT_CLOSE_ACCOUNT_DATA: {errors: null, success: '', isLoading: false}, diff --git a/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js b/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js index 600ac0b4fd21..9e2ae4195a7c 100644 --- a/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js +++ b/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js @@ -26,7 +26,8 @@ export default function generateMonthMatrix(year, month) { } // Get the week day for the start and end of week - const {weekStartsOn, weekEndsOn} = DateUtils.getWeekStartsAndEndsOn(); + const weekStartsOn = DateUtils.getWeekStartsOn(); + const weekEndsOn = DateUtils.getWeekEndsOn(); // Get the number of days in the month and the first day of the month const firstDayOfMonth = startOfMonth(new Date(year, month, 1)); diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index d8803e301cee..d7b6d9132808 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -30,10 +30,6 @@ import * as Localize from './Localize'; type Locale = ValueOf; type WeekDay = 0 | 1 | 2 | 3 | 4 | 5 | 6; -type WeekStartsAndEndsOn = { - weekStartsOn: WeekDay; - weekEndsOn: WeekDay; -}; let currentUserAccountID: number | undefined; Onyx.connect({ @@ -66,13 +62,19 @@ Onyx.connect({ }); /** - * Get the day of the week that the week starts and ends on + * Get the day of the week that the week starts on + */ +function getWeekStartsOn(): WeekDay { + return CONST.WEEK_STARTS_ON; +} + +/** + * Get the day of the week that the week ends on */ -function getWeekStartsAndEndsOn(): WeekStartsAndEndsOn { - return { - weekStartsOn: 1, // Assuming Monday is the start of the week - weekEndsOn: 0, // Assuming Sunday is the end of the week - }; +function getWeekEndsOn(): WeekDay { + const weekStartsOn = getWeekStartsOn(); + + return weekStartsOn === 0 ? 6 : ((weekStartsOn - 1) as WeekDay); } /** @@ -160,7 +162,7 @@ function datetimeToCalendarTime(locale: Locale, datetime: string, includeTimeZon let tomorrowAt = Localize.translate(locale, 'common.tomorrowAt'); let yesterdayAt = Localize.translate(locale, 'common.yesterdayAt'); const at = Localize.translate(locale, 'common.conjunctionAt'); - const {weekStartsOn} = getWeekStartsAndEndsOn(); + const weekStartsOn = getWeekStartsOn(); const startOfCurrentWeek = startOfWeek(new Date(), {weekStartsOn}); const endOfCurrentWeek = endOfWeek(new Date(), {weekStartsOn}); @@ -300,7 +302,7 @@ function getDaysOfWeek(preferredLocale: Locale): string[] { if (preferredLocale) { setLocale(preferredLocale); } - const {weekStartsOn} = getWeekStartsAndEndsOn(); + const weekStartsOn = getWeekStartsOn(); const startOfCurrentWeek = startOfWeek(new Date(), {weekStartsOn}); const endOfCurrentWeek = endOfWeek(new Date(), {weekStartsOn}); const daysOfWeek = eachDayOfInterval({start: startOfCurrentWeek, end: endOfCurrentWeek}); @@ -430,7 +432,8 @@ const DateUtils = { getMonthNames, getDaysOfWeek, formatWithUTCTimeZone, - getWeekStartsAndEndsOn, + getWeekStartsOn, + getWeekEndsOn, }; export default DateUtils; From 5b6b2ff667f574141215f26a87cb8db110a3d9e5 Mon Sep 17 00:00:00 2001 From: Carlos Barros <765936+barros001@users.noreply.github.com> Date: Tue, 21 Nov 2023 10:43:14 -0500 Subject: [PATCH 004/152] updated generateMonthMatrix test --- tests/unit/generateMonthMatrixTest.js | 62 +++++++++++++-------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/tests/unit/generateMonthMatrixTest.js b/tests/unit/generateMonthMatrixTest.js index 9f565a6e3a78..dc3df145c0b5 100644 --- a/tests/unit/generateMonthMatrixTest.js +++ b/tests/unit/generateMonthMatrixTest.js @@ -3,67 +3,67 @@ import generateMonthMatrix from '../../src/components/NewDatePicker/CalendarPick describe('generateMonthMatrix', () => { it('returns the correct matrix for January 2022', () => { const expected = [ - [null, null, null, null, null, null, 1], - [2, 3, 4, 5, 6, 7, 8], - [9, 10, 11, 12, 13, 14, 15], - [16, 17, 18, 19, 20, 21, 22], - [23, 24, 25, 26, 27, 28, 29], - [30, 31, null, null, null, null, null], + [null, null, null, null, null, 1, 2], + [3, 4, 5, 6, 7, 8, 9], + [10, 11, 12, 13, 14, 15, 16], + [17, 18, 19, 20, 21, 22, 23], + [24, 25, 26, 27, 28, 29, 30], + [31, null, null, null, null, null, null], ]; expect(generateMonthMatrix(2022, 0)).toEqual(expected); }); it('returns the correct matrix for February 2022', () => { const expected = [ - [null, null, 1, 2, 3, 4, 5], - [6, 7, 8, 9, 10, 11, 12], - [13, 14, 15, 16, 17, 18, 19], - [20, 21, 22, 23, 24, 25, 26], - [27, 28, null, null, null, null, null], + [null, 1, 2, 3, 4, 5, 6], + [7, 8, 9, 10, 11, 12, 13], + [14, 15, 16, 17, 18, 19, 20], + [21, 22, 23, 24, 25, 26, 27], + [28, null, null, null, null, null, null], ]; expect(generateMonthMatrix(2022, 1)).toEqual(expected); }); it('returns the correct matrix for leap year February 2020', () => { const expected = [ - [null, null, null, null, null, null, 1], - [2, 3, 4, 5, 6, 7, 8], - [9, 10, 11, 12, 13, 14, 15], - [16, 17, 18, 19, 20, 21, 22], - [23, 24, 25, 26, 27, 28, 29], + [null, null, null, null, null, 1, 2], + [3, 4, 5, 6, 7, 8, 9], + [10, 11, 12, 13, 14, 15, 16], + [17, 18, 19, 20, 21, 22, 23], + [24, 25, 26, 27, 28, 29, null], ]; expect(generateMonthMatrix(2020, 1)).toEqual(expected); }); it('returns the correct matrix for March 2022', () => { const expected = [ - [null, null, 1, 2, 3, 4, 5], - [6, 7, 8, 9, 10, 11, 12], - [13, 14, 15, 16, 17, 18, 19], - [20, 21, 22, 23, 24, 25, 26], - [27, 28, 29, 30, 31, null, null], + [null, 1, 2, 3, 4, 5, 6], + [7, 8, 9, 10, 11, 12, 13], + [14, 15, 16, 17, 18, 19, 20], + [21, 22, 23, 24, 25, 26, 27], + [28, 29, 30, 31, null, null, null], ]; expect(generateMonthMatrix(2022, 2)).toEqual(expected); }); it('returns the correct matrix for April 2022', () => { const expected = [ - [null, null, null, null, null, 1, 2], - [3, 4, 5, 6, 7, 8, 9], - [10, 11, 12, 13, 14, 15, 16], - [17, 18, 19, 20, 21, 22, 23], - [24, 25, 26, 27, 28, 29, 30], + [null, null, null, null, 1, 2, 3], + [4, 5, 6, 7, 8, 9, 10], + [11, 12, 13, 14, 15, 16, 17], + [18, 19, 20, 21, 22, 23, 24], + [25, 26, 27, 28, 29, 30, null], ]; expect(generateMonthMatrix(2022, 3)).toEqual(expected); }); it('returns the correct matrix for December 2022', () => { const expected = [ - [null, null, null, null, 1, 2, 3], - [4, 5, 6, 7, 8, 9, 10], - [11, 12, 13, 14, 15, 16, 17], - [18, 19, 20, 21, 22, 23, 24], - [25, 26, 27, 28, 29, 30, 31], + [null, null, null, 1, 2, 3, 4], + [5, 6, 7, 8, 9, 10, 11], + [12, 13, 14, 15, 16, 17, 18], + [19, 20, 21, 22, 23, 24, 25], + [26, 27, 28, 29, 30, 31, null], ]; expect(generateMonthMatrix(2022, 11)).toEqual(expected); }); From aa015de65f6854c8c585464e7939bb9b33c52c39 Mon Sep 17 00:00:00 2001 From: Carlos Barros <765936+barros001@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:23:54 -0500 Subject: [PATCH 005/152] updated how empty days are added at the beginning of the month --- .../CalendarPicker/generateMonthMatrix.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js b/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js index 9e2ae4195a7c..ecf338d36424 100644 --- a/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js +++ b/src/components/NewDatePicker/CalendarPicker/generateMonthMatrix.js @@ -25,8 +25,7 @@ export default function generateMonthMatrix(year, month) { throw new Error('Month cannot be greater than 11'); } - // Get the week day for the start and end of week - const weekStartsOn = DateUtils.getWeekStartsOn(); + // Get the week day for the end of week const weekEndsOn = DateUtils.getWeekEndsOn(); // Get the number of days in the month and the first day of the month @@ -37,11 +36,6 @@ export default function generateMonthMatrix(year, month) { const matrix = []; let currentWeek = []; - // Add null values for days before the first day of the month - for (let i = weekStartsOn; i < getDay(firstDayOfMonth); i++) { - currentWeek.push(null); - } - // Add calendar days to the matrix for (let i = 1; i <= daysInMonth; i++) { const currentDate = addDays(firstDayOfMonth, i - 1); @@ -61,5 +55,11 @@ export default function generateMonthMatrix(year, month) { } matrix.push(currentWeek); } + + // Add null values for days before the first day of the month + for (let i = matrix[0].length; i < 7; i++) { + matrix[0].unshift(null); + } + return matrix; } From 45c6f7878ea5edb01435409fa2f28bea06b94a00 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 22 Nov 2023 11:40:38 +0700 Subject: [PATCH 006/152] fix: 30726 A blank spot appears after deleting a money request --- src/pages/home/report/ReportActionsList.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index e1230d7219db..e9ecbd1bdeab 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -21,6 +21,7 @@ import useThemeStyles from '@styles/useThemeStyles'; import variables from '@styles/variables'; import * as Report from '@userActions/Report'; import CONST from '@src/CONST'; +import usePrevious from '@hooks/usePrevious'; import FloatingMessageCounter from './FloatingMessageCounter'; import ListBoundaryLoader from './ListBoundaryLoader/ListBoundaryLoader'; import reportActionPropTypes from './reportActionPropTypes'; @@ -160,6 +161,8 @@ function ReportActionsList({ const reportActionSize = useRef(sortedReportActions.length); const lastReadTimeRef = useRef(report.lastReadTime); + const previousLastIndex = usePrevious(sortedReportActions[0].reportActionID) + const linkedReportActionID = lodashGet(route, 'params.reportActionID', ''); // This state is used to force a re-render when the user manually marks a message as unread @@ -174,6 +177,14 @@ function ReportActionsList({ opacity.value = withTiming(1, {duration: 100}); }, [opacity]); + useEffect(()=>{ + if(previousLastIndex === sortedReportActions[0].reportActionID || reportActionSize.current <= sortedReportActions.length){ + return; + } + reportScrollManager.scrollToBottom(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [previousLastIndex, sortedReportActions[0].reportActionID]) + useEffect(() => { // If the reportID changes, we reset the userActiveSince to null, we need to do it because // the parent component is sending the previous reportID even when the user isn't active From fd105ab93551e48ae230fcf2f988566180e6bce2 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 22 Nov 2023 14:30:54 +0700 Subject: [PATCH 007/152] format --- src/pages/home/report/ReportActionsList.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index e9ecbd1bdeab..81a481e667cb 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -11,6 +11,7 @@ import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultPro import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; +import usePrevious from '@hooks/usePrevious'; import useReportScrollManager from '@hooks/useReportScrollManager'; import compose from '@libs/compose'; import DateUtils from '@libs/DateUtils'; @@ -21,7 +22,6 @@ import useThemeStyles from '@styles/useThemeStyles'; import variables from '@styles/variables'; import * as Report from '@userActions/Report'; import CONST from '@src/CONST'; -import usePrevious from '@hooks/usePrevious'; import FloatingMessageCounter from './FloatingMessageCounter'; import ListBoundaryLoader from './ListBoundaryLoader/ListBoundaryLoader'; import reportActionPropTypes from './reportActionPropTypes'; @@ -161,7 +161,7 @@ function ReportActionsList({ const reportActionSize = useRef(sortedReportActions.length); const lastReadTimeRef = useRef(report.lastReadTime); - const previousLastIndex = usePrevious(sortedReportActions[0].reportActionID) + const previousLastIndex = usePrevious(sortedReportActions[0].reportActionID); const linkedReportActionID = lodashGet(route, 'params.reportActionID', ''); @@ -177,14 +177,14 @@ function ReportActionsList({ opacity.value = withTiming(1, {duration: 100}); }, [opacity]); - useEffect(()=>{ - if(previousLastIndex === sortedReportActions[0].reportActionID || reportActionSize.current <= sortedReportActions.length){ + useEffect(() => { + if (previousLastIndex === sortedReportActions[0].reportActionID || reportActionSize.current <= sortedReportActions.length) { return; } reportScrollManager.scrollToBottom(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [previousLastIndex, sortedReportActions[0].reportActionID]) - + }, [previousLastIndex, sortedReportActions[0].reportActionID]); + useEffect(() => { // If the reportID changes, we reset the userActiveSince to null, we need to do it because // the parent component is sending the previous reportID even when the user isn't active From 7dc7bfa3d4a60f4d95e1ebc2f9abfa69e203bbed Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 22 Nov 2023 15:38:39 +0700 Subject: [PATCH 008/152] refactor --- src/pages/home/report/ReportActionsList.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index 81a481e667cb..c02c1c162946 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -11,7 +11,6 @@ import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultPro import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; -import usePrevious from '@hooks/usePrevious'; import useReportScrollManager from '@hooks/useReportScrollManager'; import compose from '@libs/compose'; import DateUtils from '@libs/DateUtils'; @@ -161,7 +160,9 @@ function ReportActionsList({ const reportActionSize = useRef(sortedReportActions.length); const lastReadTimeRef = useRef(report.lastReadTime); - const previousLastIndex = usePrevious(sortedReportActions[0].reportActionID); + const lastActionIndex = lodashGet(sortedReportActions, [0, 'reportActionID']); + + const previousLastIndex = useRef(lastActionIndex); const linkedReportActionID = lodashGet(route, 'params.reportActionID', ''); @@ -178,12 +179,12 @@ function ReportActionsList({ }, [opacity]); useEffect(() => { - if (previousLastIndex === sortedReportActions[0].reportActionID || reportActionSize.current <= sortedReportActions.length) { + if (previousLastIndex.current === lastActionIndex || reportActionSize.current <= sortedReportActions.length) { return; } reportScrollManager.scrollToBottom(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [previousLastIndex, sortedReportActions[0].reportActionID]); + previousLastIndex.current = lastActionIndex; + }, [lastActionIndex, sortedReportActions.length, reportScrollManager]); useEffect(() => { // If the reportID changes, we reset the userActiveSince to null, we need to do it because From 0c45632a043ae8127c9fb0fdeac46e96d1dadb1e Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 22 Nov 2023 15:40:34 +0700 Subject: [PATCH 009/152] refactor --- src/pages/home/report/ReportActionsList.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index c02c1c162946..1575f6054661 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -179,10 +179,9 @@ function ReportActionsList({ }, [opacity]); useEffect(() => { - if (previousLastIndex.current === lastActionIndex || reportActionSize.current <= sortedReportActions.length) { - return; + if (previousLastIndex.current !== lastActionIndex && reportActionSize.current > sortedReportActions.length) { + reportScrollManager.scrollToBottom(); } - reportScrollManager.scrollToBottom(); previousLastIndex.current = lastActionIndex; }, [lastActionIndex, sortedReportActions.length, reportScrollManager]); From ee63ef7d92f619ace709894b84c37e96640d4b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20=27fvlvte=27=20Fa=C5=82at?= Date: Wed, 22 Nov 2023 14:41:21 +0100 Subject: [PATCH 010/152] Migrated ConfirmContent to typescript. --- .../{ConfirmContent.js => ConfirmContent.tsx} | 77 ++++++------------- 1 file changed, 25 insertions(+), 52 deletions(-) rename src/components/{ConfirmContent.js => ConfirmContent.tsx} (67%) diff --git a/src/components/ConfirmContent.js b/src/components/ConfirmContent.tsx similarity index 67% rename from src/components/ConfirmContent.js rename to src/components/ConfirmContent.tsx index ff8ee4f861a4..317d48f4954a 100644 --- a/src/components/ConfirmContent.js +++ b/src/components/ConfirmContent.tsx @@ -1,7 +1,5 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import {View} from 'react-native'; -import _ from 'underscore'; +import React, {ReactNode} from 'react'; +import {StyleProp, TextStyle, View, ViewStyle} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@styles/useThemeStyles'; @@ -11,82 +9,60 @@ import Header from './Header'; import Icon from './Icon'; import Text from './Text'; -const propTypes = { +type ConfirmContentProps = { /** Title of the modal */ - title: PropTypes.string.isRequired, + title: string, /** A callback to call when the form has been submitted */ - onConfirm: PropTypes.func.isRequired, + onConfirm: (...args: unknown[]) => unknown, /** A callback to call when the form has been closed */ - onCancel: PropTypes.func, + onCancel: (...args: unknown[]) => unknown, /** Confirm button text */ - confirmText: PropTypes.string, + confirmText: string, /** Cancel button text */ - cancelText: PropTypes.string, + cancelText: string, /** Modal content text/element */ - prompt: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), + prompt: string | Element, /** Whether we should use the success button color */ - success: PropTypes.bool, + success: boolean, /** Whether we should use the danger button color. Use if the action is destructive */ - danger: PropTypes.bool, + danger: boolean, /** Whether we should disable the confirm button when offline */ - shouldDisableConfirmButtonWhenOffline: PropTypes.bool, + shouldDisableConfirmButtonWhenOffline: boolean, /** Whether we should show the cancel button */ - shouldShowCancelButton: PropTypes.bool, + shouldShowCancelButton: boolean, /** Icon to display above the title */ - iconSource: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), + iconSource: string | ((props: unknown) => ReactNode), /** Whether to center the icon / text content */ - shouldCenterContent: PropTypes.bool, + shouldCenterContent: boolean, /** Whether to stack the buttons */ - shouldStackButtons: PropTypes.bool, + shouldStackButtons: boolean, /** Styles for title */ - // eslint-disable-next-line react/forbid-prop-types - titleStyles: PropTypes.arrayOf(PropTypes.object), + titleStyles: Array>, /** Styles for prompt */ - // eslint-disable-next-line react/forbid-prop-types - promptStyles: PropTypes.arrayOf(PropTypes.object), + promptStyles: Array>, /** Styles for view */ - // eslint-disable-next-line react/forbid-prop-types - contentStyles: PropTypes.arrayOf(PropTypes.object), + contentStyles: Array>, /** Styles for icon */ - // eslint-disable-next-line react/forbid-prop-types - iconAdditionalStyles: PropTypes.arrayOf(PropTypes.object), + iconAdditionalStyles: Array>, }; -const defaultProps = { - confirmText: '', - cancelText: '', - prompt: '', - success: true, - danger: false, - onCancel: () => {}, - shouldDisableConfirmButtonWhenOffline: false, - shouldShowCancelButton: true, - contentStyles: [], - iconSource: null, - shouldCenterContent: false, - shouldStackButtons: true, - titleStyles: [], - promptStyles: [], - iconAdditionalStyles: [], -}; - -function ConfirmContent(props) { +function ConfirmContent(props: ConfirmContentProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const {isOffline} = useNetwork(); @@ -96,8 +72,8 @@ function ConfirmContent(props) { return ( - {!_.isEmpty(props.iconSource) || - (_.isFunction(props.iconSource) && ( + {(Object.keys(props.iconSource).length !== 0) || + (typeof props.iconSource === "function") && ( - ))} + )}
- - {_.isString(props.prompt) ? {props.prompt} : props.prompt} + {typeof props.prompt === "string" ? {props.prompt} : props.prompt} {props.shouldStackButtons ? ( @@ -163,7 +138,5 @@ function ConfirmContent(props) { ); } -ConfirmContent.propTypes = propTypes; -ConfirmContent.defaultProps = defaultProps; ConfirmContent.displayName = 'ConfirmContent'; export default ConfirmContent; From e304bb9f57bfee03c291ee49380cf7b3c484d63f Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 27 Nov 2023 10:10:16 +0700 Subject: [PATCH 011/152] remove autoScrollToTopThreshold --- src/components/InvertedFlatList/BaseInvertedFlatList.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/InvertedFlatList/BaseInvertedFlatList.js b/src/components/InvertedFlatList/BaseInvertedFlatList.js index 4206d5086a9e..abfad0f04be1 100644 --- a/src/components/InvertedFlatList/BaseInvertedFlatList.js +++ b/src/components/InvertedFlatList/BaseInvertedFlatList.js @@ -2,8 +2,6 @@ import PropTypes from 'prop-types'; import React, {forwardRef} from 'react'; import FlatList from '@components/FlatList'; -const AUTOSCROLL_TO_TOP_THRESHOLD = 128; - const propTypes = { /** Same as FlatList can be any array of anything */ // eslint-disable-next-line react/forbid-prop-types @@ -25,7 +23,6 @@ const BaseInvertedFlatList = forwardRef((props, ref) => ( windowSize={15} maintainVisibleContentPosition={{ minIndexForVisible: 0, - autoscrollToTopThreshold: AUTOSCROLL_TO_TOP_THRESHOLD, }} inverted /> From a763f0004c91f5702e6f6e2a4d53c6fea7add3ab Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Wed, 29 Nov 2023 10:56:13 +0100 Subject: [PATCH 012/152] migrate PopoverWithoutOverlay.js to TypeScript --- src/components/Modal/types.ts | 2 +- src/components/PopoverWithoutOverlay/index.js | 109 ------------------ .../PopoverWithoutOverlay/index.tsx | 107 +++++++++++++++++ src/components/PopoverWithoutOverlay/types.ts | 28 +++++ 4 files changed, 136 insertions(+), 110 deletions(-) delete mode 100644 src/components/PopoverWithoutOverlay/index.js create mode 100644 src/components/PopoverWithoutOverlay/index.tsx create mode 100644 src/components/PopoverWithoutOverlay/types.ts diff --git a/src/components/Modal/types.ts b/src/components/Modal/types.ts index 3fa60e6ac765..bf1a34d9ca94 100644 --- a/src/components/Modal/types.ts +++ b/src/components/Modal/types.ts @@ -23,7 +23,7 @@ type BaseModalProps = WindowDimensionsProps & shouldSetModalVisibility?: boolean; /** Callback method fired when the user requests to close the modal */ - onClose: () => void; + onClose: (ref?: React.RefObject) => void; /** State that determines whether to display the modal or not */ isVisible: boolean; diff --git a/src/components/PopoverWithoutOverlay/index.js b/src/components/PopoverWithoutOverlay/index.js deleted file mode 100644 index 8b9dd4ac7a61..000000000000 --- a/src/components/PopoverWithoutOverlay/index.js +++ /dev/null @@ -1,109 +0,0 @@ -import React from 'react'; -import {View} from 'react-native'; -import {SafeAreaInsetsContext} from 'react-native-safe-area-context'; -import {defaultProps, propTypes} from '@components/Popover/popoverPropTypes'; -import {PopoverContext} from '@components/PopoverProvider'; -import withWindowDimensions from '@components/withWindowDimensions'; -import getModalStyles from '@styles/getModalStyles'; -import * as StyleUtils from '@styles/StyleUtils'; -import useThemeStyles from '@styles/useThemeStyles'; -import * as Modal from '@userActions/Modal'; - -function Popover(props) { - const styles = useThemeStyles(); - const {onOpen, close} = React.useContext(PopoverContext); - const {modalStyle, modalContainerStyle, shouldAddTopSafeAreaMargin, shouldAddBottomSafeAreaMargin, shouldAddTopSafeAreaPadding, shouldAddBottomSafeAreaPadding} = getModalStyles( - 'popover', - { - windowWidth: props.windowWidth, - windowHeight: props.windowHeight, - isSmallScreenWidth: false, - }, - props.anchorPosition, - props.innerContainerStyle, - props.outerStyle, - ); - - React.useEffect(() => { - let removeOnClose; - if (props.isVisible) { - props.onModalShow(); - onOpen({ - ref: props.withoutOverlayRef, - close: props.onClose, - anchorRef: props.anchorRef, - }); - removeOnClose = Modal.setCloseModal(() => props.onClose(props.anchorRef)); - } else { - props.onModalHide(); - close(props.anchorRef); - Modal.onModalDidClose(); - } - Modal.willAlertModalBecomeVisible(props.isVisible); - - return () => { - if (!removeOnClose) { - return; - } - removeOnClose(); - }; - // We want this effect to run strictly ONLY when isVisible prop changes - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [props.isVisible]); - - if (!props.isVisible) { - return null; - } - - return ( - - - {(insets) => { - const { - paddingTop: safeAreaPaddingTop, - paddingBottom: safeAreaPaddingBottom, - paddingLeft: safeAreaPaddingLeft, - paddingRight: safeAreaPaddingRight, - } = StyleUtils.getSafeAreaPadding(insets); - - const modalPaddingStyles = StyleUtils.getModalPaddingStyles({ - safeAreaPaddingTop, - safeAreaPaddingBottom, - safeAreaPaddingLeft, - safeAreaPaddingRight, - shouldAddBottomSafeAreaMargin, - shouldAddTopSafeAreaMargin, - shouldAddBottomSafeAreaPadding, - shouldAddTopSafeAreaPadding, - modalContainerStyleMarginTop: modalContainerStyle.marginTop, - modalContainerStyleMarginBottom: modalContainerStyle.marginBottom, - modalContainerStylePaddingTop: modalContainerStyle.paddingTop, - modalContainerStylePaddingBottom: modalContainerStyle.paddingBottom, - insets, - }); - return ( - - {props.children} - - ); - }} - - - ); -} - -Popover.propTypes = propTypes; -Popover.defaultProps = defaultProps; -Popover.displayName = 'Popover'; - -export default withWindowDimensions(Popover); diff --git a/src/components/PopoverWithoutOverlay/index.tsx b/src/components/PopoverWithoutOverlay/index.tsx new file mode 100644 index 000000000000..5bcd4c64cb0c --- /dev/null +++ b/src/components/PopoverWithoutOverlay/index.tsx @@ -0,0 +1,107 @@ +import React, {ForwardedRef} from 'react'; +import {View} from 'react-native'; +import {useSafeAreaInsets} from 'react-native-safe-area-context'; +import {PopoverContext} from '@components/PopoverProvider'; +import useWindowDimensions from '@hooks/useWindowDimensions'; +import getModalStyles from '@styles/getModalStyles'; +import * as StyleUtils from '@styles/StyleUtils'; +import useThemeStyles from '@styles/useThemeStyles'; +import * as Modal from '@userActions/Modal'; +import PopoverProps from './types'; + +function Popover( + {anchorPosition = {}, anchorRef, withoutOverlayRef, innerContainerStyle = {}, outerStyle, onModalShow = () => {}, isVisible, onClose, onModalHide = () => {}, children}: PopoverProps, + ref: ForwardedRef, +) { + const styles = useThemeStyles(); + const {onOpen, close} = React.useContext(PopoverContext); + const {windowWidth, windowHeight} = useWindowDimensions(); + const insets = useSafeAreaInsets(); + const {modalStyle, modalContainerStyle, shouldAddTopSafeAreaMargin, shouldAddBottomSafeAreaMargin, shouldAddTopSafeAreaPadding, shouldAddBottomSafeAreaPadding} = getModalStyles( + 'popover', + { + windowWidth, + windowHeight, + isSmallScreenWidth: false, + }, + anchorPosition, + innerContainerStyle, + outerStyle, + ); + + React.useEffect(() => { + let removeOnClose: () => void; + if (isVisible && anchorRef && onOpen) { + onModalShow(); + onOpen({ + ref: withoutOverlayRef, + close: onClose, + anchorRef, + }); + removeOnClose = Modal.setCloseModal(() => onClose(anchorRef)); + } else { + onModalHide(); + close(anchorRef); + Modal.onModalDidClose(); + } + Modal.willAlertModalBecomeVisible(isVisible); + + return () => { + if (!removeOnClose) { + return; + } + removeOnClose(); + }; + // We want this effect to run strictly ONLY when isVisible prop changes + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isVisible]); + + if (!isVisible) { + return null; + } + + const { + paddingTop: safeAreaPaddingTop, + paddingBottom: safeAreaPaddingBottom, + paddingLeft: safeAreaPaddingLeft, + paddingRight: safeAreaPaddingRight, + } = StyleUtils.getSafeAreaPadding(insets); + + const modalPaddingStyles = StyleUtils.getModalPaddingStyles({ + safeAreaPaddingTop, + safeAreaPaddingBottom, + safeAreaPaddingLeft, + safeAreaPaddingRight, + shouldAddBottomSafeAreaMargin, + shouldAddTopSafeAreaMargin, + shouldAddBottomSafeAreaPadding, + shouldAddTopSafeAreaPadding, + modalContainerStyleMarginTop: modalContainerStyle.marginTop, + modalContainerStyleMarginBottom: modalContainerStyle.marginBottom, + modalContainerStylePaddingTop: modalContainerStyle.paddingTop, + modalContainerStylePaddingBottom: modalContainerStyle.paddingBottom, + insets, + }); + + return ( + + + {children} + + + ); +} + +Popover.displayName = 'Popover'; + +export default React.forwardRef(Popover); diff --git a/src/components/PopoverWithoutOverlay/types.ts b/src/components/PopoverWithoutOverlay/types.ts new file mode 100644 index 000000000000..7e73a7ae8408 --- /dev/null +++ b/src/components/PopoverWithoutOverlay/types.ts @@ -0,0 +1,28 @@ +import {View} from 'react-native'; +import BaseModalProps from '@components/Modal/types'; +import ChildrenProps from '@src/types/utils/ChildrenProps'; + +type PopoverProps = ChildrenProps & + Omit & { + /** The anchor position of the popover */ + anchorPosition?: { + top?: number; + right?: number; + bottom?: number; + left?: number; + }; + + /** The anchor ref of the popover */ + anchorRef?: React.RefObject; + + /** A react-native-animatable animation timing for the modal display animation. */ + animationInTiming?: number; + + /** Whether disable the animations */ + disableAnimation?: boolean; + + /** The ref of the popover */ + withoutOverlayRef: React.RefObject; + }; + +export default PopoverProps; From e1afa7c71dbd0a50b5f012a3e47d63448e72a070 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Wed, 29 Nov 2023 12:05:23 +0100 Subject: [PATCH 013/152] fix type error in BaseModal --- src/components/Modal/BaseModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Modal/BaseModal.tsx b/src/components/Modal/BaseModal.tsx index 95a7f3adc279..c8fe65af086f 100644 --- a/src/components/Modal/BaseModal.tsx +++ b/src/components/Modal/BaseModal.tsx @@ -180,7 +180,7 @@ function BaseModal( onModalHide={hideModal} onModalWillShow={() => ComposerFocusManager.resetReadyToFocus()} onDismiss={handleDismissModal} - onSwipeComplete={onClose} + onSwipeComplete={() => onClose()} swipeDirection={swipeDirection} isVisible={isVisible} backdropColor={theme.overlay} From cd4167d682ecd8598599d588d47044a99da404a9 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Wed, 29 Nov 2023 13:15:27 +0100 Subject: [PATCH 014/152] import hooks from react --- src/components/PopoverWithoutOverlay/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/PopoverWithoutOverlay/index.tsx b/src/components/PopoverWithoutOverlay/index.tsx index 5bcd4c64cb0c..ddcdec247fac 100644 --- a/src/components/PopoverWithoutOverlay/index.tsx +++ b/src/components/PopoverWithoutOverlay/index.tsx @@ -1,4 +1,4 @@ -import React, {ForwardedRef} from 'react'; +import React, {ForwardedRef, forwardRef, useContext, useEffect} from 'react'; import {View} from 'react-native'; import {useSafeAreaInsets} from 'react-native-safe-area-context'; import {PopoverContext} from '@components/PopoverProvider'; @@ -14,7 +14,7 @@ function Popover( ref: ForwardedRef, ) { const styles = useThemeStyles(); - const {onOpen, close} = React.useContext(PopoverContext); + const {onOpen, close} = useContext(PopoverContext); const {windowWidth, windowHeight} = useWindowDimensions(); const insets = useSafeAreaInsets(); const {modalStyle, modalContainerStyle, shouldAddTopSafeAreaMargin, shouldAddBottomSafeAreaMargin, shouldAddTopSafeAreaPadding, shouldAddBottomSafeAreaPadding} = getModalStyles( @@ -29,7 +29,7 @@ function Popover( outerStyle, ); - React.useEffect(() => { + useEffect(() => { let removeOnClose: () => void; if (isVisible && anchorRef && onOpen) { onModalShow(); @@ -104,4 +104,4 @@ function Popover( Popover.displayName = 'Popover'; -export default React.forwardRef(Popover); +export default forwardRef(Popover); From c5a641859a4ac66250438383556f33b24e12ee1f Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Thu, 30 Nov 2023 15:07:09 +0100 Subject: [PATCH 015/152] make anchorRef a required prop, conditional onOpen call --- .../PopoverWithoutOverlay/index.tsx | 25 +++++++++++++------ src/components/PopoverWithoutOverlay/types.ts | 6 ++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/components/PopoverWithoutOverlay/index.tsx b/src/components/PopoverWithoutOverlay/index.tsx index ddcdec247fac..8786d5593e33 100644 --- a/src/components/PopoverWithoutOverlay/index.tsx +++ b/src/components/PopoverWithoutOverlay/index.tsx @@ -7,10 +7,21 @@ import getModalStyles from '@styles/getModalStyles'; import * as StyleUtils from '@styles/StyleUtils'; import useThemeStyles from '@styles/useThemeStyles'; import * as Modal from '@userActions/Modal'; -import PopoverProps from './types'; +import PopoverWithoutOverlayProps from './types'; -function Popover( - {anchorPosition = {}, anchorRef, withoutOverlayRef, innerContainerStyle = {}, outerStyle, onModalShow = () => {}, isVisible, onClose, onModalHide = () => {}, children}: PopoverProps, +function PopoverWithoutOverlay( + { + anchorPosition = {}, + anchorRef, + withoutOverlayRef, + innerContainerStyle = {}, + outerStyle, + onModalShow = () => {}, + isVisible, + onClose, + onModalHide = () => {}, + children, + }: PopoverWithoutOverlayProps, ref: ForwardedRef, ) { const styles = useThemeStyles(); @@ -31,9 +42,9 @@ function Popover( useEffect(() => { let removeOnClose: () => void; - if (isVisible && anchorRef && onOpen) { + if (isVisible) { onModalShow(); - onOpen({ + onOpen?.({ ref: withoutOverlayRef, close: onClose, anchorRef, @@ -102,6 +113,6 @@ function Popover( ); } -Popover.displayName = 'Popover'; +PopoverWithoutOverlay.displayName = 'PopoverWithoutOverlay'; -export default forwardRef(Popover); +export default forwardRef(PopoverWithoutOverlay); diff --git a/src/components/PopoverWithoutOverlay/types.ts b/src/components/PopoverWithoutOverlay/types.ts index 7e73a7ae8408..61b6727b40ee 100644 --- a/src/components/PopoverWithoutOverlay/types.ts +++ b/src/components/PopoverWithoutOverlay/types.ts @@ -2,7 +2,7 @@ import {View} from 'react-native'; import BaseModalProps from '@components/Modal/types'; import ChildrenProps from '@src/types/utils/ChildrenProps'; -type PopoverProps = ChildrenProps & +type PopoverWithoutOverlayProps = ChildrenProps & Omit & { /** The anchor position of the popover */ anchorPosition?: { @@ -13,7 +13,7 @@ type PopoverProps = ChildrenProps & }; /** The anchor ref of the popover */ - anchorRef?: React.RefObject; + anchorRef: React.RefObject; /** A react-native-animatable animation timing for the modal display animation. */ animationInTiming?: number; @@ -25,4 +25,4 @@ type PopoverProps = ChildrenProps & withoutOverlayRef: React.RefObject; }; -export default PopoverProps; +export default PopoverWithoutOverlayProps; From 22502c94c3a1e79050b99736778405c8798f53e7 Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 5 Dec 2023 17:55:58 +0700 Subject: [PATCH 016/152] fix: bug --- src/pages/home/report/ReportActionsList.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index d9ba4d1dc4d1..43560726327c 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -2,7 +2,7 @@ import {useRoute} from '@react-navigation/native'; import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {DeviceEventEmitter} from 'react-native'; +import {DeviceEventEmitter, InteractionManager} from 'react-native'; import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import _ from 'underscore'; import InvertedFlatList from '@components/InvertedFlatList'; @@ -159,7 +159,8 @@ function ReportActionsList({ const reportActionSize = useRef(sortedReportActions.length); const lastReadTimeRef = useRef(report.lastReadTime); - const lastActionIndex = lodashGet(sortedReportActions, [0, 'reportActionID']); + const sortedVisibleReportActions = _.filter(sortedReportActions, (s) => isOffline || s.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || s.errors); + const lastActionIndex = lodashGet(sortedVisibleReportActions, [0, 'reportActionID']); const previousLastIndex = useRef(lastActionIndex); @@ -178,11 +179,11 @@ function ReportActionsList({ }, [opacity]); useEffect(() => { - if (previousLastIndex.current !== lastActionIndex && reportActionSize.current > sortedReportActions.length) { + if (previousLastIndex.current !== lastActionIndex && reportActionSize.current > sortedVisibleReportActions.length) { reportScrollManager.scrollToBottom(); } previousLastIndex.current = lastActionIndex; - }, [lastActionIndex, sortedReportActions.length, reportScrollManager]); + }, [lastActionIndex, sortedVisibleReportActions.length, reportScrollManager]); useEffect(() => { // If the reportID changes, we reset the userActiveSince to null, we need to do it because @@ -270,7 +271,9 @@ function ReportActionsList({ if (!isFromCurrentUser) { return; } - reportScrollManager.scrollToBottom(); + InteractionManager.runAfterInteractions(()=>{ + reportScrollManager.scrollToBottom(); + }) }); const cleanup = () => { From fee91999b2d48c336afaee00780fd731257e9740 Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 5 Dec 2023 18:10:07 +0700 Subject: [PATCH 017/152] lint fix --- src/pages/home/report/ReportActionsList.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index 43560726327c..6ae4555d02c1 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -271,9 +271,9 @@ function ReportActionsList({ if (!isFromCurrentUser) { return; } - InteractionManager.runAfterInteractions(()=>{ + InteractionManager.runAfterInteractions(() => { reportScrollManager.scrollToBottom(); - }) + }); }); const cleanup = () => { From 6ed9bcbdca840da6265d2a489cc2450e13fa9c40 Mon Sep 17 00:00:00 2001 From: Maciej Dobosz Date: Tue, 5 Dec 2023 17:01:08 +0100 Subject: [PATCH 018/152] Add border radius 3 style --- src/styles/utilities/borders.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/styles/utilities/borders.ts b/src/styles/utilities/borders.ts index 5d5110f858e4..9cd02dcd22ae 100644 --- a/src/styles/utilities/borders.ts +++ b/src/styles/utilities/borders.ts @@ -12,6 +12,10 @@ export default { borderRadius: 8, }, + br3: { + borderRadius: 12, + }, + br4: { borderRadius: 16, }, From 4346c84849c43a6deef3c5a33781ecc284ab0f40 Mon Sep 17 00:00:00 2001 From: Maciej Dobosz Date: Tue, 5 Dec 2023 17:01:40 +0100 Subject: [PATCH 019/152] Create WorkspacesListRow --- src/pages/workspace/WorkspacesListPage.js | 22 ++++++---------------- src/pages/workspace/WorkspacesListRow.tsx | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 16 deletions(-) create mode 100755 src/pages/workspace/WorkspacesListRow.tsx diff --git a/src/pages/workspace/WorkspacesListPage.js b/src/pages/workspace/WorkspacesListPage.js index cf258b462285..c031e061fbe2 100755 --- a/src/pages/workspace/WorkspacesListPage.js +++ b/src/pages/workspace/WorkspacesListPage.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import React, {useMemo} from 'react'; +import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import Button from '@components/Button'; @@ -28,6 +29,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; +import WorkspacesListRow from './WorkspacesListRow'; const propTypes = { /** The list of this user's policies */ @@ -182,20 +184,7 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, u }, [reimbursementAccount.errors, policies, isOffline, theme.textLight, allPolicyMembers]); return ( - Navigation.goBack(ROUTES.SETTINGS)} - title={translate('common.workspaces')} - footer={ -