Skip to content

Commit

Permalink
Merge pull request #37509 from tienifr/fix/34833
Browse files Browse the repository at this point in the history
Hover menu is not dismissed after opening emoji picker
  • Loading branch information
luacmartins authored Mar 5, 2024
2 parents 5787691 + 72c70b0 commit 97c654e
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 9 deletions.
11 changes: 9 additions & 2 deletions src/components/Reactions/AddReactionBubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@ type AddReactionBubbleProps = {
* ReportAction for EmojiPicker.
*/
reportAction: ReportAction;

/** Function to update emoji picker state */
setIsEmojiPickerActive?: (state: boolean) => void;
};

function AddReactionBubble({onSelectEmoji, reportAction, onPressOpenPicker, onWillShowPicker = () => {}, isContextMenu = false}: AddReactionBubbleProps) {
function AddReactionBubble({onSelectEmoji, reportAction, onPressOpenPicker, onWillShowPicker = () => {}, isContextMenu = false, setIsEmojiPickerActive}: AddReactionBubbleProps) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const ref = useRef<View | HTMLDivElement>(null);
Expand All @@ -56,7 +59,9 @@ function AddReactionBubble({onSelectEmoji, reportAction, onPressOpenPicker, onWi
const onPress = () => {
const openPicker = (refParam?: PickerRefElement, anchorOrigin?: AnchorOrigin) => {
EmojiPickerAction.showEmojiPicker(
() => {},
() => {
setIsEmojiPickerActive?.(false);
},
(emojiCode, emojiObject) => {
onSelectEmoji(emojiObject);
},
Expand All @@ -68,12 +73,14 @@ function AddReactionBubble({onSelectEmoji, reportAction, onPressOpenPicker, onWi
};

if (!EmojiPickerAction.emojiPickerRef.current?.isEmojiPickerVisible) {
setIsEmojiPickerActive?.(true);
if (onPressOpenPicker) {
onPressOpenPicker(openPicker);
} else {
openPicker();
}
} else {
setIsEmojiPickerActive?.(false);
EmojiPickerAction.emojiPickerRef.current.hideEmojiPicker();
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function BaseQuickEmojiReactions({
emojiReactions = {},
onPressOpenPicker = () => {},
onWillShowPicker = () => {},
setIsEmojiPickerActive,
}: BaseQuickEmojiReactionsProps) {
const styles = useThemeStyles();

Expand All @@ -45,6 +46,7 @@ function BaseQuickEmojiReactions({
onWillShowPicker={onWillShowPicker}
onSelectEmoji={(emoji) => onEmojiSelected(emoji, emojiReactions)}
reportAction={reportAction}
setIsEmojiPickerActive={setIsEmojiPickerActive}
/>
</View>
);
Expand Down
5 changes: 5 additions & 0 deletions src/components/Reactions/QuickEmojiReactions/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ type BaseReactionsProps = {

/** Id of the ReportAction for EmojiPicker. */
reportActionID: string;

/** Function to update emoji picker state */
setIsEmojiPickerActive?: (state: boolean) => void;
};

type BaseQuickEmojiReactionsOnyxProps = {
Expand All @@ -53,6 +56,8 @@ type QuickEmojiReactionsProps = BaseReactionsProps & {
* in which this component is rendered.
*/
closeContextMenu: (callback: CloseContextMenuCallback) => void;

setIsEmojiPickerActive?: (state: boolean) => void;
};

export type {BaseQuickEmojiReactionsProps, BaseQuickEmojiReactionsOnyxProps, QuickEmojiReactionsProps, OpenPickerCallback, CloseContextMenuCallback, PickerRefElement};
7 changes: 7 additions & 0 deletions src/components/Reactions/ReportActionItemEmojiReactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type ReportActionItemEmojiReactionsProps = WithCurrentUserPersonalDetailsProps &

/** We disable reacting with emojis on report actions that have errors */
shouldBlockReactions?: boolean;

/** Function to update emoji picker state */
setIsEmojiPickerActive?: (state: boolean) => void;
};

type PopoverReactionListAnchors = Record<string, ReactionListAnchor>;
Expand Down Expand Up @@ -68,6 +71,8 @@ type FormattedReaction = {

/** The type of action that's pending */
pendingAction?: PendingAction;

setIsEmojiPickerActive?: (state: boolean) => void;
};

function ReportActionItemEmojiReactions({
Expand All @@ -77,6 +82,7 @@ function ReportActionItemEmojiReactions({
emojiReactions = {},
shouldBlockReactions = false,
preferredLocale = CONST.LOCALES.DEFAULT,
setIsEmojiPickerActive,
}: ReportActionItemEmojiReactionsProps) {
const styles = useThemeStyles();
const reactionListRef = useContext(ReactionListContext);
Expand Down Expand Up @@ -166,6 +172,7 @@ function ReportActionItemEmojiReactions({
<AddReactionBubble
onSelectEmoji={toggleReaction}
reportAction={reportAction}
setIsEmojiPickerActive={setIsEmojiPickerActive}
/>
)}
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ type BaseReportActionContextMenuProps = BaseReportActionContextMenuOnyxProps & {

/** List of disabled actions */
disabledActions?: ContextMenuAction[];

/** Function to update emoji picker state */
setIsEmojiPickerActive?: (state: boolean) => void;
};

type MenuItemRefs = Record<string, ContextMenuItemHandle | null>;
Expand All @@ -108,6 +111,7 @@ function BaseReportActionContextMenu({
reportActions,
checkIfContextMenuActive,
disabledActions = [],
setIsEmojiPickerActive,
}: BaseReportActionContextMenuProps) {
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
Expand Down Expand Up @@ -202,7 +206,10 @@ function BaseReportActionContextMenu({
originalReportID,
draftMessage,
checkIfContextMenuActive,
checkIfContextMenuActive,
() => {
checkIfContextMenuActive?.();
setShouldKeepOpen(false);
},
ReportUtils.isArchivedRoom(originalReport),
ReportUtils.chatIncludesChronos(originalReport),
undefined,
Expand All @@ -229,6 +236,7 @@ function BaseReportActionContextMenu({
openContextMenu: () => setShouldKeepOpen(true),
interceptAnonymousUser,
openOverflowMenu,
setIsEmojiPickerActive,
};

if ('renderContent' in contextAction) {
Expand Down
18 changes: 14 additions & 4 deletions src/pages/home/report/ContextMenu/ContextMenuActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type ContextMenuActionPayload = {
interceptAnonymousUser: (callback: () => void, isAnonymousAction?: boolean) => void;
openOverflowMenu: (event: GestureResponderEvent | MouseEvent) => void;
event?: GestureResponderEvent | MouseEvent | KeyboardEvent;
setIsEmojiPickerActive?: (state: boolean) => void;
};

type OnPress = (closePopover: boolean, payload: ContextMenuActionPayload, selection?: string, reportID?: string, draftMessage?: string) => void;
Expand Down Expand Up @@ -103,7 +104,7 @@ const ContextMenuActions: ContextMenuAction[] = [
isAnonymousAction: false,
shouldShow: (type, reportAction): reportAction is ReportAction =>
type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && !!reportAction && 'message' in reportAction && !ReportActionsUtils.isMessageDeleted(reportAction),
renderContent: (closePopover, {reportID, reportAction, close: closeManually, openContextMenu}) => {
renderContent: (closePopover, {reportID, reportAction, close: closeManually, openContextMenu, setIsEmojiPickerActive}) => {
const isMini = !closePopover;

const closeContextMenu = (onHideCallback?: () => void) => {
Expand All @@ -120,15 +121,22 @@ const ContextMenuActions: ContextMenuAction[] = [
const toggleEmojiAndCloseMenu = (emoji: Emoji, existingReactions: OnyxEntry<ReportActionReactions>) => {
Report.toggleEmojiReaction(reportID, reportAction, emoji, existingReactions);
closeContextMenu();
setIsEmojiPickerActive?.(false);
};

if (isMini) {
return (
<MiniQuickEmojiReactions
key="MiniQuickEmojiReactions"
onEmojiSelected={toggleEmojiAndCloseMenu}
onPressOpenPicker={openContextMenu}
onEmojiPickerClosed={closeContextMenu}
onPressOpenPicker={() => {
openContextMenu();
setIsEmojiPickerActive?.(true);
}}
onEmojiPickerClosed={() => {
closeContextMenu();
setIsEmojiPickerActive?.(false);
}}
reportActionID={reportAction?.reportActionID}
reportAction={reportAction}
/>
Expand All @@ -142,6 +150,7 @@ const ContextMenuActions: ContextMenuAction[] = [
onEmojiSelected={toggleEmojiAndCloseMenu}
reportActionID={reportAction?.reportActionID}
reportAction={reportAction}
setIsEmojiPickerActive={setIsEmojiPickerActive}
/>
);
},
Expand Down Expand Up @@ -476,8 +485,9 @@ const ContextMenuActions: ContextMenuAction[] = [
textTranslateKey: 'reportActionContextMenu.menu',
icon: Expensicons.ThreeDots,
shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini) => isMini,
onPress: (closePopover, {openOverflowMenu, event}) => {
onPress: (closePopover, {openOverflowMenu, event, openContextMenu}) => {
openOverflowMenu(event as GestureResponderEvent | MouseEvent);
openContextMenu();
},
getDescription: () => {},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor

const onPopoverShow = useRef(() => {});
const onPopoverHide = useRef(() => {});
const onEmojiPickerToggle = useRef<undefined | ((state: boolean) => void)>();
const onCancelDeleteModal = useRef(() => {});
const onComfirmDeleteModal = useRef(() => {});

Expand Down Expand Up @@ -164,6 +165,7 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor
isUnreadChat = false,
disabledOptions = [],
shouldCloseOnTarget = false,
setIsEmojiPickerActive = () => {},
) => {
const {pageX = 0, pageY = 0} = extractPointerEvent(event);
contextMenuAnchorRef.current = contextMenuAnchor;
Expand All @@ -177,6 +179,7 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor

onPopoverShow.current = onShow;
onPopoverHide.current = onHide;
onEmojiPickerToggle.current = setIsEmojiPickerActive;

new Promise<void>((resolve) => {
if (!pageX && !pageY && contextMenuAnchorRef.current) {
Expand Down Expand Up @@ -329,6 +332,7 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef<Repor
contentRef={contentRef}
originalReportID={originalReportIDRef.current}
disabledActions={disabledActions}
setIsEmojiPickerActive={onEmojiPickerToggle.current}
/>
</PopoverWithMeasuredContent>
<ConfirmModal
Expand Down
3 changes: 3 additions & 0 deletions src/pages/home/report/ContextMenu/ReportActionContextMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type ShowContextMenu = (
isUnreadChat?: boolean,
disabledOptions?: ContextMenuAction[],
shouldCloseOnTarget?: boolean,
setIsEmojiPickerActive?: (state: boolean) => void,
) => void;

type ReportActionContextMenu = {
Expand Down Expand Up @@ -115,6 +116,7 @@ function showContextMenu(
isUnreadChat = false,
disabledActions: ContextMenuAction[] = [],
shouldCloseOnTarget = false,
setIsEmojiPickerActive = () => {},
) {
if (!contextMenuRef.current) {
return;
Expand Down Expand Up @@ -143,6 +145,7 @@ function showContextMenu(
isUnreadChat,
disabledActions,
shouldCloseOnTarget,
setIsEmojiPickerActive,
);
}

Expand Down
13 changes: 11 additions & 2 deletions src/pages/home/report/ReportActionItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ function ReportActionItem(props) {
const StyleUtils = useStyleUtils();
const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT;
const [isContextMenuActive, setIsContextMenuActive] = useState(() => ReportActionContextMenu.isActiveReportAction(props.action.reportActionID));
const [isEmojiPickerActive, setIsEmojiPickerActive] = useState();

const [isHidden, setIsHidden] = useState(false);
const [moderationDecision, setModerationDecision] = useState(CONST.MODERATION.MODERATOR_DECISION_APPROVED);
const reactionListRef = useContext(ReactionListContext);
Expand Down Expand Up @@ -291,6 +293,11 @@ function ReportActionItem(props) {
toggleContextMenuFromActiveReportAction,
ReportUtils.isArchivedRoom(originalReport),
ReportUtils.chatIncludesChronos(originalReport),
false,
false,
[],
false,
setIsEmojiPickerActive,
);
},
[props.draftMessage, props.action, props.report.reportID, toggleContextMenuFromActiveReportAction, originalReport, originalReportID],
Expand Down Expand Up @@ -569,6 +576,7 @@ function ReportActionItem(props) {
toggleReaction(emoji);
}
}}
setIsEmojiPickerActive={setIsEmojiPickerActive}
/>
</View>
)}
Expand Down Expand Up @@ -597,7 +605,7 @@ function ReportActionItem(props) {
* @returns {Object} report action item
*/
const renderReportActionItem = (hovered, isWhisper, hasErrors) => {
const content = renderItemContent(hovered || isContextMenuActive, isWhisper, hasErrors);
const content = renderItemContent(hovered || isContextMenuActive || isEmojiPickerActive, isWhisper, hasErrors);

if (!_.isUndefined(props.draftMessage)) {
return <ReportActionItemDraft>{content}</ReportActionItemDraft>;
Expand Down Expand Up @@ -785,8 +793,9 @@ function ReportActionItem(props) {
draftMessage={props.draftMessage}
isChronosReport={ReportUtils.chatIncludesChronos(originalReport)}
checkIfContextMenuActive={toggleContextMenuFromActiveReportAction}
setIsEmojiPickerActive={setIsEmojiPickerActive}
/>
<View style={StyleUtils.getReportActionItemStyle(hovered || isWhisper || isContextMenuActive || !_.isUndefined(props.draftMessage))}>
<View style={StyleUtils.getReportActionItemStyle(hovered || isWhisper || isContextMenuActive || isEmojiPickerActive || !_.isUndefined(props.draftMessage))}>
<OfflineWithFeedback
onClose={() => ReportActions.clearReportActionErrors(props.report.reportID, props.action)}
pendingAction={
Expand Down

0 comments on commit 97c654e

Please sign in to comment.