Skip to content

Commit

Permalink
Merge pull request Expensify#54804 from Krishna2323/krishna2323/issue…
Browse files Browse the repository at this point in the history
…/53617

Tweak UI for deleted message and expense
  • Loading branch information
rlinoz authored Jan 24, 2025
2 parents b883a37 + 5f2028c commit 95cc648
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 92 deletions.
6 changes: 6 additions & 0 deletions assets/images/arrows-leftright.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/images/chatbubble-slash.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,9 @@ const CONST = {
MAX_LENGTH: 83,
},

REVERSED_TRANSACTION_ATTRIBUTE: 'is-reversed-transaction',
HIDDEN_MESSAGE_ATTRIBUTE: 'is-hidden-message',

CALENDAR_PICKER: {
// Numbers were arbitrarily picked.
MIN_YEAR: CURRENT_YEAR - 100,
Expand Down
5 changes: 5 additions & 0 deletions src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim
mixedUAStyles: {...styles.formError, ...styles.mb0},
contentModel: HTMLContentModel.block,
}),
'deleted-action': HTMLElementModel.fromCustomModel({
tagName: 'alert-text',
mixedUAStyles: {...styles.formError, ...styles.mb0},
contentModel: HTMLContentModel.block,
}),
'muted-text': HTMLElementModel.fromCustomModel({
tagName: 'muted-text',
mixedUAStyles: {...styles.colorMuted, ...styles.mb0},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import {View} from 'react-native';
import type {CustomRendererProps, TPhrasing, TText} from 'react-native-render-html';
import {TNodeChildrenRenderer} from 'react-native-render-html';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';

function DeletedActionRenderer({tnode}: CustomRendererProps<TText | TPhrasing>) {
const styles = useThemeStyles();
const theme = useTheme();
const htmlAttribs = tnode.attributes;

const reversedTransactionValue = htmlAttribs[CONST.REVERSED_TRANSACTION_ATTRIBUTE];
const hiddenMessageValue = htmlAttribs[CONST.HIDDEN_MESSAGE_ATTRIBUTE];

const getIcon = () => {
if (reversedTransactionValue === 'true') {
return Expensicons.ArrowsLeftRight;
}
if (hiddenMessageValue === 'true') {
return Expensicons.EyeDisabled;
}
return Expensicons.Trashcan;
};

return (
<View style={[styles.p4, styles.mt1, styles.appBG, styles.border, {borderColor: theme.border}, styles.flexRow, styles.justifyContentCenter, styles.alignItemsCenter, styles.gap2]}>
<Icon
width={variables.iconSizeMedium}
height={variables.iconSizeMedium}
fill={theme.icon}
src={getIcon()}
/>
<TNodeChildrenRenderer
tnode={tnode}
renderChild={(props) => {
const firstChild = props?.childTnode?.children?.at(0);
const data = firstChild && 'data' in firstChild ? firstChild.data : null;

if (typeof data === 'string') {
return <Text style={(styles.textLabelSupporting, styles.textStrong)}>{data}</Text>;
}
return props.childElement;
}}
/>
</View>
);
}

DeletedActionRenderer.displayName = 'DeletedActionRenderer';

export default DeletedActionRenderer;
2 changes: 2 additions & 0 deletions src/components/HTMLEngineProvider/HTMLRenderers/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {CustomTagRendererRecord} from 'react-native-render-html';
import AnchorRenderer from './AnchorRenderer';
import CodeRenderer from './CodeRenderer';
import DeletedActionRenderer from './DeletedActionRenderer';
import EditedRenderer from './EditedRenderer';
import EmojiRenderer from './EmojiRenderer';
import ImageRenderer from './ImageRenderer';
Expand Down Expand Up @@ -30,6 +31,7 @@ const HTMLEngineProviderComponentList: CustomTagRendererRecord = {
'mention-here': MentionHereRenderer,
emoji: EmojiRenderer,
'next-step-email': NextStepEmailRenderer,
'deleted-action': DeletedActionRenderer,
/* eslint-enable @typescript-eslint/naming-convention */
};

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 @@ -7,6 +7,7 @@ import ArrowRightLong from '@assets/images/arrow-right-long.svg';
import ArrowRight from '@assets/images/arrow-right.svg';
import ArrowUpLong from '@assets/images/arrow-up-long.svg';
import UpArrow from '@assets/images/arrow-up.svg';
import ArrowsLeftRight from '@assets/images/arrows-leftright.svg';
import ArrowsUpDown from '@assets/images/arrows-updown.svg';
import AttachmentNotFound from '@assets/images/attachment-not-found.svg';
import AdminRoomAvatar from '@assets/images/avatars/admin-room.svg';
Expand Down Expand Up @@ -43,6 +44,7 @@ import Cash from '@assets/images/cash.svg';
import Chair from '@assets/images/chair.svg';
import ChatBubbleAdd from '@assets/images/chatbubble-add.svg';
import ChatBubbleReply from '@assets/images/chatbubble-reply.svg';
import ChatBubbleSlash from '@assets/images/chatbubble-slash.svg';
import ChatBubbleUnread from '@assets/images/chatbubble-unread.svg';
import ChatBubble from '@assets/images/chatbubble.svg';
import ChatBubbles from '@assets/images/chatbubbles.svg';
Expand Down Expand Up @@ -220,6 +222,7 @@ export {
ArrowRight,
ArrowRightLong,
ArrowsUpDown,
ArrowsLeftRight,
ArrowUpLong,
ArrowDownLong,
AttachmentNotFound,
Expand Down Expand Up @@ -390,6 +393,7 @@ export {
Linkedin,
Instagram,
ChatBubbleAdd,
ChatBubbleSlash,
ChatBubbleUnread,
ChatBubbleReply,
Lightbulb,
Expand Down
68 changes: 24 additions & 44 deletions src/components/ReportActionItem/MoneyRequestAction.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import React from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
import RenderHTML from '@components/RenderHTML';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import * as IOUUtils from '@libs/IOUUtils';
import {isIOUReportPendingCurrencyConversion} from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import {isDeletedParentAction, isReversedTransaction, isSplitBillAction, isTrackExpenseAction} from '@libs/ReportActionsUtils';
import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
Expand All @@ -18,18 +17,7 @@ import type * as OnyxTypes from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import MoneyRequestPreview from './MoneyRequestPreview';

type MoneyRequestActionOnyxProps = {
/** Chat report associated with iouReport */
chatReport: OnyxEntry<OnyxTypes.Report>;

/** IOU report data object */
iouReport: OnyxEntry<OnyxTypes.Report>;

/** Report actions for this report */
reportActions: OnyxEntry<OnyxTypes.ReportActions>;
};

type MoneyRequestActionProps = MoneyRequestActionOnyxProps & {
type MoneyRequestActionProps = {
/** All the data of the action */
action: OnyxTypes.ReportAction;

Expand Down Expand Up @@ -72,9 +60,6 @@ function MoneyRequestAction({
isMostRecentIOUReportAction,
contextMenuAnchor,
checkIfContextMenuActive = () => {},
chatReport,
iouReport,
reportActions,
isHovered = false,
style,
isWhisper = false,
Expand All @@ -83,23 +68,29 @@ function MoneyRequestAction({
const styles = useThemeStyles();
const {translate} = useLocalize();
const {isOffline} = useNetwork();
const isSplitBillAction = ReportActionsUtils.isSplitBillAction(action);
const isTrackExpenseAction = ReportActionsUtils.isTrackExpenseAction(action);
const isActionSplitBill = isSplitBillAction(action);
const isActionTrackExpense = isTrackExpenseAction(action);
const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID || CONST.DEFAULT_NUMBER_ID}`, {canEvict: false});
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID || CONST.DEFAULT_NUMBER_ID}`);
const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${requestReportID}`);

const onMoneyRequestPreviewPressed = () => {
if (isSplitBillAction) {
const reportActionID = action.reportActionID ?? '-1';
if (isActionSplitBill) {
const reportActionID = action.reportActionID;
Navigation.navigate(ROUTES.SPLIT_BILL_DETAILS.getRoute(chatReportID, reportActionID, Navigation.getReportRHPActiveRoute()));
return;
}

const childReportID = action?.childReportID ?? '-1';
const childReportID = action?.childReportID;
if (!childReportID) {
return;
}
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(childReportID));
};

let shouldShowPendingConversionMessage = false;
const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(action);
const isReversedTransaction = ReportActionsUtils.isReversedTransaction(action);
const isParentActionDeleted = isDeletedParentAction(action);
const isTransactionReveresed = isReversedTransaction(action);
if (
!isEmptyObject(iouReport) &&
!isEmptyObject(reportActions) &&
Expand All @@ -108,25 +99,25 @@ function MoneyRequestAction({
action.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD &&
isOffline
) {
shouldShowPendingConversionMessage = IOUUtils.isIOUReportPendingCurrencyConversion(iouReport);
shouldShowPendingConversionMessage = isIOUReportPendingCurrencyConversion(iouReport);
}

if (isDeletedParentAction || isReversedTransaction) {
if (isParentActionDeleted || isTransactionReveresed) {
let message: TranslationPaths;
if (isReversedTransaction) {
if (isTransactionReveresed) {
message = 'parentReportAction.reversedTransaction';
} else {
message = 'parentReportAction.deletedExpense';
}
return <RenderHTML html={`<comment>${translate(message)}</comment>`} />;
return <RenderHTML html={`<deleted-action ${CONST.REVERSED_TRANSACTION_ATTRIBUTE}="${isTransactionReveresed}">${translate(message)}</deleted-action>`} />;
}
return (
<MoneyRequestPreview
iouReportID={requestReportID}
chatReportID={chatReportID}
reportID={reportID}
isBillSplit={isSplitBillAction}
isTrackExpense={isTrackExpenseAction}
isBillSplit={isActionSplitBill}
isTrackExpense={isActionTrackExpense}
action={action}
contextMenuAnchor={contextMenuAnchor}
checkIfContextMenuActive={checkIfContextMenuActive}
Expand All @@ -142,15 +133,4 @@ function MoneyRequestAction({

MoneyRequestAction.displayName = 'MoneyRequestAction';

export default withOnyx<MoneyRequestActionProps, MoneyRequestActionOnyxProps>({
chatReport: {
key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`,
},
iouReport: {
key: ({requestReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${requestReportID}`,
},
reportActions: {
key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID}`,
canEvict: false,
},
})(MoneyRequestAction);
export default MoneyRequestAction;
30 changes: 15 additions & 15 deletions src/components/ReportActionItem/TaskPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ import useLocalize from '@hooks/useLocalize';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {checkIfActionIsAllowed} from '@libs/actions/Session';
import {canActionTask, completeTask, getTaskAssigneeAccountID, reopenTask} from '@libs/actions/Task';
import ControlSelection from '@libs/ControlSelection';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import {canUseTouchScreen} from '@libs/DeviceCapabilities';
import getButtonState from '@libs/getButtonState';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
import * as TaskUtils from '@libs/TaskUtils';
import {isCanceledTaskReport, isOpenTaskReport, isReportManager} from '@libs/ReportUtils';
import {getTaskTitleFromReport} from '@libs/TaskUtils';
import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import * as Session from '@userActions/Session';
import * as Task from '@userActions/Task';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
Expand Down Expand Up @@ -74,27 +74,27 @@ function TaskPreview({taskReportID, action, contextMenuAnchor, chatReportID, che
const isTaskCompleted = !isEmptyObject(taskReport)
? taskReport?.stateNum === CONST.REPORT.STATE_NUM.APPROVED && taskReport.statusNum === CONST.REPORT.STATUS_NUM.APPROVED
: action?.childStateNum === CONST.REPORT.STATE_NUM.APPROVED && action?.childStatusNum === CONST.REPORT.STATUS_NUM.APPROVED;
const taskTitle = Str.htmlEncode(TaskUtils.getTaskTitleFromReport(taskReport, action?.childReportName ?? ''));
const taskAssigneeAccountID = Task.getTaskAssigneeAccountID(taskReport) ?? action?.childManagerAccountID ?? CONST.DEFAULT_NUMBER_ID;
const taskTitle = Str.htmlEncode(getTaskTitleFromReport(taskReport, action?.childReportName ?? ''));
const taskAssigneeAccountID = getTaskAssigneeAccountID(taskReport) ?? action?.childManagerAccountID ?? CONST.DEFAULT_NUMBER_ID;
const taskOwnerAccountID = taskReport?.ownerAccountID ?? action?.actorAccountID ?? CONST.DEFAULT_NUMBER_ID;
const hasAssignee = taskAssigneeAccountID > 0;
const personalDetails = usePersonalDetails();
const avatar = personalDetails?.[taskAssigneeAccountID]?.avatar ?? Expensicons.FallbackAvatar;
const avatarSize = CONST.AVATAR_SIZE.SMALL;
const isDeletedParentAction = ReportUtils.isCanceledTaskReport(taskReport, action);
const isDeletedParentAction = isCanceledTaskReport(taskReport, action);
const iconWrapperStyle = StyleUtils.getTaskPreviewIconWrapper(hasAssignee ? avatarSize : undefined);
const titleStyle = StyleUtils.getTaskPreviewTitleStyle(iconWrapperStyle.height, isTaskCompleted);

const shouldShowGreenDotIndicator = ReportUtils.isOpenTaskReport(taskReport, action) && ReportUtils.isReportManager(taskReport);
const shouldShowGreenDotIndicator = isOpenTaskReport(taskReport, action) && isReportManager(taskReport);
if (isDeletedParentAction) {
return <RenderHTML html={`<comment>${translate('parentReportAction.deletedTask')}</comment>`} />;
return <RenderHTML html={`<deleted-action>${translate('parentReportAction.deletedTask')}</deleted-action>`} />;
}

return (
<View style={[styles.chatItemMessage, !hasAssignee && styles.mv1]}>
<PressableWithoutFeedback
onPress={() => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(taskReportID))}
onPressIn={() => DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()}
onPressIn={() => canUseTouchScreen() && ControlSelection.block()}
onPressOut={() => ControlSelection.unblock()}
onLongPress={(event) => showContextMenuForReport(event, contextMenuAnchor, chatReportID, action, checkIfContextMenuActive)}
shouldUseHapticsOnLongPress
Expand All @@ -107,12 +107,12 @@ function TaskPreview({taskReportID, action, contextMenuAnchor, chatReportID, che
<Checkbox
style={[styles.mr2]}
isChecked={isTaskCompleted}
disabled={!Task.canActionTask(taskReport, currentUserPersonalDetails.accountID, taskOwnerAccountID, taskAssigneeAccountID)}
onPress={Session.checkIfActionIsAllowed(() => {
disabled={!canActionTask(taskReport, currentUserPersonalDetails.accountID, taskOwnerAccountID, taskAssigneeAccountID)}
onPress={checkIfActionIsAllowed(() => {
if (isTaskCompleted) {
Task.reopenTask(taskReport, taskReportID);
reopenTask(taskReport, taskReportID);
} else {
Task.completeTask(taskReport, taskReportID);
completeTask(taskReport, taskReportID);
}
})}
accessibilityLabel={translate('task.task')}
Expand Down
12 changes: 6 additions & 6 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4974,12 +4974,12 @@ const translations = {
viewAttachment: 'View attachment',
},
parentReportAction: {
deletedReport: '[Deleted report]',
deletedMessage: '[Deleted message]',
deletedExpense: '[Deleted expense]',
reversedTransaction: '[Reversed transaction]',
deletedTask: '[Deleted task]',
hiddenMessage: '[Hidden message]',
deletedReport: 'Deleted report',
deletedMessage: 'Deleted message',
deletedExpense: 'Deleted expense',
reversedTransaction: 'Reversed transaction',
deletedTask: 'Deleted task',
hiddenMessage: 'Hidden message',
},
threads: {
thread: 'Thread',
Expand Down
12 changes: 6 additions & 6 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5486,12 +5486,12 @@ const translations = {
viewAttachment: 'Ver archivo adjunto',
},
parentReportAction: {
deletedReport: '[Informe eliminado]',
deletedMessage: '[Mensaje eliminado]',
deletedExpense: '[Gasto eliminado]',
reversedTransaction: '[Transacción anulada]',
deletedTask: '[Tarea eliminada]',
hiddenMessage: '[Mensaje oculto]',
deletedReport: 'Informe eliminado',
deletedMessage: 'Mensaje eliminado',
deletedExpense: 'Gasto eliminado',
reversedTransaction: 'Transacción anulada',
deletedTask: 'Tarea eliminada',
hiddenMessage: 'Mensaje oculto',
},
threads: {
thread: 'Hilo',
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/report/PureReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ function PureReportActionItem({
);
} else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW) {
children = isClosedExpenseReportWithNoExpenses ? (
<RenderHTML html={`<comment>${translate('parentReportAction.deletedReport')}</comment>`} />
<RenderHTML html={`<deleted-action>${translate('parentReportAction.deletedReport')}</deleted-action>`} />
) : (
<ReportPreview
// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
Expand Down
Loading

0 comments on commit 95cc648

Please sign in to comment.