-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Hide flagged attachment in attachment carousel #24564
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
Changes from 31 commits
f53d3dc
6d0190c
104f0f4
7dfcf17
93fe8c3
0fd41e9
6b6f267
95045a5
1734b16
83c629e
d5b8130
4dbf950
e7956b3
8863e79
dce6721
fc337d6
4202190
4d41062
8d22119
e850d52
3f396d6
0b586f4
619af69
f151ae0
c315df5
fe07eba
0315c87
7244223
31385c3
b9ef612
ab4d5f3
9a0755c
4df91a2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import React, {useContext, useState} from 'react'; | ||
import {View} from 'react-native'; | ||
import PropTypes from 'prop-types'; | ||
import CONST from '../../../CONST'; | ||
import styles from '../../../styles/styles'; | ||
import useLocalize from '../../../hooks/useLocalize'; | ||
import PressableWithoutFeedback from '../../Pressable/PressableWithoutFeedback'; | ||
import Text from '../../Text'; | ||
import Button from '../../Button'; | ||
import AttachmentView from '../AttachmentView'; | ||
import SafeAreaConsumer from '../../SafeAreaConsumer'; | ||
import ReportAttachmentsContext from '../../../pages/home/report/ReportAttachmentsContext'; | ||
|
||
const propTypes = { | ||
/** Attachment required information such as the source and file name */ | ||
item: PropTypes.shape({ | ||
/** Report action ID of the attachment */ | ||
reportActionID: PropTypes.string, | ||
|
||
/** Whether source URL requires authentication */ | ||
isAuthTokenRequired: PropTypes.bool, | ||
|
||
/** The source (URL) of the attachment */ | ||
source: PropTypes.string, | ||
|
||
/** File additional information of the attachment */ | ||
file: PropTypes.shape({ | ||
/** File name of the attachment */ | ||
name: PropTypes.string, | ||
}), | ||
|
||
/** Whether the attachment has been flagged */ | ||
hasBeenFlagged: PropTypes.bool, | ||
}).isRequired, | ||
|
||
/** Whether the attachment is currently being viewed in the carousel */ | ||
isFocused: PropTypes.bool.isRequired, | ||
|
||
/** onPress callback */ | ||
onPress: PropTypes.func, | ||
}; | ||
|
||
const defaultProps = { | ||
onPress: undefined, | ||
}; | ||
|
||
function CarouselItem({item, isFocused, onPress}) { | ||
const {translate} = useLocalize(); | ||
const {isAttachmentHidden} = useContext(ReportAttachmentsContext); | ||
const [isHidden, setIsHidden] = useState(() => { | ||
const isAttachmentHiddenValue = isAttachmentHidden(item.reportActionID); | ||
return isAttachmentHiddenValue === undefined ? item.hasBeenFlagged : isAttachmentHiddenValue; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NAB but I'd prefer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It will conflict with the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it could be simplified using the null-coalescing operator const [isHidden, setIsHidden] = useState(isAttachmentHidden(item.reportActionID) ?? item.hasBeenFlagged); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can pass that rule ? FYI, nullish coalescing will be supported as part of the TypeScript migration. You can find more details in the following link: TS_STYLE.md There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's go for it, I think that improves readability considerably and is valid given we're supporting it soon. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great, updated |
||
}); | ||
|
||
const renderButton = (style) => ( | ||
<Button | ||
small | ||
style={style} | ||
onPress={() => setIsHidden(!isHidden)} | ||
> | ||
<Text | ||
style={styles.buttonSmallText} | ||
selectable={false} | ||
dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}} | ||
> | ||
{isHidden ? translate('moderation.revealMessage') : translate('moderation.hideMessage')} | ||
</Text> | ||
</Button> | ||
); | ||
|
||
if (isHidden) { | ||
const children = ( | ||
<> | ||
<Text style={[styles.textLabelSupporting, styles.textAlignCenter, styles.lh20]}>{translate('moderation.flaggedContent')}</Text> | ||
{renderButton([styles.mt2])} | ||
</> | ||
); | ||
return onPress ? ( | ||
<PressableWithoutFeedback | ||
style={[styles.attachmentRevealButtonContainer]} | ||
onPress={onPress} | ||
accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON} | ||
accessibilityLabel={item.file.name || translate('attachmentView.unknownFilename')} | ||
> | ||
{children} | ||
</PressableWithoutFeedback> | ||
) : ( | ||
<View style={[styles.attachmentRevealButtonContainer]}>{children}</View> | ||
); | ||
} | ||
|
||
return ( | ||
<View style={[styles.flex1]}> | ||
<View style={[styles.flex1]}> | ||
<AttachmentView | ||
source={item.source} | ||
file={item.file} | ||
isAuthTokenRequired={item.isAuthTokenRequired} | ||
isFocused={isFocused} | ||
onPress={onPress} | ||
isUsedInCarousel | ||
/> | ||
</View> | ||
|
||
{item.hasBeenFlagged && ( | ||
<SafeAreaConsumer> | ||
{({safeAreaPaddingBottomStyle}) => <View style={[styles.appBG, safeAreaPaddingBottomStyle]}>{renderButton([styles.m4, styles.alignSelfCenter])}</View>} | ||
</SafeAreaConsumer> | ||
)} | ||
</View> | ||
); | ||
} | ||
|
||
CarouselItem.propTypes = propTypes; | ||
CarouselItem.defaultProps = defaultProps; | ||
|
||
export default CarouselItem; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React, {useEffect, useMemo, useRef} from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import useCurrentReportID from '../../../hooks/useCurrentReportID'; | ||
|
||
const ReportAttachmentsContext = React.createContext(); | ||
|
||
const propTypes = { | ||
/** Rendered child component */ | ||
children: PropTypes.node.isRequired, | ||
}; | ||
|
||
function ReportAttachmentsProvider(props) { | ||
const currentReportID = useCurrentReportID(); | ||
const hiddenAttachments = useRef({}); | ||
|
||
useEffect(() => { | ||
// We only want to store the attachment visibility for the current report. | ||
// If the current report ID changes, clear the ref. | ||
hiddenAttachments.current = {}; | ||
}, [currentReportID]); | ||
|
||
const contextValue = useMemo( | ||
() => ({ | ||
isAttachmentHidden: (reportActionID) => hiddenAttachments.current[reportActionID], | ||
updateHiddenAttachments: (reportActionID, value) => { | ||
hiddenAttachments.current = { | ||
...hiddenAttachments.current, | ||
[reportActionID]: value, | ||
}; | ||
}, | ||
}), | ||
[], | ||
); | ||
|
||
return <ReportAttachmentsContext.Provider value={contextValue}>{props.children}</ReportAttachmentsContext.Provider>; | ||
} | ||
|
||
ReportAttachmentsProvider.propTypes = propTypes; | ||
ReportAttachmentsProvider.displayName = 'ReportAttachmentsProvider'; | ||
|
||
export default ReportAttachmentsContext; | ||
export {ReportAttachmentsProvider}; |
Uh oh!
There was an error while loading. Please reload this page.