-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Detailed list of reaction senders when long-/right-pressing a reaction #15685
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 all commits
f6279ea
bc5a517
5732ada
72d53e9
0280636
82b02be
156d6ef
c66388b
0317bd7
e36ba93
b16febf
fbc69cf
502920e
5bc555d
6bc54ce
e96d82b
acf6f2e
838585d
01848c6
5523614
e528087
b91f52c
96d05f6
524546b
b4343a8
d129b8c
6ebe8ac
308f673
38db154
b2a1c65
4ffd2ff
6df949e
907fd16
a09ad6b
cb14807
5dada1a
a989192
3604015
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 @@ | ||
/* eslint-disable rulesdir/onyx-props-must-have-default */ | ||
import React from 'react'; | ||
import {FlatList} from 'react-native'; | ||
import PropTypes from 'prop-types'; | ||
import Str from 'expensify-common/lib/str'; | ||
import styles from '../../../../styles/styles'; | ||
import HeaderReactionList from './HeaderReactionList'; | ||
import * as ReportUtils from '../../../../libs/ReportUtils'; | ||
import CONST from '../../../../CONST'; | ||
import participantPropTypes from '../../../../components/participantPropTypes'; | ||
import reactionPropTypes from './reactionPropTypes'; | ||
import OptionRow from '../../../../components/OptionRow'; | ||
import variables from '../../../../styles/variables'; | ||
import withWindowDimensions from '../../../../components/withWindowDimensions'; | ||
|
||
const propTypes = { | ||
|
||
/** | ||
* Array of personal detail objects | ||
*/ | ||
users: PropTypes.arrayOf(participantPropTypes).isRequired, | ||
|
||
/** | ||
* Returns true if the current account has reacted to the report action (with the given skin tone). | ||
*/ | ||
hasUserReacted: PropTypes.bool, | ||
perunt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
...reactionPropTypes, | ||
}; | ||
|
||
const defaultProps = { | ||
hasUserReacted: false, | ||
}; | ||
|
||
/** | ||
* Given an emoji item object, render a component based on its type. | ||
* Items with the code "SPACER" return nothing and are used to fill rows up to 8 | ||
* so that the sticky headers function properly | ||
* | ||
* @param {Object} params | ||
* @param {Object} params.item | ||
* @return {React.Component} | ||
*/ | ||
const renderItem = ({item}) => ( | ||
<OptionRow | ||
item={item} | ||
boldStyle | ||
isDisabled | ||
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. This also makes the text on the item unselectable. Is it fine? @Julesssss and others. 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. Good spot. I think that's okay given that there are other ways for web/Desktop users to copy this text. |
||
style={{maxWidth: variables.mobileResponsiveWidthBreakpoint}} | ||
option={{ | ||
text: Str.removeSMSDomain(item.displayName), | ||
alternateText: Str.removeSMSDomain(item.login), | ||
participantsList: [item], | ||
icons: [{ | ||
source: ReportUtils.getAvatar(item.avatar, item.login), | ||
name: item.login, | ||
type: CONST.ICON_TYPE_AVATAR, | ||
}], | ||
keyForList: item.login, | ||
}} | ||
/> | ||
); | ||
|
||
/** | ||
* Create a unique key for each action in the FlatList. | ||
* @param {Object} item | ||
* @param {Number} index | ||
* @return {String} | ||
*/ | ||
const keyExtractor = (item, index) => `${item.login}+${index}`; | ||
Julesssss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* This function will be used with FlatList getItemLayout property for optimization purpose that allows skipping | ||
* the measurement of dynamic content if we know the size (height or width) of items ahead of time. | ||
* Generate and return an object with properties length(height of each individual row), | ||
* offset(distance of the current row from the top of the FlatList), index(current row index) | ||
* | ||
* @param {*} _ FlatList item | ||
* @param {Number} index row index | ||
* @returns {Object} | ||
*/ | ||
const getItemLayout = (_, index) => ({ | ||
index, | ||
length: variables.listItemHeightNormal, | ||
offset: variables.listItemHeightNormal * index, | ||
}); | ||
|
||
const BaseReactionList = (props) => { | ||
if (!props.isVisible) { | ||
return null; | ||
} | ||
return ( | ||
<> | ||
<HeaderReactionList | ||
onClose={props.onClose} | ||
emojiName={props.emojiName} | ||
emojiCodes={props.emojiCodes} | ||
emojiCount={props.emojiCount} | ||
hasUserReacted={props.hasUserReacted} | ||
/> | ||
<FlatList | ||
data={props.users} | ||
renderItem={renderItem} | ||
keyExtractor={keyExtractor} | ||
getItemLayout={getItemLayout} | ||
contentContainerStyle={styles.pv2} | ||
style={[styles.reactionListContainer, !props.isSmallScreenWidth && styles.reactionListContainerFixedWidth]} | ||
/> | ||
</> | ||
); | ||
}; | ||
|
||
BaseReactionList.propTypes = propTypes; | ||
BaseReactionList.defaultProps = defaultProps; | ||
BaseReactionList.displayName = 'BaseReactionList'; | ||
|
||
export default withWindowDimensions(BaseReactionList); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✋ Coming from #25976
We are preventing the popover from closing when clicking on the popover and the anchor. In this case, the entire View component where the reactions sit is used as the anchor, causing clicks to be ignored in this area.