diff --git a/docs/assets/images/ExpensifyHelp_ApprovingReports_01.png b/docs/assets/images/ExpensifyHelp_ApprovingReports_01.png new file mode 100644 index 000000000000..a9bc57525a1a Binary files /dev/null and b/docs/assets/images/ExpensifyHelp_ApprovingReports_01.png differ diff --git a/docs/assets/images/ExpensifyHelp_ApprovingReports_02.png b/docs/assets/images/ExpensifyHelp_ApprovingReports_02.png new file mode 100644 index 000000000000..4bd2c5af455b Binary files /dev/null and b/docs/assets/images/ExpensifyHelp_ApprovingReports_02.png differ diff --git a/docs/assets/images/ExpensifyHelp_ApprovingReports_03.png b/docs/assets/images/ExpensifyHelp_ApprovingReports_03.png new file mode 100644 index 000000000000..f5318cd5272a Binary files /dev/null and b/docs/assets/images/ExpensifyHelp_ApprovingReports_03.png differ diff --git a/docs/assets/images/ExpensifyHelp_ApprovingReports_04.png b/docs/assets/images/ExpensifyHelp_ApprovingReports_04.png new file mode 100644 index 000000000000..8913771747aa Binary files /dev/null and b/docs/assets/images/ExpensifyHelp_ApprovingReports_04.png differ diff --git a/docs/assets/images/ExpensifyHelp_ApprovingReports_05.png b/docs/assets/images/ExpensifyHelp_ApprovingReports_05.png new file mode 100644 index 000000000000..f1f43ae16f03 Binary files /dev/null and b/docs/assets/images/ExpensifyHelp_ApprovingReports_05.png differ diff --git a/docs/assets/images/ExpensifyHelp_ApprovingReports_06.png b/docs/assets/images/ExpensifyHelp_ApprovingReports_06.png new file mode 100644 index 000000000000..51854b6e2690 Binary files /dev/null and b/docs/assets/images/ExpensifyHelp_ApprovingReports_06.png differ diff --git a/docs/assets/images/ExpensifyHelp_ApprovingReports_07.png b/docs/assets/images/ExpensifyHelp_ApprovingReports_07.png new file mode 100644 index 000000000000..b750ffdc486f Binary files /dev/null and b/docs/assets/images/ExpensifyHelp_ApprovingReports_07.png differ diff --git a/ios/expensify_chat_adhoc.mobileprovision.gpg b/ios/expensify_chat_adhoc.mobileprovision.gpg index 994136a07b6c..1dae451f168c 100644 Binary files a/ios/expensify_chat_adhoc.mobileprovision.gpg and b/ios/expensify_chat_adhoc.mobileprovision.gpg differ diff --git a/src/components/EmojiPicker/EmojiPicker.js b/src/components/EmojiPicker/EmojiPicker.js index 8b32234fdbdf..5c2f65e24b01 100644 --- a/src/components/EmojiPicker/EmojiPicker.js +++ b/src/components/EmojiPicker/EmojiPicker.js @@ -6,11 +6,10 @@ import EmojiPickerMenu from './EmojiPickerMenu'; import CONST from '../../CONST'; import styles from '../../styles/styles'; import PopoverWithMeasuredContent from '../PopoverWithMeasuredContent'; -import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions'; import withViewportOffsetTop from '../withViewportOffsetTop'; -import compose from '../../libs/compose'; import * as StyleUtils from '../../styles/StyleUtils'; import calculateAnchorPosition from '../../libs/calculateAnchorPosition'; +import useWindowDimensions from '../../hooks/useWindowDimensions'; const DEFAULT_ANCHOR_ORIGIN = { horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT, @@ -18,7 +17,6 @@ const DEFAULT_ANCHOR_ORIGIN = { }; const propTypes = { - ...windowDimensionsPropTypes, viewportOffsetTop: PropTypes.number.isRequired, }; @@ -34,6 +32,7 @@ const EmojiPicker = forwardRef((props, ref) => { const onModalHide = useRef(() => {}); const onEmojiSelected = useRef(() => {}); const emojiSearchInput = useRef(); + const {isSmallScreenWidth, windowHeight} = useWindowDimensions(); /** * Show the emoji picker menu. @@ -125,7 +124,7 @@ const EmojiPicker = forwardRef((props, ref) => { const emojiPopoverDimensionListener = Dimensions.addEventListener('change', () => { if (!emojiPopoverAnchor.current) { // In small screen width, the window size change might be due to keyboard open/hide, we should avoid hide EmojiPicker in those cases - if (isEmojiPickerVisible && !props.isSmallScreenWidth) { + if (isEmojiPickerVisible && !isSmallScreenWidth) { hideEmojiPicker(); } return; @@ -137,7 +136,7 @@ const EmojiPicker = forwardRef((props, ref) => { return () => { emojiPopoverDimensionListener.remove(); }; - }, [isEmojiPickerVisible, props.isSmallScreenWidth, emojiPopoverAnchorOrigin]); + }, [isEmojiPickerVisible, isSmallScreenWidth, emojiPopoverAnchorOrigin]); // There is no way to disable animations, and they are really laggy, because there are so many // emojis. The best alternative is to set it to 1ms so it just "pops" in and out @@ -162,7 +161,7 @@ const EmojiPicker = forwardRef((props, ref) => { height: CONST.EMOJI_PICKER_SIZE.HEIGHT, }} anchorAlignment={emojiPopoverAnchorOrigin} - outerStyle={StyleUtils.getOuterModalStyle(props.windowHeight, props.viewportOffsetTop)} + outerStyle={StyleUtils.getOuterModalStyle(windowHeight, props.viewportOffsetTop)} innerContainerStyle={styles.popoverInnerContainer} avoidKeyboard > @@ -176,4 +175,4 @@ const EmojiPicker = forwardRef((props, ref) => { EmojiPicker.propTypes = propTypes; EmojiPicker.displayName = 'EmojiPicker'; -export default compose(withViewportOffsetTop, withWindowDimensions)(EmojiPicker); +export default withViewportOffsetTop(EmojiPicker); diff --git a/src/components/EmojiPicker/EmojiPickerMenu/index.js b/src/components/EmojiPicker/EmojiPickerMenu/index.js index df47d3494928..aea3b0f5b984 100755 --- a/src/components/EmojiPicker/EmojiPickerMenu/index.js +++ b/src/components/EmojiPicker/EmojiPickerMenu/index.js @@ -11,7 +11,6 @@ import * as StyleUtils from '../../../styles/StyleUtils'; import emojiAssets from '../../../../assets/emojis'; import EmojiPickerMenuItem from '../EmojiPickerMenuItem'; import Text from '../../Text'; -import withWindowDimensions, {windowDimensionsPropTypes} from '../../withWindowDimensions'; import withLocalize, {withLocalizePropTypes} from '../../withLocalize'; import compose from '../../../libs/compose'; import getOperatingSystem from '../../../libs/getOperatingSystem'; @@ -23,6 +22,7 @@ import CategoryShortcutBar from '../CategoryShortcutBar'; import TextInput from '../../TextInput'; import isEnterWhileComposition from '../../../libs/KeyboardShortcut/isEnterWhileComposition'; import canFocusInputOnScreenFocus from '../../../libs/canFocusInputOnScreenFocus'; +import useWindowDimensions from '../../../hooks/useWindowDimensions'; const propTypes = { /** Function to add the selected emoji to the main compose text input */ @@ -37,9 +37,6 @@ const propTypes = { // eslint-disable-next-line react/forbid-prop-types frequentlyUsedEmojis: PropTypes.arrayOf(PropTypes.object), - /** Props related to the dimensions of the window */ - ...windowDimensionsPropTypes, - ...withLocalizePropTypes, }; @@ -52,7 +49,9 @@ const defaultProps = { const throttleTime = Browser.isMobile() ? 200 : 50; function EmojiPickerMenu(props) { - const {forwardedRef, frequentlyUsedEmojis, preferredSkinTone, onEmojiSelected, preferredLocale, isSmallScreenWidth, windowHeight, translate} = props; + const {forwardedRef, frequentlyUsedEmojis, preferredSkinTone, onEmojiSelected, preferredLocale, translate} = props; + + const {isSmallScreenWidth, windowHeight} = useWindowDimensions(); // Ref for the emoji search input const searchInputRef = useRef(null); @@ -528,7 +527,6 @@ EmojiPickerMenu.propTypes = propTypes; EmojiPickerMenu.defaultProps = defaultProps; export default compose( - withWindowDimensions, withLocalize, withOnyx({ preferredSkinTone: { diff --git a/src/components/LHNOptionsList/OptionRowLHNData.js b/src/components/LHNOptionsList/OptionRowLHNData.js index 3386dbe8c8cd..e93e3690138e 100644 --- a/src/components/LHNOptionsList/OptionRowLHNData.js +++ b/src/components/LHNOptionsList/OptionRowLHNData.js @@ -4,7 +4,6 @@ import _ from 'underscore'; import PropTypes from 'prop-types'; import React, {useEffect, useRef, useMemo} from 'react'; import {deepEqual} from 'fast-equals'; -import {withReportCommentDrafts} from '../OnyxProvider'; import SidebarUtils from '../../libs/SidebarUtils'; import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; @@ -164,14 +163,10 @@ const personalDetailsSelector = (personalDetails) => */ export default React.memo( compose( - withReportCommentDrafts({ - propName: 'comment', - transformValue: (drafts, props) => { - const draftKey = `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${props.reportID}`; - return lodashGet(drafts, draftKey, ''); - }, - }), withOnyx({ + comment: { + key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`, + }, fullReport: { key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, }, diff --git a/src/components/LottieAnimations.js b/src/components/LottieAnimations.ts similarity index 100% rename from src/components/LottieAnimations.js rename to src/components/LottieAnimations.ts diff --git a/src/libs/OnyxSelectors/reportWithoutHasDraftSelector.ts b/src/libs/OnyxSelectors/reportWithoutHasDraftSelector.ts new file mode 100644 index 000000000000..8819cc8aa47c --- /dev/null +++ b/src/libs/OnyxSelectors/reportWithoutHasDraftSelector.ts @@ -0,0 +1,9 @@ +import {OnyxKeyValue} from '../../ONYXKEYS'; + +export default function reportWithoutHasDraftSelector(report: OnyxKeyValue<'report_'>) { + if (!report) { + return report; + } + const {hasDraft, ...reportWithoutHasDraft} = report; + return reportWithoutHasDraft; +} diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 5557ed1e73c8..e88f6cd0b756 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -34,6 +34,7 @@ import * as Session from '../../libs/actions/Session'; import styles from '../../styles/styles'; import themeColors from '../../styles/themes/default'; import reportPropTypes from '../reportPropTypes'; +import reportWithoutHasDraftSelector from '../../libs/OnyxSelectors/reportWithoutHasDraftSelector'; const propTypes = { /** Toggles the navigationMenu open and closed */ @@ -281,6 +282,7 @@ export default compose( }, parentReport: { key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID || report.reportID}`, + selector: reportWithoutHasDraftSelector, }, session: { key: ONYXKEYS.SESSION, diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 81000c2dab92..32a14303e9a7 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -39,6 +39,7 @@ import DragAndDropProvider from '../../components/DragAndDrop/Provider'; import usePrevious from '../../hooks/usePrevious'; import CONST from '../../CONST'; import withCurrentReportID, {withCurrentReportIDPropTypes, withCurrentReportIDDefaultProps} from '../../components/withCurrentReportID'; +import reportWithoutHasDraftSelector from '../../libs/OnyxSelectors/reportWithoutHasDraftSelector'; const propTypes = { /** Navigation route context info provided by react navigation */ @@ -482,6 +483,7 @@ export default compose( report: { key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${getReportID(route)}`, allowStaleData: true, + selector: reportWithoutHasDraftSelector, }, reportMetadata: { key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT_METADATA}${getReportID(route)}`, diff --git a/src/pages/home/report/ReportActionItemCreated.js b/src/pages/home/report/ReportActionItemCreated.js index a5df1c37e769..50b4a3eb6148 100644 --- a/src/pages/home/report/ReportActionItemCreated.js +++ b/src/pages/home/report/ReportActionItemCreated.js @@ -19,6 +19,7 @@ import PressableWithoutFeedback from '../../../components/Pressable/PressableWit import MultipleAvatars from '../../../components/MultipleAvatars'; import CONST from '../../../CONST'; import AnimatedEmptyStateBackground from './AnimatedEmptyStateBackground'; +import reportWithoutHasDraftSelector from '../../../libs/OnyxSelectors/reportWithoutHasDraftSelector'; const propTypes = { /** The id of the report */ @@ -106,6 +107,7 @@ export default compose( withOnyx({ report: { key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + selector: reportWithoutHasDraftSelector, }, personalDetails: { key: ONYXKEYS.PERSONAL_DETAILS_LIST,