Skip to content

Commit

Permalink
Merge branch 'main' into wave8/CreatingNewTaxes
Browse files Browse the repository at this point in the history
  • Loading branch information
kosmydel committed Mar 15, 2024
2 parents 438c973 + 4e599b2 commit e94dde9
Show file tree
Hide file tree
Showing 88 changed files with 786 additions and 545 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/deployExpensifyHelp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ jobs:
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: helpdot
directory: ./docs/_site
# Add the conditional on this step to prevent execution for pull requests from forks
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository

- name: Setup Cloudflare CLI
run: pip3 install cloudflare==2.19.0
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001045200
versionName "1.4.52-0"
versionCode 1001045206
versionName "1.4.52-6"
}

flavorDimensions "default"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: Act as a Copilot
description: How to access another account after being granted Copilot permissions
---
<div id="expensify-classic" markdown="1">

After being assigned as a Copilot, you can access the account you’ve been given Copilot permissions to via the Expensify website or the mobile app.

{% include selector.html values="desktop, mobile" %}

{% include option.html value="desktop" %}
To switch to Copilot mode,
1. Click your profile icon in the upper left side of the page.
2. In the “Copilot Access” section of the dropdown, choose the account you wish to access.

The Expensify header will change to blue, and an airplane icon will appear to show that you are in copilot mode. You can return to your own account any time by clicking your profile icon and selecting **Return to your account**.

{% include end-option.html %}

{% include option.html value="mobile" %}
To switch to Copilot mode,
1. Tap the menu icon in the top left.
2. Tap your profile icon.
3. Tap **Switch to Copilot Mode** and choose the account.

An airplane icon will appear to show that you are in copilot mode. To return to your own account, follow the same steps above and select **Return to your account**.

{% include end-option.html %}

{% include end-selector.html %}

# FAQs

**Can a Copilot’s secondary login be used to forward receipts?**

Yes, a Copilot can use any of the email addresses tied to their account to forward receipts into the account they are copiloting. To ensure a receipt is routed to the Expensify account you are copiloting instead of your own account, email the receipt to receipts@expensify.com with the email address of the account you are copiloting as the subject line of the email.

**Can I add another copilot to an account that I’m copiloting?**

No, only the original account holder can add another Copilot to their account.

</div>
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.4.52.0</string>
<string>1.4.52.6</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</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>1.4.52.0</string>
<string>1.4.52.6</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>1.4.52</string>
<key>CFBundleVersion</key>
<string>1.4.52.0</string>
<string>1.4.52.6</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": "1.4.52-0",
"version": "1.4.52-6",
"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
6 changes: 3 additions & 3 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,8 @@ const ONYXKEYS = {
ADD_DEBIT_CARD_FORM: 'addDebitCardForm',
ADD_DEBIT_CARD_FORM_DRAFT: 'addDebitCardFormDraft',
WORKSPACE_SETTINGS_FORM: 'workspaceSettingsForm',
WORKSPACE_CATEGORY_CREATE_FORM: 'workspaceCategoryCreate',
WORKSPACE_CATEGORY_CREATE_FORM_DRAFT: 'workspaceCategoryCreateDraft',
WORKSPACE_CATEGORY_FORM: 'workspaceCategoryForm',
WORKSPACE_CATEGORY_FORM_DRAFT: 'workspaceCategoryFormDraft',
WORKSPACE_TAG_CREATE_FORM: 'workspaceTagCreate',
WORKSPACE_TAG_CREATE_FORM_DRAFT: 'workspaceTagCreateDraft',
WORKSPACE_SETTINGS_FORM_DRAFT: 'workspaceSettingsFormDraft',
Expand Down Expand Up @@ -419,7 +419,7 @@ type AllOnyxKeys = DeepValueOf<typeof ONYXKEYS>;
type OnyxFormValuesMapping = {
[ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM]: FormTypes.AddDebitCardForm;
[ONYXKEYS.FORMS.WORKSPACE_SETTINGS_FORM]: FormTypes.WorkspaceSettingsForm;
[ONYXKEYS.FORMS.WORKSPACE_CATEGORY_CREATE_FORM]: FormTypes.WorkspaceCategoryCreateForm;
[ONYXKEYS.FORMS.WORKSPACE_CATEGORY_FORM]: FormTypes.WorkspaceCategoryForm;
[ONYXKEYS.FORMS.WORKSPACE_TAG_CREATE_FORM]: FormTypes.WorkspaceTagCreateForm;
[ONYXKEYS.FORMS.WORKSPACE_RATE_AND_UNIT_FORM]: FormTypes.WorkspaceRateAndUnitForm;
[ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM]: FormTypes.CloseAccountForm;
Expand Down
6 changes: 5 additions & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ const ROUTES = {
},
WORKSPACE_CATEGORY_SETTINGS: {
route: 'settings/workspaces/:policyID/categories/:categoryName',
getRoute: (policyID: string, categoryName: string) => `settings/workspaces/${policyID}/categories/${encodeURI(categoryName)}` as const,
getRoute: (policyID: string, categoryName: string) => `settings/workspaces/${policyID}/categories/${encodeURIComponent(categoryName)}` as const,
},
WORKSPACE_CATEGORIES_SETTINGS: {
route: 'settings/workspaces/:policyID/categories/settings',
Expand All @@ -569,6 +569,10 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/categories/new',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/categories/new` as const,
},
WORKSPACE_CATEGORY_EDIT: {
route: 'workspace/:policyID/categories/:categoryName/edit',
getRoute: (policyID: string, categoryName: string) => `workspace/${policyID}/categories/${encodeURI(categoryName)}/edit` as const,
},
WORKSPACE_TAGS: {
route: 'settings/workspaces/:policyID/tags',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/tags` as const,
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ const SCREENS = {
SHARE: 'Workspace_Profile_Share',
NAME: 'Workspace_Profile_Name',
CATEGORY_CREATE: 'Category_Create',
CATEGORY_EDIT: 'Category_Edit',
CATEGORY_SETTINGS: 'Category_Settings',
CATEGORIES_SETTINGS: 'Categories_Settings',
MORE_FEATURES: 'Workspace_More_Features',
Expand Down
3 changes: 1 addition & 2 deletions src/components/AvatarCropModal/AvatarCropModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -404,9 +404,8 @@ function AvatarCropModal({imageUri = '', imageName = '', imageType = '', onClose
>
<View>
<Button
medium
icon={Expensicons.Rotate}
iconFill={theme.inverse}
iconFill={theme.icon}
onPress={rotateImage}
/>
</View>
Expand Down
1 change: 1 addition & 0 deletions src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ function Button(
<View style={[large ? styles.mr2 : styles.mr1, !text && styles.mr0, iconStyles]}>
<Icon
src={icon}
hasText={!!text}
fill={iconFill ?? (success || danger ? theme.textLight : theme.icon)}
small={small}
medium={medium}
Expand Down
2 changes: 1 addition & 1 deletion src/components/DistanceRequest/DistanceRequestFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function DistanceRequestFooter({waypoints, transaction, mapboxAccessToken, navig
onPress={() => navigateToWaypointEditPage(Object.keys(transaction?.comment?.waypoints ?? {}).length)}
text={translate('distance.addStop')}
isDisabled={numberOfWaypoints === MAX_WAYPOINTS}
innerStyles={[styles.ph10]}
innerStyles={[styles.pl10, styles.pr10]}
/>
</View>
)}
Expand Down
1 change: 1 addition & 0 deletions src/components/EmojiPicker/EmojiPickerMenu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ function EmojiPickerMenu({forwardedRef, onEmojiSelected, activeEmoji}) {
disableHorizontalKeys: isFocused,
// We pass true without checking visibility of the component because if the popover is not visible this picker won't be mounted
isActive: true,
allowNegativeIndexes: true,
});

const filterEmojis = _.throttle((searchTerm) => {
Expand Down
6 changes: 5 additions & 1 deletion src/components/Icon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ type IconProps = {
/** Is icon pressed */
pressed?: boolean;

/** Is icon will be used with text */
hasText?: boolean;

/** Additional styles to add to the Icon */
additionalStyles?: StyleProp<ViewStyle>;

Expand All @@ -56,6 +59,7 @@ function Icon({
height = variables.iconSizeNormal,
fill = undefined,
small = false,
hasText = false,
large = false,
medium = false,
inline = false,
Expand All @@ -67,7 +71,7 @@ function Icon({
}: IconProps) {
const StyleUtils = useStyleUtils();
const styles = useThemeStyles();
const {width: iconWidth, height: iconHeight} = StyleUtils.getIconWidthAndHeightStyle(small, medium, large, width, height);
const {width: iconWidth, height: iconHeight} = StyleUtils.getIconWidthAndHeightStyle(small, medium, large, width, height, hasText);
const iconStyles = [StyleUtils.getWidthAndHeightStyle(width ?? 0, height), IconWrapperStyles, styles.pAbsolute, additionalStyles];

if (inline) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ type MenuItemBaseProps = {
onSecondaryInteraction?: (event: GestureResponderEvent | MouseEvent) => void;

/** Array of objects that map display names to their corresponding tooltip */
titleWithTooltips?: DisplayNameWithTooltip[];
titleWithTooltips?: DisplayNameWithTooltip[] | undefined;

/** Icon should be displayed in its own color */
displayInDefaultIconColor?: boolean;
Expand Down
10 changes: 5 additions & 5 deletions src/components/VideoPlayerContexts/PlaybackContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ function PlaybackContextProvider({children}: ChildrenProps) {
const {currentReportID} = useCurrentReportID() ?? {};

const pauseVideo = useCallback(() => {
currentVideoPlayerRef.current?.setStatusAsync({shouldPlay: false});
currentVideoPlayerRef.current?.setStatusAsync?.({shouldPlay: false});
}, [currentVideoPlayerRef]);

const stopVideo = useCallback(() => {
currentVideoPlayerRef.current?.stopAsync();
currentVideoPlayerRef.current?.stopAsync?.();
}, [currentVideoPlayerRef]);

const playVideo = useCallback(() => {
currentVideoPlayerRef.current?.getStatusAsync().then((status) => {
currentVideoPlayerRef.current?.getStatusAsync?.().then((status) => {
const newStatus: AVPlaybackStatusToSet = {shouldPlay: true};
if ('durationMillis' in status && status.durationMillis === status.positionMillis) {
newStatus.positionMillis = 0;
Expand All @@ -33,7 +33,7 @@ function PlaybackContextProvider({children}: ChildrenProps) {
}, [currentVideoPlayerRef]);

const unloadVideo = useCallback(() => {
currentVideoPlayerRef.current?.unloadAsync();
currentVideoPlayerRef.current?.unloadAsync?.();
}, [currentVideoPlayerRef]);

const updateCurrentlyPlayingURL = useCallback(
Expand Down Expand Up @@ -61,7 +61,7 @@ function PlaybackContextProvider({children}: ChildrenProps) {

const checkVideoPlaying = useCallback(
(statusCallback: StatusCallback) => {
currentVideoPlayerRef.current?.getStatusAsync().then((status) => {
currentVideoPlayerRef.current?.getStatusAsync?.().then((status) => {
statusCallback('isPlaying' in status && status.isPlaying);
});
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function VideoPopoverMenuContextProvider({children}: ChildrenProps) {
const updatePlaybackSpeed = useCallback(
(speed: PlaybackSpeed) => {
setCurrentPlaybackSpeed(speed);
currentVideoPlayerRef.current?.setStatusAsync({rate: speed});
currentVideoPlayerRef.current?.setStatusAsync?.({rate: speed});
},
[currentVideoPlayerRef],
);
Expand Down
19 changes: 15 additions & 4 deletions src/hooks/useArrowKeyFocusManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Config = {
itemsPerRow?: number;
disableCyclicTraversal?: boolean;
disableHorizontalKeys?: boolean;
allowNegativeIndexes?: boolean;
};

type UseArrowKeyFocusManager = [number, (index: number) => void];
Expand Down Expand Up @@ -44,6 +45,7 @@ export default function useArrowKeyFocusManager({
itemsPerRow,
disableCyclicTraversal = false,
disableHorizontalKeys = false,
allowNegativeIndexes = false,
}: Config): UseArrowKeyFocusManager {
const allowHorizontalArrowKeys = !!itemsPerRow;
const [focusedIndex, setFocusedIndex] = useState(initialFocusedIndex);
Expand Down Expand Up @@ -84,7 +86,13 @@ export default function useArrowKeyFocusManager({
while (disabledIndexes.includes(newFocusedIndex)) {
newFocusedIndex -= allowHorizontalArrowKeys ? itemsPerRow : 1;
if (newFocusedIndex < 0) {
break;
if (disableCyclicTraversal) {
if (!allowNegativeIndexes) {
return actualIndex;
}
break;
}
newFocusedIndex = maxIndex;
}
if (newFocusedIndex === currentFocusedIndex) {
// all indexes are disabled
Expand All @@ -93,7 +101,7 @@ export default function useArrowKeyFocusManager({
}
return newFocusedIndex;
});
}, [allowHorizontalArrowKeys, disableCyclicTraversal, disabledIndexes, itemsPerRow, maxIndex]);
}, [allowHorizontalArrowKeys, disableCyclicTraversal, disabledIndexes, itemsPerRow, maxIndex, allowNegativeIndexes]);

useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ARROW_UP, arrowUpCallback, arrowConfig);

Expand Down Expand Up @@ -127,8 +135,11 @@ export default function useArrowKeyFocusManager({
newFocusedIndex += allowHorizontalArrowKeys ? itemsPerRow : 1;
}

if (newFocusedIndex < 0) {
break;
if (newFocusedIndex > maxIndex) {
if (disableCyclicTraversal) {
return actualIndex;
}
newFocusedIndex = 0;
}
if (newFocusedIndex === currentFocusedIndex) {
// all indexes are disabled
Expand Down
11 changes: 6 additions & 5 deletions src/hooks/useReimbursementAccountStepFormSubmit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,29 @@ import type {OnyxFormKey} from '@src/ONYXKEYS';
import ONYXKEYS from '@src/ONYXKEYS';
import type {SubStepProps} from './useSubStep/types';

type UseReimbursementAccountStepFormSubmitParams = Pick<SubStepProps, 'isEditing' | 'onNext'> & {
type UseReimbursementAccountStepFormSubmitParams = Pick<SubStepProps, 'onNext'> & {
formId?: OnyxFormKey;
fieldIds: Array<FormOnyxKeys<typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM>>;
shouldSaveDraft: boolean;
};

/**
* Hook for handling submit method in ReimbursementAccount substeps.
* When user is in editing mode we should save values only when user confirm that
* @param formId - ID for particular form
* @param isEditing - if form is in editing mode
* @param onNext - callback
* @param fieldIds - field IDs for particular step
* @param shouldSaveDraft - if we should save draft values
*/
export default function useReimbursementAccountStepFormSubmit({
formId = ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM,
isEditing,
onNext,
fieldIds,
shouldSaveDraft,
}: UseReimbursementAccountStepFormSubmitParams) {
return useCallback(
(values: FormOnyxValues<typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM>) => {
if (isEditing) {
if (shouldSaveDraft) {
const stepValues = fieldIds.reduce(
(acc, key) => ({
...acc,
Expand All @@ -40,6 +41,6 @@ export default function useReimbursementAccountStepFormSubmit({

onNext();
},
[isEditing, onNext, formId, fieldIds],
[onNext, formId, fieldIds, shouldSaveDraft],
);
}
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1789,6 +1789,7 @@ export default {
},
genericFailureMessage: 'An error occurred while updating the category, please try again.',
addCategory: 'Add category',
editCategory: 'Edit category',
categoryRequiredError: 'Category name is required.',
existingCategoryError: 'A category with this name already exists.',
invalidCategoryName: 'Invalid category name.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1813,6 +1813,7 @@ export default {
},
genericFailureMessage: 'Se ha producido un error al intentar eliminar la categoría. Por favor, inténtalo más tarde.',
addCategory: 'Añadir categoría',
editCategory: 'Editar categoría',
categoryRequiredError: 'Lo nombre de la categoría es obligatorio.',
existingCategoryError: 'Ya existe una categoría con este nombre.',
invalidCategoryName: 'Lo nombre de la categoría es invalido.',
Expand Down
Loading

0 comments on commit e94dde9

Please sign in to comment.