Skip to content

Commit

Permalink
Merge branch 'main' of github.com:teneeto/App into feat/31672/add-new…
Browse files Browse the repository at this point in the history
…-input-fields-for-tax-tracking
  • Loading branch information
teneeto committed Jan 3, 2024
2 parents 844fdd4 + 2fe1174 commit 70f3b99
Show file tree
Hide file tree
Showing 76 changed files with 1,006 additions and 635 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/testGithubActionsWorkflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
workflow_call:
pull_request:
types: [opened, reopened, edited, synchronize]
types: [opened, reopened, synchronize]
branches-ignore: [staging, production]
paths: ['.github/**']

Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001042002
versionName "1.4.20-2"
versionCode 1001042101
versionName "1.4.21-1"
}

flavorDimensions "default"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Certinia
description: Guide to connecting Expensify and Certinia FFA and PSA/SRP (formerly known as FinancialForce)
---
# Overview
[Cetinia](https://use.expensify.com/financialforce) (Formerly known as FinancialForce)is a cloud-based software solution that provides a range of financial management and accounting applications built on the Salesforce platform. There are two versions: PSA/SRP and FFA and we support both.
[Cetinia](https://use.expensify.com/financialforce) (formerly known as FinancialForce) is a cloud-based software solution that provides a range of financial management and accounting applications built on the Salesforce platform. There are two versions: PSA/SRP and FFA and we support both.

# Before connecting to Certinia
Install the Expensify bundle in Certinia using the relevant installer:
Expand Down
4 changes: 2 additions & 2 deletions ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.4.20</string>
<string>1.4.21</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
Expand All @@ -40,7 +40,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.4.20.2</string>
<string>1.4.21.1</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
Expand Down
4 changes: 2 additions & 2 deletions ios/NewExpensifyTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.4.20</string>
<string>1.4.21</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.4.20.2</string>
<string>1.4.21.1</string>
</dict>
</plist>
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": "1.4.20-2",
"version": "1.4.21-1",
"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
5 changes: 4 additions & 1 deletion src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ const CONST = {
TRIE_INITIALIZATION: 'trie_initialization',
COMMENT_LENGTH_DEBOUNCE_TIME: 500,
SEARCH_OPTION_LIST_DEBOUNCE_TIME: 300,
RESIZE_DEBOUNCE_TIME: 100,
},
PRIORITY_MODE: {
GSD: 'gsd',
Expand Down Expand Up @@ -853,7 +854,7 @@ const CONST = {
// It's copied here so that the same regex pattern can be used in form validations to be consistent with the server.
VALIDATE_FOR_HTML_TAG_REGEX: /<([^>\s]+)(?:[^>]*?)>/g,

VALIDATE_FOR_LEADINGSPACES_HTML_TAG_REGEX: /<([\s]+[\s\w~!@#$%^&*(){}[\];':"`|?.,/\\+\-=<]+.*[\s]*)>/g,
VALIDATE_FOR_LEADINGSPACES_HTML_TAG_REGEX: /<([\s]+.+[\s]*)>/g,

WHITELISTED_TAGS: [/<>/, /< >/, /<->/, /<-->/, /<br>/, /<br\/>/],

Expand Down Expand Up @@ -979,6 +980,7 @@ const CONST = {
CHAT_FOOTER_SECONDARY_ROW_HEIGHT: 15,
CHAT_FOOTER_SECONDARY_ROW_PADDING: 5,
CHAT_FOOTER_MIN_HEIGHT: 65,
CHAT_FOOTER_HORIZONTAL_PADDING: 40,
CHAT_SKELETON_VIEW: {
AVERAGE_ROW_HEIGHT: 80,
HEIGHT_FOR_ROW_COUNT: {
Expand Down Expand Up @@ -1174,6 +1176,7 @@ const CONST = {
EXPENSIFY: 'Expensify',
VBBA: 'ACH',
},
DEFAULT_AMOUNT: 0,
TYPE: {
SEND: 'send',
SPLIT: 'split',
Expand Down
13 changes: 9 additions & 4 deletions src/components/AddressSearch/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ const propTypes = {
/** Information about the network */
network: networkPropTypes.isRequired,

/** Location bias for querying search results. */
locationBias: PropTypes.string,

...withLocalizePropTypes,
};

Expand Down Expand Up @@ -138,6 +141,7 @@ const defaultProps = {
maxInputLength: undefined,
predefinedPlaces: [],
resultTypes: 'address',
locationBias: undefined,
};

function AddressSearch({
Expand All @@ -162,6 +166,7 @@ function AddressSearch({
shouldSaveDraft,
translate,
value,
locationBias,
}) {
const theme = useTheme();
const styles = useThemeStyles();
Expand All @@ -179,11 +184,11 @@ function AddressSearch({
language: preferredLocale,
types: resultTypes,
components: isLimitedToUSA ? 'country:us' : undefined,
...(locationBias && {locationbias: locationBias}),
}),
[preferredLocale, resultTypes, isLimitedToUSA],
[preferredLocale, resultTypes, isLimitedToUSA, locationBias],
);
const shouldShowCurrentLocationButton = canUseCurrentLocation && searchValue.trim().length === 0 && isFocused;

const saveLocationDetails = (autocompleteData, details) => {
const addressComponents = details.address_components;
if (!addressComponents) {
Expand All @@ -192,7 +197,7 @@ function AddressSearch({
// amount of data massaging needs to happen for what the parent expects to get from this function.
if (_.size(details)) {
onPress({
address: lodashGet(details, 'description'),
address: autocompleteData.description || lodashGet(details, 'description', ''),
lat: lodashGet(details, 'geometry.location.lat', 0),
lng: lodashGet(details, 'geometry.location.lng', 0),
name: lodashGet(details, 'name'),
Expand Down Expand Up @@ -261,7 +266,7 @@ function AddressSearch({

lat: lodashGet(details, 'geometry.location.lat', 0),
lng: lodashGet(details, 'geometry.location.lng', 0),
address: lodashGet(details, 'formatted_address', ''),
address: autocompleteData.description || lodashGet(details, 'formatted_address', ''),
};

// If the address is not in the US, use the full length state name since we're displaying the address's
Expand Down
6 changes: 3 additions & 3 deletions src/components/ArchivedReportFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ function ArchivedReportFooter({report, reportClosedAction, personalDetails = {}}

const originalMessage = reportClosedAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED ? reportClosedAction.originalMessage : null;
const archiveReason = originalMessage?.reason ?? CONST.REPORT.ARCHIVE_REASON.DEFAULT;
let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[report?.ownerAccountID ?? 0]?.displayName);
let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[report?.ownerAccountID ?? 0]);

let oldDisplayName: string | undefined;
if (archiveReason === CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED) {
const newAccountID = originalMessage?.newAccountID;
const oldAccountID = originalMessage?.oldAccountID;
displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[newAccountID ?? 0]?.displayName);
oldDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[oldAccountID ?? 0]?.displayName);
displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[newAccountID ?? 0]);
oldDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[oldAccountID ?? 0]);
}

const shouldRenderHTML = archiveReason !== CONST.REPORT.ARCHIVE_REASON.DEFAULT;
Expand Down
12 changes: 10 additions & 2 deletions src/components/AttachmentModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,14 @@ function AttachmentModal(props) {
setIsModalOpen(true);
}, []);

useEffect(() => {
setSource(props.source);
}, [props.source]);

useEffect(() => {
setIsAuthTokenRequired(props.isAuthTokenRequired);
}, [props.isAuthTokenRequired]);

const sourceForAttachmentView = props.source || source;

const threeDotsMenuItems = useMemo(() => {
Expand All @@ -368,7 +376,7 @@ function AttachmentModal(props) {
const parentReportAction = props.parentReportActions[props.report.parentReportActionID];

const canEdit =
ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, props.parentReport.reportID, CONST.EDIT_REQUEST_FIELD.RECEIPT) &&
ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, props.parentReport.reportID, CONST.EDIT_REQUEST_FIELD.RECEIPT, props.transaction) &&
!TransactionUtils.isDistanceRequest(props.transaction);
if (canEdit) {
menuItems.push({
Expand Down Expand Up @@ -396,7 +404,7 @@ function AttachmentModal(props) {
}
return menuItems;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.isReceiptAttachment, props.parentReport, props.parentReportActions, props.policy, props.transaction, file]);
}, [props.isReceiptAttachment, props.parentReport, props.parentReportActions, props.policy, props.transaction, file, source]);

// There are a few things that shouldn't be set until we absolutely know if the file is a receipt or an attachment.
// props.isReceiptAttachment will be null until its certain what the file is, in which case it will then be true|false.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {FlashList} from '@shopify/flash-list';
import React, {ForwardedRef, forwardRef, ReactElement, useCallback, useEffect, useRef} from 'react';
import React, {ForwardedRef, forwardRef, ReactElement, useCallback, useEffect, useMemo, useRef} from 'react';
import {View} from 'react-native';
// We take ScrollView from this package to properly handle the scrolling of AutoCompleteSuggestions in chats since one scroll is nested inside another
import {ScrollView} from 'react-native-gesture-handler';
Expand All @@ -8,6 +8,8 @@ import ColorSchemeWrapper from '@components/ColorSchemeWrapper';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import viewForwardedRef from '@src/types/utils/viewForwardedRef';
import type {AutoCompleteSuggestionsProps, RenderSuggestionMenuItemProps} from './types';
Expand Down Expand Up @@ -39,6 +41,7 @@ function BaseAutoCompleteSuggestions<TSuggestion>(
}: AutoCompleteSuggestionsProps<TSuggestion>,
ref: ForwardedRef<View | HTMLDivElement>,
) {
const {windowWidth, isLargeScreenWidth} = useWindowDimensions();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const rowHeight = useSharedValue(0);
Expand All @@ -64,7 +67,13 @@ function BaseAutoCompleteSuggestions<TSuggestion>(

const innerHeight = CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT * suggestions.length;
const animatedStyles = useAnimatedStyle(() => StyleUtils.getAutoCompleteSuggestionContainerStyle(rowHeight.value));

const estimatedListSize = useMemo(
() => ({
height: CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT * suggestions.length,
width: (isLargeScreenWidth ? windowWidth - variables.sideBarWidth : windowWidth) - CONST.CHAT_FOOTER_HORIZONTAL_PADDING,
}),
[isLargeScreenWidth, suggestions.length, windowWidth],
);
useEffect(() => {
rowHeight.value = withTiming(measureHeightOfSuggestionRows(suggestions.length, isSuggestionPickerLarge), {
duration: 100,
Expand All @@ -88,6 +97,7 @@ function BaseAutoCompleteSuggestions<TSuggestion>(
<ColorSchemeWrapper>
<FlashList
estimatedItemSize={CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT}
estimatedListSize={estimatedListSize}
ref={scrollRef}
keyboardShouldPersistTaps="handled"
data={suggestions}
Expand Down
63 changes: 44 additions & 19 deletions src/components/CustomStatusBarAndBackground/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, {useCallback, useContext, useEffect, useRef, useState} from 'react';
import {interpolateColor, runOnJS, useAnimatedReaction, useSharedValue, withDelay, withTiming} from 'react-native-reanimated';
import useTheme from '@hooks/useTheme';
import {navigationRef} from '@libs/Navigation/Navigation';
import StatusBar from '@libs/StatusBar';
Expand Down Expand Up @@ -33,7 +34,27 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack
};
}, [disableRootStatusBar, isNested]);

const prevStatusBarBackgroundColor = useRef(theme.appBG);
const statusBarBackgroundColor = useRef(theme.appBG);
const statusBarAnimation = useSharedValue(0);

useAnimatedReaction(
() => statusBarAnimation.value,
(current, previous) => {
// Do not run if either of the animated value is null
// or previous animated value is greater than or equal to the current one
if (previous === null || current === null || current <= previous) {
return;
}
const backgroundColor = interpolateColor(statusBarAnimation.value, [0, 1], [prevStatusBarBackgroundColor.current, statusBarBackgroundColor.current]);
runOnJS(updateStatusBarAppearance)({backgroundColor});
},
);

const listenerCount = useRef(0);

// Updates the status bar style and background color depending on the current route and theme
// This callback is triggered everytime the route changes or the theme changes
const updateStatusBarStyle = useCallback(
(listenerId?: number) => {
// Check if this function is either called through the current navigation listener or the general useEffect which listens for theme changes.
Expand All @@ -49,27 +70,40 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack
currentRoute = navigationRef.getCurrentRoute();
}

let currentScreenBackgroundColor = theme.appBG;
let newStatusBarStyle = theme.statusBarStyle;
let currentScreenBackgroundColor = theme.appBG;
if (currentRoute && 'name' in currentRoute && currentRoute.name in theme.PAGE_THEMES) {
const screenTheme = theme.PAGE_THEMES[currentRoute.name];
currentScreenBackgroundColor = screenTheme.backgroundColor;
newStatusBarStyle = screenTheme.statusBarStyle;
const pageTheme = theme.PAGE_THEMES[currentRoute.name];

newStatusBarStyle = pageTheme.statusBarStyle;

const backgroundColorFromRoute =
currentRoute?.params && 'backgroundColor' in currentRoute.params && typeof currentRoute.params.backgroundColor === 'string' && currentRoute.params.backgroundColor;

// It's possible for backgroundColorFromRoute to be empty string, so we must use "||" to fallback to backgroundColorFallback.
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
currentScreenBackgroundColor = backgroundColorFromRoute || pageTheme.backgroundColor;
}

prevStatusBarBackgroundColor.current = statusBarBackgroundColor.current;
statusBarBackgroundColor.current = currentScreenBackgroundColor;

if (currentScreenBackgroundColor !== theme.appBG || prevStatusBarBackgroundColor.current !== theme.appBG) {
statusBarAnimation.value = 0;
statusBarAnimation.value = withDelay(300, withTiming(1));
}

// Don't update the status bar style if it's the same as the current one, to prevent flashing.
if (newStatusBarStyle === statusBarStyle) {
updateStatusBarAppearance({backgroundColor: currentScreenBackgroundColor});
} else {
updateStatusBarAppearance({backgroundColor: currentScreenBackgroundColor, statusBarStyle: newStatusBarStyle});
if (newStatusBarStyle !== statusBarStyle) {
updateStatusBarAppearance({statusBarStyle: newStatusBarStyle});
setStatusBarStyle(newStatusBarStyle);
}
},
[statusBarStyle, theme.PAGE_THEMES, theme.appBG, theme.statusBarStyle],
[statusBarAnimation, statusBarStyle, theme.PAGE_THEMES, theme.appBG, theme.statusBarStyle],
);

// Add navigation state listeners to update the status bar every time the route changes
// We have to pass a count as the listener id, because "react-navigation" somehow doesn't remove listeners properyl
// We have to pass a count as the listener id, because "react-navigation" somehow doesn't remove listeners properly
useEffect(() => {
if (isDisabled) {
return;
Expand All @@ -82,15 +116,6 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack
return () => navigationRef.removeListener('state', listener);
}, [isDisabled, theme.appBG, updateStatusBarStyle]);

// Update the status bar style everytime the theme changes
useEffect(() => {
if (isDisabled) {
return;
}

updateStatusBarStyle();
}, [isDisabled, theme, updateStatusBarStyle]);

// Update the global background (on web) everytime the theme changes.
// The background of the html element needs to be updated, otherwise you will see a big contrast when resizing the window or when the keyboard is open on iOS web.
useEffect(() => {
Expand Down
Loading

0 comments on commit 70f3b99

Please sign in to comment.