-
Notifications
You must be signed in to change notification settings - Fork 3.9k
[TS migration] Migrate 'OfflineWithFeedback.js' component to TypeScript #31124
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
Merged
cristipaval
merged 11 commits into
Expensify:main
from
kubabutkiewicz:ts-migration/OfflineWithFeedback/component
Dec 7, 2023
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
04ef831
ref: migrate OfflineWithFeedback to TS
kubabutkiewicz 1323fae
fix: migrate MessagesRow to TS
kubabutkiewicz e5b91bd
Merge branch 'main' of github.com:kubabutkiewicz/expensify-app into t…
kubabutkiewicz 5f0b880
fix: lint errors
kubabutkiewicz c0b19a9
fix: resolve comments
kubabutkiewicz 03126d4
fix: resolve comments
kubabutkiewicz 53cd80e
fix: resolve comment
kubabutkiewicz b4d4cd3
Merge branch 'main' of github.com:kubabutkiewicz/expensify-app into t…
kubabutkiewicz b88897b
fix: resolve comment
kubabutkiewicz 3164601
Merge branch 'main' of github.com:kubabutkiewicz/expensify-app into t…
kubabutkiewicz 26782f9
fix: resolve comments
kubabutkiewicz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| import React from 'react'; | ||
| import {ImageStyle, StyleProp, TextStyle, View, ViewStyle} from 'react-native'; | ||
| import useNetwork from '@hooks/useNetwork'; | ||
| import shouldRenderOffscreen from '@libs/shouldRenderOffscreen'; | ||
| import * as StyleUtils from '@styles/StyleUtils'; | ||
| import useThemeStyles from '@styles/useThemeStyles'; | ||
| import CONST from '@src/CONST'; | ||
| import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; | ||
| import ChildrenProps from '@src/types/utils/ChildrenProps'; | ||
| import {isNotEmptyObject} from '@src/types/utils/EmptyObject'; | ||
| import MessagesRow from './MessagesRow'; | ||
|
|
||
| /** | ||
| * This component should be used when we are using the offline pattern B (offline with feedback). | ||
| * You should enclose any element that should have feedback that the action was taken offline and it will take | ||
| * care of adding the appropriate styles for pending actions and displaying the dismissible error. | ||
| */ | ||
|
|
||
| type OfflineWithFeedbackProps = ChildrenProps & { | ||
| /** The type of action that's pending */ | ||
| pendingAction: OnyxCommon.PendingAction; | ||
|
|
||
| /** Determine whether to hide the component's children if deletion is pending */ | ||
| shouldHideOnDelete?: boolean; | ||
|
|
||
| /** The errors to display */ | ||
| errors?: OnyxCommon.Errors; | ||
|
|
||
| /** Whether we should show the error messages */ | ||
| shouldShowErrorMessages?: boolean; | ||
|
|
||
| /** Whether we should disable opacity */ | ||
| shouldDisableOpacity?: boolean; | ||
|
|
||
| /** A function to run when the X button next to the error is clicked */ | ||
| onClose?: () => void; | ||
|
|
||
| /** Additional styles to add after local styles. Applied to the parent container */ | ||
| style?: StyleProp<ViewStyle>; | ||
|
|
||
| /** Additional styles to add after local styles. Applied to the children wrapper container */ | ||
| contentContainerStyle?: StyleProp<ViewStyle>; | ||
|
|
||
| /** Additional style object for the error row */ | ||
| errorRowStyles?: StyleProp<ViewStyle>; | ||
|
|
||
| /** Whether applying strikethrough to the children should be disabled */ | ||
| shouldDisableStrikeThrough?: boolean; | ||
|
|
||
| /** Whether to apply needsOffscreenAlphaCompositing prop to the children */ | ||
| needsOffscreenAlphaCompositing?: boolean; | ||
|
|
||
| /** Whether we can dismiss the error message */ | ||
| canDismissError?: boolean; | ||
| }; | ||
|
|
||
| type StrikethroughProps = Partial<ChildrenProps> & {style: Array<ViewStyle | TextStyle | ImageStyle>}; | ||
|
|
||
| /** | ||
| * This method applies the strikethrough to all the children passed recursively | ||
| */ | ||
| function applyStrikeThrough(children: React.ReactNode, styles: ReturnType<typeof useThemeStyles>): React.ReactNode { | ||
| return React.Children.map(children, (child) => { | ||
| if (!React.isValidElement(child)) { | ||
| return child; | ||
| } | ||
|
kubabutkiewicz marked this conversation as resolved.
|
||
|
|
||
| const props: StrikethroughProps = { | ||
| style: StyleUtils.combineStyles(child.props.style, styles.offlineFeedback.deleted, styles.userSelectNone), | ||
| }; | ||
|
|
||
| if (child.props.children) { | ||
| props.children = applyStrikeThrough(child.props.children, styles); | ||
| } | ||
|
|
||
| return React.cloneElement(child, props); | ||
| }); | ||
| } | ||
|
|
||
| function omitBy<T>(obj: Record<string, T> | undefined, predicate: (value: T) => boolean) { | ||
| // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars | ||
| return Object.fromEntries(Object.entries(obj ?? {}).filter(([_, value]) => !predicate(value))); | ||
| } | ||
|
|
||
| function OfflineWithFeedback({ | ||
| pendingAction, | ||
| canDismissError = true, | ||
| contentContainerStyle, | ||
| errorRowStyles, | ||
| errors, | ||
| needsOffscreenAlphaCompositing = false, | ||
| onClose = () => {}, | ||
| shouldDisableOpacity = false, | ||
| shouldDisableStrikeThrough = false, | ||
| shouldHideOnDelete = true, | ||
| shouldShowErrorMessages = true, | ||
| style, | ||
| ...rest | ||
| }: OfflineWithFeedbackProps) { | ||
| const styles = useThemeStyles(); | ||
| const {isOffline} = useNetwork(); | ||
|
|
||
| const hasErrors = isNotEmptyObject(errors ?? {}); | ||
| // Some errors have a null message. This is used to apply opacity only and to avoid showing redundant messages. | ||
| const errorMessages = omitBy(errors, (e) => e === null); | ||
| const hasErrorMessages = isNotEmptyObject(errorMessages); | ||
| const isOfflinePendingAction = !!isOffline && !!pendingAction; | ||
| const isUpdateOrDeleteError = hasErrors && (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); | ||
| const isAddError = hasErrors && pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD; | ||
| const needsOpacity = !shouldDisableOpacity && ((isOfflinePendingAction && !isUpdateOrDeleteError) || isAddError); | ||
| const needsStrikeThrough = !shouldDisableStrikeThrough && isOffline && pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; | ||
| const hideChildren = shouldHideOnDelete && !isOffline && pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !hasErrors; | ||
| let children = rest.children; | ||
|
|
||
| // Apply strikethrough to children if needed, but skip it if we are not going to render them | ||
| if (needsStrikeThrough && !hideChildren) { | ||
| children = applyStrikeThrough(children, styles); | ||
| } | ||
| return ( | ||
| <View style={style}> | ||
| {!hideChildren && ( | ||
| <View | ||
| style={[needsOpacity ? styles.offlineFeedback.pending : {}, contentContainerStyle]} | ||
| needsOffscreenAlphaCompositing={shouldRenderOffscreen ? needsOpacity && needsOffscreenAlphaCompositing : undefined} | ||
| > | ||
| {children} | ||
| </View> | ||
| )} | ||
| {shouldShowErrorMessages && hasErrorMessages && ( | ||
| <MessagesRow | ||
| messages={errorMessages} | ||
| type="error" | ||
| onClose={onClose} | ||
| containerStyles={errorRowStyles} | ||
| canDismiss={canDismissError} | ||
| /> | ||
| )} | ||
| </View> | ||
| ); | ||
| } | ||
|
|
||
| OfflineWithFeedback.displayName = 'OfflineWithFeedback'; | ||
|
|
||
| export default OfflineWithFeedback; | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.