Skip to content

Commit

Permalink
Merge pull request #48517 from rushatgabhane/fix-copilot-bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
dangrous authored Sep 18, 2024
2 parents 4d2d34e + 747372d commit 3657a67
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 83 deletions.
3 changes: 2 additions & 1 deletion src/components/AccountSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ function AccountSwitcher() {
}}
ref={buttonRef}
interactive={canSwitchAccounts}
pressDimmingValue={canSwitchAccounts ? undefined : 1}
wrapperStyle={[styles.flexGrow1, styles.flex1, styles.mnw0, styles.justifyContentCenter]}
>
<View style={[styles.flexRow, styles.gap3]}>
Expand All @@ -147,7 +148,7 @@ function AccountSwitcher() {
<View style={[styles.flexRow, styles.gap1]}>
<Text
numberOfLines={1}
style={[styles.textBold, styles.textLarge]}
style={[styles.textBold, styles.textLarge, styles.flexShrink1]}
>
{currentUserPersonalDetails?.displayName}
</Text>
Expand Down
13 changes: 9 additions & 4 deletions src/components/AvatarSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import React from 'react';
import {Circle} from 'react-native-svg';
import type {ValueOf} from 'type-fest';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import SkeletonViewContentLoader from './SkeletonViewContentLoader';

function AvatarSkeleton() {
function AvatarSkeleton({size = CONST.AVATAR_SIZE.SMALL}: {size?: ValueOf<typeof CONST.AVATAR_SIZE>}) {
const theme = useTheme();
const skeletonCircleRadius = variables.sidebarAvatarSize / 2;

const StyleUtils = useStyleUtils();
const avatarSize = StyleUtils.getAvatarSize(size);
const skeletonCircleRadius = avatarSize / 2;

return (
<SkeletonViewContentLoader
animate
height={variables.sidebarAvatarSize}
height={avatarSize}
backgroundColor={theme.skeletonLHNIn}
foregroundColor={theme.skeletonLHNOut}
>
Expand Down
8 changes: 6 additions & 2 deletions src/components/AvatarWithImagePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ function AvatarWithImagePicker({
setError(null, {});
}, [isFocused]);

useEffect(() => {
setError(null, {});
}, [source, avatarID]);

/**
* Check if the attachment extension is allowed.
*/
Expand Down Expand Up @@ -325,7 +329,7 @@ function AvatarWithImagePicker({
);

return (
<View style={style}>
<View style={[styles.w100, style]}>
<View style={styles.w100}>
<AttachmentModal
headerTitle={headerTitle}
Expand Down Expand Up @@ -372,7 +376,7 @@ function AvatarWithImagePicker({
accessibilityLabel={translate('avatarWithImagePicker.editImage')}
disabled={isAvatarCropModalOpen || (disabled && !enablePreview)}
disabledStyle={disabledStyle}
style={[styles.pRelative, avatarStyle, type === CONST.ICON_TYPE_AVATAR && styles.alignSelfCenter]}
style={[styles.pRelative, type === CONST.ICON_TYPE_AVATAR && styles.alignSelfCenter, avatarStyle]}
ref={anchorRef}
>
<OfflineWithFeedback pendingAction={pendingAction}>
Expand Down
2 changes: 1 addition & 1 deletion src/libs/actions/Delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Onyx.connect({
},
});

const KEYS_TO_PRESERVE_DELEGATE_ACCESS = [ONYXKEYS.NVP_TRY_FOCUS_MODE, ONYXKEYS.PREFERRED_THEME, ONYXKEYS.NVP_PREFERRED_LOCALE, ONYXKEYS.SESSION];
const KEYS_TO_PRESERVE_DELEGATE_ACCESS = [ONYXKEYS.NVP_TRY_FOCUS_MODE, ONYXKEYS.PREFERRED_THEME, ONYXKEYS.NVP_PREFERRED_LOCALE, ONYXKEYS.SESSION, ONYXKEYS.IS_LOADING_APP];

function connect(email: string) {
if (!delegatedAccess?.delegators) {
Expand Down
106 changes: 37 additions & 69 deletions src/pages/settings/Profile/ProfilePage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
import AvatarSkeleton from '@components/AvatarSkeleton';
import AvatarWithImagePicker from '@components/AvatarWithImagePicker';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
Expand All @@ -16,8 +16,7 @@ import ScrollView from '@components/ScrollView';
import Section from '@components/Section';
import Text from '@components/Text';
import Tooltip from '@components/Tooltip';
import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails';
import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStyleUtils from '@hooks/useStyleUtils';
Expand All @@ -33,44 +32,21 @@ import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {LoginList, PrivatePersonalDetails} from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';

type ProfilePageOnyxProps = {
loginList: OnyxEntry<LoginList>;
/** User's private personal details */
privatePersonalDetails: OnyxEntry<PrivatePersonalDetails>;
/** Whether app is loading */
isLoadingApp: OnyxEntry<boolean>;
};

type ProfilePageProps = ProfilePageOnyxProps & WithCurrentUserPersonalDetailsProps;

function ProfilePage({
loginList,
privatePersonalDetails = {
legalFirstName: '',
legalLastName: '',
dob: '',
addresses: [
{
street: '',
street2: '',
city: '',
state: '',
zip: '',
country: '',
},
],
},
currentUserPersonalDetails,
isLoadingApp,
}: ProfilePageProps) {
function ProfilePage() {
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const {shouldUseNarrowLayout} = useResponsiveLayout();

const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST);
const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS);
const currentUserPersonalDetails = useCurrentUserPersonalDetails();

const isLoadingApp = useOnyx(ONYXKEYS.IS_LOADING_APP);

const getPronouns = (): string => {
const pronounsKey = currentUserPersonalDetails?.pronouns?.replace(CONST.PRONOUNS.PREFIX, '') ?? '';
return pronounsKey ? translate(`pronouns.${pronounsKey}` as TranslationPaths) : translate('profilePage.selectYourPronouns');
Expand Down Expand Up @@ -155,27 +131,31 @@ function ProfilePage({
titleStyles={styles.accountSettingsSectionTitle}
>
<View style={[styles.pt3, styles.pb6, styles.alignSelfStart]}>
<MenuItemGroup shouldUseSingleExecution={false}>
<AvatarWithImagePicker
isUsingDefaultAvatar={UserUtils.isDefaultAvatar(currentUserPersonalDetails?.avatar ?? '')}
source={avatarURL}
avatarID={accountID}
onImageSelected={PersonalDetails.updateAvatar}
onImageRemoved={PersonalDetails.deleteAvatar}
size={CONST.AVATAR_SIZE.XLARGE}
avatarStyle={styles.avatarXLarge}
pendingAction={currentUserPersonalDetails?.pendingFields?.avatar ?? undefined}
errors={currentUserPersonalDetails?.errorFields?.avatar ?? null}
errorRowStyles={styles.mt6}
onErrorClose={PersonalDetails.clearAvatarErrors}
onViewPhotoPress={() => Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(String(accountID)))}
previewSource={UserUtils.getFullSizeAvatar(avatarURL, accountID)}
originalFileName={currentUserPersonalDetails.originalFileName}
headerTitle={translate('profilePage.profileAvatar')}
fallbackIcon={currentUserPersonalDetails?.fallbackIcon}
editIconStyle={styles.profilePageAvatar}
/>
</MenuItemGroup>
{isEmptyObject(currentUserPersonalDetails) || accountID === -1 || !avatarURL ? (
<AvatarSkeleton size={CONST.AVATAR_SIZE.XLARGE} />
) : (
<MenuItemGroup shouldUseSingleExecution={false}>
<AvatarWithImagePicker
isUsingDefaultAvatar={UserUtils.isDefaultAvatar(currentUserPersonalDetails?.avatar ?? '')}
source={avatarURL}
avatarID={accountID}
onImageSelected={PersonalDetails.updateAvatar}
onImageRemoved={PersonalDetails.deleteAvatar}
size={CONST.AVATAR_SIZE.XLARGE}
avatarStyle={[styles.avatarXLarge, styles.alignSelfStart]}
pendingAction={currentUserPersonalDetails?.pendingFields?.avatar ?? undefined}
errors={currentUserPersonalDetails?.errorFields?.avatar ?? null}
errorRowStyles={styles.mt6}
onErrorClose={PersonalDetails.clearAvatarErrors}
onViewPhotoPress={() => Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(String(accountID)))}
previewSource={UserUtils.getFullSizeAvatar(avatarURL, accountID)}
originalFileName={currentUserPersonalDetails.originalFileName}
headerTitle={translate('profilePage.profileAvatar')}
fallbackIcon={currentUserPersonalDetails?.fallbackIcon}
editIconStyle={styles.profilePageAvatar}
/>
</MenuItemGroup>
)}
</View>
{publicOptions.map((detail, index) => (
<MenuItemWithTopDescription
Expand Down Expand Up @@ -244,16 +224,4 @@ function ProfilePage({

ProfilePage.displayName = 'ProfilePage';

export default withCurrentUserPersonalDetails(
withOnyx<ProfilePageProps, ProfilePageOnyxProps>({
loginList: {
key: ONYXKEYS.LOGIN_LIST,
},
privatePersonalDetails: {
key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS,
},
isLoadingApp: {
key: ONYXKEYS.IS_LOADING_APP,
},
})(ProfilePage),
);
export default ProfilePage;
4 changes: 2 additions & 2 deletions src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function useOptions() {
0,
);

const headerMessage = OptionsListUtils.getHeaderMessage((recentReports?.length || 0) + (personalDetails?.length || 0) !== 0 || !!currentUserOption, !!userToInvite, '');
const headerMessage = OptionsListUtils.getHeaderMessage((recentReports?.length || 0) + (personalDetails?.length || 0) !== 0, !!userToInvite, '');

if (isLoading) {
setIsLoading(false);
Expand All @@ -72,7 +72,7 @@ function useOptions() {
maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW,
});
const headerMessage = OptionsListUtils.getHeaderMessage(
(filteredOptions.recentReports?.length || 0) + (filteredOptions.personalDetails?.length || 0) !== 0 || !!filteredOptions.currentUserOption,
(filteredOptions.recentReports?.length || 0) + (filteredOptions.personalDetails?.length || 0) !== 0,
!!filteredOptions.userToInvite,
debouncedSearchValue,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ function SelectDelegateRolePage({route}: SelectDelegateRolePageProps) {
const roleOptions = Object.values(CONST.DELEGATE_ROLE).map((role) => ({
value: role,
text: translate('delegate.role', role),
keyForList: role,
alternateText: translate('delegate.roleDescription', role),
isSelected: role === route.params.role,
keyForList: role,
}));

return (
Expand All @@ -41,6 +41,8 @@ function SelectDelegateRolePage({route}: SelectDelegateRolePageProps) {
<SelectionList
isAlternateTextMultilineSupported
alternateTextNumberOfLines={4}
initiallyFocusedOptionKey={roleOptions.find((role) => role.isSelected)?.keyForList}
shouldUpdateFocusedIndex
headerContent={
<Text style={[styles.ph5, styles.pb5, styles.pt3]}>
<>
Expand Down
6 changes: 3 additions & 3 deletions src/pages/settings/Security/SecuritySettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function SecuritySettingsPage() {
description: personalDetail?.displayName ? formattedEmail : '',
badgeText: translate('delegate.role', role),
avatarID: personalDetail?.accountID ?? -1,
icon: personalDetail?.avatar ?? '',
icon: personalDetail?.avatar ?? FallbackAvatar,
iconType: CONST.ICON_TYPE_AVATAR,
numberOfLinesDescription: 1,
wrapperStyle: [styles.sectionMenuItemTopDescription],
Expand Down Expand Up @@ -163,15 +163,15 @@ function SecuritySettingsPage() {
<Section
title={translate('delegate.copilotDelegatedAccess')}
renderSubtitle={() => (
<View style={[styles.flexRow, styles.alignItemsCenter, styles.w100, styles.mt2]}>
<Text style={[styles.flexRow, styles.alignItemsCenter, styles.w100, styles.mt2]}>
<Text style={[styles.textNormal, styles.colorMuted]}>{translate('delegate.copilotDelegatedAccessDescription')} </Text>
<TextLink
style={[styles.link]}
href={CONST.COPILOT_HELP_URL}
>
{translate('common.learnMore')}
</TextLink>
</View>
</Text>
)}
isCentralPane
subtitleMuted
Expand Down
7 changes: 7 additions & 0 deletions src/pages/settings/Subscription/SubscriptionSettingsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, {useEffect} from 'react';
import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Illustrations from '@components/Icon/Illustrations';
import ScreenWrapper from '@components/ScreenWrapper';
Expand All @@ -11,6 +13,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
import * as Subscription from '@userActions/Subscription';
import ONYXKEYS from '@src/ONYXKEYS';
import CardSection from './CardSection/CardSection';
import ReducedFunctionalityMessage from './ReducedFunctionalityMessage';
import SubscriptionDetails from './SubscriptionDetails';
Expand All @@ -26,7 +29,11 @@ function SubscriptionSettingsPage() {
useEffect(() => {
Subscription.openSubscriptionPage();
}, []);
const [isAppLoading] = useOnyx(ONYXKEYS.IS_LOADING_APP);

if (!subscriptionPlan && isAppLoading) {
return <FullScreenLoadingIndicator />;
}
if (!subscriptionPlan) {
return <NotFoundPage />;
}
Expand Down

0 comments on commit 3657a67

Please sign in to comment.