Skip to content

Commit

Permalink
Merge pull request #34031 from esh-g/overflow-menu
Browse files Browse the repository at this point in the history
Add overflow menu to mini context menu
  • Loading branch information
mountiny authored Jan 18, 2024
2 parents 4b7b8f2 + a697f71 commit 99d5850
Show file tree
Hide file tree
Showing 16 changed files with 177 additions and 97 deletions.
13 changes: 13 additions & 0 deletions assets/images/chatbubble-add.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions assets/images/chatbubble-unread.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3121,6 +3121,8 @@ const CONST = {
EMAIL: 'EMAIL',
REPORT: 'REPORT',
},

MINI_CONTEXT_MENU_MAX_ITEMS: 4,
} as const;

export default CONST;
7 changes: 4 additions & 3 deletions src/components/ContextMenuItem.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {ForwardedRef} from 'react';
import React, {forwardRef, useImperativeHandle} from 'react';
import type {GestureResponderEvent} from 'react-native';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import useThrottledButtonState from '@hooks/useThrottledButtonState';
Expand Down Expand Up @@ -27,7 +28,7 @@ type ContextMenuItemProps = {
isMini?: boolean;

/** Callback to fire when the item is pressed */
onPress: () => void;
onPress: (event?: GestureResponderEvent | MouseEvent | KeyboardEvent) => void;

/** A description text to show under the title */
description?: string;
Expand All @@ -52,11 +53,11 @@ function ContextMenuItem(
const {windowWidth} = useWindowDimensions();
const [isThrottledButtonActive, setThrottledButtonInactive] = useThrottledButtonState();

const triggerPressAndUpdateSuccess = () => {
const triggerPressAndUpdateSuccess = (event?: GestureResponderEvent | MouseEvent | KeyboardEvent) => {
if (!isThrottledButtonActive) {
return;
}
onPress();
onPress(event);

// We only set the success state when we have icon or text to represent the success state
// We may want to replace this check by checking the Result from OnPress Callback in future.
Expand Down
4 changes: 4 additions & 0 deletions src/components/Icon/Expensicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import Camera from '@assets/images/camera.svg';
import Car from '@assets/images/car.svg';
import Cash from '@assets/images/cash.svg';
import Chair from '@assets/images/chair.svg';
import ChatBubbleAdd from '@assets/images/chatbubble-add.svg';
import ChatBubbleUnread from '@assets/images/chatbubble-unread.svg';
import ChatBubble from '@assets/images/chatbubble.svg';
import ChatBubbles from '@assets/images/chatbubbles.svg';
import Checkmark from '@assets/images/checkmark.svg';
Expand Down Expand Up @@ -264,4 +266,6 @@ export {
Podcast,
Linkedin,
Instagram,
ChatBubbleAdd,
ChatBubbleUnread,
};
6 changes: 4 additions & 2 deletions src/components/Reactions/MiniQuickEmojiReactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import * as EmojiUtils from '@libs/EmojiUtils';
import getButtonState from '@libs/getButtonState';
import variables from '@styles/variables';
import * as EmojiPickerAction from '@userActions/EmojiPickerAction';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -61,7 +62,7 @@ function MiniQuickEmojiReactions({

return (
<View style={styles.flexRow}>
{CONST.QUICK_REACTIONS.map((emoji: Emoji) => (
{CONST.QUICK_REACTIONS.slice(0, 3).map((emoji: Emoji) => (
<BaseMiniContextMenuItem
key={emoji.name}
isDelayButtonStateComplete={false}
Expand Down Expand Up @@ -90,7 +91,8 @@ function MiniQuickEmojiReactions({
>
{({hovered, pressed}) => (
<Icon
small
width={variables.iconSizeMedium}
height={variables.iconSizeMedium}
src={Expensicons.AddReaction}
fill={StyleUtils.getIconFillColor(getButtonState(hovered, pressed, false))}
/>
Expand Down
5 changes: 3 additions & 2 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,9 +457,10 @@ export default {
deleteConfirmation: ({action}: DeleteConfirmationParams) => `Are you sure you want to delete this ${action?.actionName === CONST.REPORT.ACTIONS.TYPE.IOU ? 'request' : 'comment'}?`,
onlyVisible: 'Only visible to',
replyInThread: 'Reply in thread',
subscribeToThread: 'Subscribe to thread',
unsubscribeFromThread: 'Unsubscribe from thread',
joinThread: 'Join thread',
leaveThread: 'Leave thread',
flagAsOffensive: 'Flag as offensive',
menu: 'Menu',
},
emojiReactions: {
addReactionTooltip: 'Add reaction',
Expand Down
5 changes: 3 additions & 2 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,10 @@ export default {
`¿Estás seguro de que quieres eliminar este ${action?.actionName === CONST.REPORT.ACTIONS.TYPE.IOU ? 'pedido' : 'comentario'}`,
onlyVisible: 'Visible sólo para',
replyInThread: 'Responder en el hilo',
subscribeToThread: 'Suscribirse al hilo',
unsubscribeFromThread: 'Darse de baja del hilo',
joinThread: 'Unirse al hilo',
leaveThread: 'Dejar hilo',
flagAsOffensive: 'Marcar como ofensivo',
menu: 'Menú',
},
emojiReactions: {
addReactionTooltip: 'Añadir una reacción',
Expand Down
2 changes: 1 addition & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3611,7 +3611,7 @@ function getAllPolicyReports(policyID: string): Array<OnyxEntry<Report>> {
/**
* Returns true if Chronos is one of the chat participants (1:1)
*/
function chatIncludesChronos(report: OnyxEntry<Report>): boolean {
function chatIncludesChronos(report: OnyxEntry<Report> | EmptyObject): boolean {
return Boolean(report?.participantAccountIDs?.includes(CONST.ACCOUNT_ID.CHRONOS));
}

Expand Down
15 changes: 12 additions & 3 deletions src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ type BaseReportActionContextMenuProps = BaseReportActionContextMenuOnyxProps & {

/** Content Ref */
contentRef?: RefObject<View>;

checkIfContextMenuActive?: () => void;
};

type MenuItemRefs = Record<string, ContextMenuItemHandle | null>;
Expand All @@ -97,6 +99,7 @@ function BaseReportActionContextMenu({
reportID,
betas,
reportActions,
checkIfContextMenuActive,
}: BaseReportActionContextMenuProps) {
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
Expand All @@ -114,9 +117,13 @@ function BaseReportActionContextMenu({
}, [reportActions, reportActionID]);

const shouldEnableArrowNavigation = !isMini && (isVisible || shouldKeepOpen);
const filteredContextMenuActions = ContextMenuActions.filter((contextAction) =>
contextAction.shouldShow(type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, !!isOffline),
let filteredContextMenuActions = ContextMenuActions.filter((contextAction) =>
contextAction.shouldShow(type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, !!isOffline, isMini),
);
filteredContextMenuActions =
isMini && filteredContextMenuActions.length > CONST.MINI_CONTEXT_MENU_MAX_ITEMS
? ([...filteredContextMenuActions.slice(0, CONST.MINI_CONTEXT_MENU_MAX_ITEMS - 1), filteredContextMenuActions.at(-1)] as typeof filteredContextMenuActions)
: filteredContextMenuActions;

// Context menu actions that are not rendered as menu items are excluded from arrow navigation
const nonMenuItemActionIndexes = filteredContextMenuActions.map((contextAction, index) =>
Expand Down Expand Up @@ -181,6 +188,8 @@ function BaseReportActionContextMenu({
close: () => setShouldKeepOpen(false),
openContextMenu: () => setShouldKeepOpen(true),
interceptAnonymousUser,
anchor,
checkIfContextMenuActive,
};

if ('renderContent' in contextAction) {
Expand All @@ -205,7 +214,7 @@ function BaseReportActionContextMenu({
successText={contextAction.successTextTranslateKey ? translate(contextAction.successTextTranslateKey) : undefined}
isMini={isMini}
key={contextAction.textTranslateKey}
onPress={() => interceptAnonymousUser(() => contextAction.onPress?.(closePopup, payload), contextAction.isAnonymousAction)}
onPress={(event) => interceptAnonymousUser(() => contextAction.onPress?.(closePopup, {...payload, event}), contextAction.isAnonymousAction)}
description={contextAction.getDescription?.(selection) ?? ''}
isAnonymousAction={contextAction.isAnonymousAction}
isFocused={focusedIndex === index}
Expand Down
Loading

0 comments on commit 99d5850

Please sign in to comment.