Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
Browse files Browse the repository at this point in the history
…x/51296-chat-list-item-v2
  • Loading branch information
wildan-m committed Mar 10, 2025
2 parents 20aa067 + f2a5de7 commit d858e30
Show file tree
Hide file tree
Showing 58 changed files with 564 additions and 222 deletions.
2 changes: 1 addition & 1 deletion Mobile-Expensify
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1009011003
versionName "9.1.10-3"
versionCode 1009011004
versionName "9.1.10-4"
// Supported language variants must be declared here to avoid from being removed during the compilation.
// This also helps us to not include unnecessary language variants in the APK.
resConfigs "en", "es"
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>9.1.10.3</string>
<string>9.1.10.4</string>
<key>FullStory</key>
<dict>
<key>OrgId</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensifyTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>9.1.10.3</string>
<string>9.1.10.4</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion ios/NotificationServiceExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<key>CFBundleShortVersionString</key>
<string>9.1.10</string>
<key>CFBundleVersion</key>
<string>9.1.10.3</string>
<string>9.1.10.4</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
"version": "9.1.10-3",
"version": "9.1.10-4",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
Expand Down
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3445,6 +3445,7 @@ const CONST = {
WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH: 256,
REPORT_NAME_LIMIT: 100,
TITLE_CHARACTER_LIMIT: 100,
TASK_TITLE_CHARACTER_LIMIT: 10000,
DESCRIPTION_LIMIT: 1000,
SEARCH_QUERY_LIMIT: 1000,
WORKSPACE_NAME_CHARACTER_LIMIT: 80,
Expand Down
95 changes: 72 additions & 23 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,28 +524,48 @@ const ROUTES = {
},
MONEY_REQUEST_STEP_AMOUNT: {
route: ':action/:iouType/amount/:transactionID/:reportID/:pageIndex?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, pageIndex: string, backTo = '') =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/amount/${transactionID}/${reportID}/${pageIndex}`, backTo),
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, pageIndex: string, backTo = '') => {
if (!transactionID || !reportID) {
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_AMOUNT route');
}
return getUrlWithBackToParam(`${action as string}/${iouType as string}/amount/${transactionID}/${reportID}/${pageIndex}`, backTo);
},
},
MONEY_REQUEST_STEP_TAX_RATE: {
route: ':action/:iouType/taxRate/:transactionID/:reportID?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '') =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/taxRate/${transactionID}/${reportID}`, backTo),
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
if (!transactionID || !reportID) {
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_TAX_RATE route');
}
return getUrlWithBackToParam(`${action as string}/${iouType as string}/taxRate/${transactionID}/${reportID}`, backTo);
},
},
MONEY_REQUEST_STEP_TAX_AMOUNT: {
route: ':action/:iouType/taxAmount/:transactionID/:reportID?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '') =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/taxAmount/${transactionID}/${reportID}`, backTo),
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
if (!transactionID || !reportID) {
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_TAX_AMOUNT route');
}
return getUrlWithBackToParam(`${action as string}/${iouType as string}/taxAmount/${transactionID}/${reportID}`, backTo);
},
},
MONEY_REQUEST_STEP_CATEGORY: {
route: ':action/:iouType/category/:transactionID/:reportID/:reportActionID?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string | undefined, backTo = '', reportActionID?: string) =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/category/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo),
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '', reportActionID?: string) => {
if (!transactionID || !reportID) {
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_CATEGORY route');
}
return getUrlWithBackToParam(`${action as string}/${iouType as string}/category/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
},
},
MONEY_REQUEST_ATTENDEE: {
route: ':action/:iouType/attendees/:transactionID/:reportID',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '') =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/attendees/${transactionID}/${reportID}`, backTo),
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
if (!transactionID || !reportID) {
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_ATTENDEE route');
}
return getUrlWithBackToParam(`${action as string}/${iouType as string}/attendees/${transactionID}/${reportID}`, backTo);
},
},
MONEY_REQUEST_UPGRADE: {
route: ':action/:iouType/upgrade/:transactionID/:reportID',
Expand Down Expand Up @@ -680,28 +700,48 @@ const ROUTES = {
},
MONEY_REQUEST_STEP_DATE: {
route: ':action/:iouType/date/:transactionID/:reportID/:reportActionID?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '', reportActionID?: string) =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/date/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo),
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '', reportActionID?: string) => {
if (!transactionID || !reportID) {
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_DATE route');
}
return getUrlWithBackToParam(`${action as string}/${iouType as string}/date/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
},
},
MONEY_REQUEST_STEP_DESCRIPTION: {
route: ':action/:iouType/description/:transactionID/:reportID/:reportActionID?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '', reportActionID?: string) =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/description/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo),
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '', reportActionID?: string) => {
if (!transactionID || !reportID) {
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_DESCRIPTION route');
}
return getUrlWithBackToParam(`${action as string}/${iouType as string}/description/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
},
},
MONEY_REQUEST_STEP_DISTANCE: {
route: ':action/:iouType/distance/:transactionID/:reportID',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '') =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/distance/${transactionID}/${reportID}`, backTo),
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
if (!transactionID || !reportID) {
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_DISTANCE route');
}
return getUrlWithBackToParam(`${action as string}/${iouType as string}/distance/${transactionID}/${reportID}`, backTo);
},
},
MONEY_REQUEST_STEP_DISTANCE_RATE: {
route: ':action/:iouType/distanceRate/:transactionID/:reportID',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '') =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/distanceRate/${transactionID}/${reportID}`, backTo),
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
if (!transactionID || !reportID) {
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_DISTANCE_RATE route');
}
return getUrlWithBackToParam(`${action as string}/${iouType as string}/distanceRate/${transactionID}/${reportID}`, backTo);
},
},
MONEY_REQUEST_STEP_MERCHANT: {
route: ':action/:iouType/merchant/:transactionID/:reportID',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '') =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/merchant/${transactionID}/${reportID}`, backTo),
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
if (!transactionID || !reportID) {
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_MERCHANT route');
}
return getUrlWithBackToParam(`${action as string}/${iouType as string}/merchant/${transactionID}/${reportID}`, backTo);
},
},
MONEY_REQUEST_STEP_PARTICIPANTS: {
route: ':action/:iouType/participants/:transactionID/:reportID',
Expand Down Expand Up @@ -1657,12 +1697,21 @@ const ROUTES = {
TRACK_TRAINING_MODAL: 'track-training',
TRAVEL_TRIP_SUMMARY: {
route: 'r/:reportID/trip/:transactionID',
getRoute: (reportID: string, transactionID: string, backTo?: string) => getUrlWithBackToParam(`r/${reportID}/trip/${transactionID}`, backTo),
getRoute: (reportID: string | undefined, transactionID: string | undefined, backTo?: string) => {
if (!reportID || !transactionID) {
Log.warn('Invalid reportID or transactionID is used to build the TRAVEL_TRIP_SUMMARY route');
}
return getUrlWithBackToParam(`r/${reportID}/trip/${transactionID}`, backTo);
},
},
TRAVEL_TRIP_DETAILS: {
route: 'r/:reportID/trip/:transactionID/:reservationIndex',
getRoute: (reportID: string, transactionID: string, reservationIndex: number, backTo?: string) =>
getUrlWithBackToParam(`r/${reportID}/trip/${transactionID}/${reservationIndex}`, backTo),
getRoute: (reportID: string | undefined, transactionID: string | undefined, reservationIndex: number, backTo?: string) => {
if (!reportID || !transactionID) {
Log.warn('Invalid reportID or transactionID is used to build the TRAVEL_TRIP_DETAILS route');
}
return getUrlWithBackToParam(`r/${reportID}/trip/${transactionID}/${reservationIndex}`, backTo);
},
},
TRAVEL_DOMAIN_SELECTOR: 'travel/domain-selector',
TRAVEL_DOMAIN_PERMISSION_INFO: {
Expand Down
19 changes: 16 additions & 3 deletions src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,27 @@ import Tooltip from '@components/Tooltip';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import {canUseTouchScreen} from '@libs/DeviceCapabilities';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import CONST from '@src/CONST';
import type {BaseAnchorForCommentsOnlyProps, LinkProps} from './types';

/*
* This is a default anchor component for regular links.
*/
function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '', target = '', children = null, style, onPress, linkHasImage, ...rest}: BaseAnchorForCommentsOnlyProps) {
function BaseAnchorForCommentsOnly({
onPressIn,
onPressOut,
href = '',
rel = '',
target = '',
children = null,
style,
onPress,
linkHasImage,
wrapperStyle,
...rest
}: BaseAnchorForCommentsOnlyProps) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const linkRef = useRef<RNText>(null);
Expand All @@ -38,7 +50,7 @@ function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '',
} else {
linkProps.href = href;
}
const defaultTextStyle = DeviceCapabilities.canUseTouchScreen() || shouldUseNarrowLayout ? {} : {...styles.userSelectText, ...styles.cursorPointer};
const defaultTextStyle = canUseTouchScreen() || shouldUseNarrowLayout ? {} : {...styles.userSelectText, ...styles.cursorPointer};
const isEmail = Str.isValidEmail(href.replace(/mailto:/i, ''));
const linkHref = !linkHasImage ? href : undefined;

Expand All @@ -62,6 +74,7 @@ function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '',
onPressOut={onPressOut}
role={CONST.ROLE.LINK}
accessibilityLabel={href}
wrapperStyle={wrapperStyle}
>
<Tooltip text={linkHref}>
<Text
Expand Down
5 changes: 4 additions & 1 deletion src/components/AnchorForCommentsOnly/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {StyleProp, TextStyle} from 'react-native';
import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
import type ChildrenProps from '@src/types/utils/ChildrenProps';

type AnchorForCommentsOnlyProps = ChildrenProps & {
Expand All @@ -16,6 +16,9 @@ type AnchorForCommentsOnlyProps = ChildrenProps & {
/** Any additional styles to apply */
style: StyleProp<TextStyle>;

/** Any additional styles to apply to the wrapper */
wrapperStyle?: StyleProp<ViewStyle>;

/** Press handler for the link, when not passed, default href is used to create a link like behaviour */
onPress?: () => void;

Expand Down
6 changes: 6 additions & 0 deletions src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim
tagName: 'edited',
contentModel: HTMLContentModel.textual,
}),
'task-title': HTMLElementModel.fromCustomModel({
tagName: 'task-title',
contentModel: HTMLContentModel.block,
mixedUAStyles: {...styles.taskTitleMenuItem},
}),
'alert-text': HTMLElementModel.fromCustomModel({
tagName: 'alert-text',
mixedUAStyles: {...styles.formError, ...styles.mb0},
Expand Down Expand Up @@ -119,6 +124,7 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim
styles.mutedNormalTextLabel,
styles.onlyEmojisText,
styles.onlyEmojisTextLineHeight,
styles.taskTitleMenuItem,
],
);
/* eslint-enable @typescript-eslint/naming-convention */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import * as HTMLEngineUtils from '@components/HTMLEngineProvider/htmlEngineUtils
import Text from '@components/Text';
import useEnvironment from '@hooks/useEnvironment';
import useThemeStyles from '@hooks/useThemeStyles';
import {getInternalExpensifyPath, getInternalNewExpensifyPath, openLink} from '@libs/actions/Link';
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot';
import * as Link from '@userActions/Link';
import CONST from '@src/CONST';

type AnchorRendererProps = CustomRendererProps<TBlock> & {
Expand All @@ -27,22 +27,24 @@ function AnchorRenderer({tnode, style, key}: AnchorRendererProps) {
const displayName = tNodeChild && 'data' in tNodeChild && typeof tNodeChild.data === 'string' ? tNodeChild.data : '';
const attrHref = htmlAttribs.href || htmlAttribs[CONST.ATTACHMENT_SOURCE_ATTRIBUTE] || '';
const parentStyle = tnode.parent?.styles?.nativeTextRet ?? {};
const internalNewExpensifyPath = Link.getInternalNewExpensifyPath(attrHref);
const internalExpensifyPath = Link.getInternalExpensifyPath(attrHref);
const internalNewExpensifyPath = getInternalNewExpensifyPath(attrHref);
const internalExpensifyPath = getInternalExpensifyPath(attrHref);
const isVideo = attrHref && Str.isVideo(attrHref);
const linkHasImage = tnode.tagName === 'a' && tnode.children.some((child) => child.tagName === 'img');

const isDeleted = HTMLEngineUtils.isDeletedNode(tnode);
const isChildOfTaskTitle = HTMLEngineUtils.isChildOfTaskTitle(tnode);

const textDecorationLineStyle = isDeleted ? styles.underlineLineThrough : {};

if (!HTMLEngineUtils.isChildOfComment(tnode)) {
if (!HTMLEngineUtils.isChildOfComment(tnode) && !isChildOfTaskTitle) {
// This is not a comment from a chat, the AnchorForCommentsOnly uses a Pressable to create a context menu on right click.
// We don't have this behaviour in other links in NewDot
// TODO: We should use TextLink, but I'm leaving it as Text for now because TextLink breaks the alignment in Android.
return (
<Text
style={styles.link}
onPress={() => Link.openLink(attrHref, environmentURL, isAttachment)}
onPress={() => openLink(attrHref, environmentURL, isAttachment)}
suppressHighlighting
>
<TNodeChildrenRenderer tnode={tnode} />
Expand Down Expand Up @@ -70,10 +72,10 @@ function AnchorRenderer({tnode, style, key}: AnchorRendererProps) {
// eslint-disable-next-line react/jsx-props-no-multi-spaces
target={htmlAttribs.target || '_blank'}
rel={htmlAttribs.rel || 'noopener noreferrer'}
style={[style, parentStyle, textDecorationLineStyle, styles.textUnderlinePositionUnder, styles.textDecorationSkipInkNone]}
style={[style, parentStyle, textDecorationLineStyle, styles.textUnderlinePositionUnder, styles.textDecorationSkipInkNone, isChildOfTaskTitle && styles.taskTitleMenuItem]}
key={key}
// Only pass the press handler for internal links. For public links or whitelisted internal links fallback to default link handling
onPress={internalNewExpensifyPath || internalExpensifyPath ? () => Link.openLink(attrHref, environmentURL, isAttachment) : undefined}
onPress={internalNewExpensifyPath || internalExpensifyPath ? () => openLink(attrHref, environmentURL, isAttachment) : undefined}
linkHasImage={linkHasImage}
>
<TNodeChildrenRenderer
Expand Down
Loading

0 comments on commit d858e30

Please sign in to comment.