Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block edit assignee and mark as complete simultaneously #39397

Merged
merged 7 commits into from
Apr 18, 2024
10 changes: 3 additions & 7 deletions src/components/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ function MenuItem(
const StyleUtils = useStyleUtils();
const combinedStyle = [style, styles.popoverMenuItem];
const {isSmallScreenWidth} = useWindowDimensions();
const {isExecuting, singleExecution, waitForNavigate} = useContext(MenuItemGroupContext) ?? {};
const {isExecuting, singleExecution} = useContext(MenuItemGroupContext) ?? {};

const isDeleted = style && Array.isArray(style) ? style.includes(styles.offlineFeedback.deleted) : false;
const descriptionVerticalMargin = shouldShowDescriptionOnTop ? styles.mb1 : styles.mt1;
Expand Down Expand Up @@ -409,15 +409,11 @@ function MenuItem(
}

if (onPress && event) {
if (!singleExecution || !waitForNavigate) {
if (!singleExecution) {
onPress(event);
return;
}
singleExecution(
waitForNavigate(() => {
onPress(event);
}),
)();
singleExecution(onPress)(event);
}
};

Expand Down
17 changes: 14 additions & 3 deletions src/components/TaskHeaderActionButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, {useContext} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
Expand All @@ -10,6 +10,7 @@ import * as Task from '@userActions/Task';
import ONYXKEYS from '@src/ONYXKEYS';
import type * as OnyxTypes from '@src/types/onyx';
import Button from './Button';
import {MenuItemGroupContext} from './MenuItemGroup';

type TaskHeaderActionButtonOnyxProps = {
/** Current user session */
Expand All @@ -24,15 +25,25 @@ type TaskHeaderActionButtonProps = TaskHeaderActionButtonOnyxProps & {
function TaskHeaderActionButton({report, session}: TaskHeaderActionButtonProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const {isExecuting, singleExecution} = useContext(MenuItemGroupContext) ?? {};

const onPressAction = () => {
const onPress = () => (ReportUtils.isCompletedTaskReport(report) ? Task.reopenTask(report) : Task.completeTask(report));
if (!singleExecution) {
onPress();
return;
}
singleExecution(onPress)();
};

return (
<View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentEnd]}>
<Button
success
isDisabled={!Task.canModifyTask(report, session?.accountID ?? 0)}
isDisabled={!Task.canModifyTask(report, session?.accountID ?? 0) || isExecuting}
medium
text={translate(ReportUtils.isCompletedTaskReport(report) ? 'task.markAsIncomplete' : 'task.markAsComplete')}
onPress={Session.checkIfActionIsAllowed(() => (ReportUtils.isCompletedTaskReport(report) ? Task.reopenTask(report) : Task.completeTask(report)))}
onPress={Session.checkIfActionIsAllowed(onPressAction)}
style={styles.flex1}
/>
</View>
Expand Down
151 changes: 77 additions & 74 deletions src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import BlockingView from '@components/BlockingViews/BlockingView';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import DragAndDropProvider from '@components/DragAndDrop/Provider';
import * as Illustrations from '@components/Icon/Illustrations';
import MenuItemGroup from '@components/MenuItemGroup';
import MoneyReportHeader from '@components/MoneyReportHeader';
import MoneyRequestHeader from '@components/MoneyRequestHeader';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
Expand Down Expand Up @@ -628,85 +629,87 @@ function ReportScreen({
return (
<ActionListContext.Provider value={actionListValue}>
<ReactionListContext.Provider value={reactionListRef}>
<ScreenWrapper
navigation={navigation}
style={screenWrapperStyle}
shouldEnableKeyboardAvoidingView={isTopMostReportId}
testID={ReportScreen.displayName}
>
<FullPageNotFoundView
shouldShow={shouldShowNotFoundPage}
subtitleKey="notFound.noAccess"
shouldShowBackButton={isSmallScreenWidth}
onBackButtonPress={Navigation.goBack}
shouldShowLink={false}
<MenuItemGroup>
<ScreenWrapper
navigation={navigation}
style={screenWrapperStyle}
shouldEnableKeyboardAvoidingView={isTopMostReportId}
testID={ReportScreen.displayName}
>
<OfflineWithFeedback
pendingAction={reportPendingAction}
errors={reportErrors}
shouldShowErrorMessages={false}
needsOffscreenAlphaCompositing
<FullPageNotFoundView
shouldShow={shouldShowNotFoundPage}
subtitleKey="notFound.noAccess"
shouldShowBackButton={isSmallScreenWidth}
onBackButtonPress={Navigation.goBack}
shouldShowLink={false}
>
{headerView}
{ReportUtils.isTaskReport(report) && isSmallScreenWidth && ReportUtils.isOpenTaskReport(report, parentReportAction) && (
<View style={[styles.borderBottom]}>
<View style={[styles.appBG, styles.pl0]}>
<View style={[styles.ph5, styles.pb3]}>
<TaskHeaderActionButton report={report} />
<OfflineWithFeedback
pendingAction={reportPendingAction}
errors={reportErrors}
shouldShowErrorMessages={false}
needsOffscreenAlphaCompositing
>
{headerView}
{ReportUtils.isTaskReport(report) && isSmallScreenWidth && ReportUtils.isOpenTaskReport(report, parentReportAction) && (
<View style={[styles.borderBottom]}>
<View style={[styles.appBG, styles.pl0]}>
<View style={[styles.ph5, styles.pb3]}>
<TaskHeaderActionButton report={report} />
</View>
</View>
</View>
</View>
)}
</OfflineWithFeedback>
{!!accountManagerReportID && ReportUtils.isConciergeChatReport(report) && isBannerVisible && (
<Banner
containerStyles={[styles.mh4, styles.mt4, styles.p4, styles.bgDark]}
textStyles={[styles.colorReversed]}
text={translate('reportActionsView.chatWithAccountManager')}
onClose={dismissBanner}
onPress={chatWithAccountManager}
shouldShowCloseButton
/>
)}
<DragAndDropProvider isDisabled={!isCurrentReportLoadedFromOnyx || !ReportUtils.canUserPerformWriteAction(report)}>
<View
style={[styles.flex1, styles.justifyContentEnd, styles.overflowHidden]}
onLayout={onListLayout}
>
{shouldShowReportActionList && (
<ReportActionsView
reportActions={reportActions}
report={report}
parentReportAction={parentReportAction}
isLoadingInitialReportActions={reportMetadata?.isLoadingInitialReportActions}
isLoadingNewerReportActions={reportMetadata?.isLoadingNewerReportActions}
isLoadingOlderReportActions={reportMetadata?.isLoadingOlderReportActions}
isReadyForCommentLinking={!shouldShowSkeleton}
transactionThreadReportID={transactionThreadReportID}
/>
)}

{/* Note: The ReportActionsSkeletonView should be allowed to mount even if the initial report actions are not loaded.
If we prevent rendering the report while they are loading then
we'll unnecessarily unmount the ReportActionsView which will clear the new marker lines initial state. */}
{shouldShowSkeleton && <ReportActionsSkeletonView />}

{isCurrentReportLoadedFromOnyx ? (
<ReportFooter
onComposerFocus={() => setIsComposerFocus(true)}
onComposerBlur={() => setIsComposerFocus(false)}
report={report}
pendingAction={reportPendingAction}
isComposerFullSize={!!isComposerFullSize}
listHeight={listHeight}
isEmptyChat={isEmptyChat}
lastReportAction={lastReportAction}
/>
) : null}
</View>
</DragAndDropProvider>
</FullPageNotFoundView>
</ScreenWrapper>
</OfflineWithFeedback>
{!!accountManagerReportID && ReportUtils.isConciergeChatReport(report) && isBannerVisible && (
<Banner
containerStyles={[styles.mh4, styles.mt4, styles.p4, styles.bgDark]}
textStyles={[styles.colorReversed]}
text={translate('reportActionsView.chatWithAccountManager')}
onClose={dismissBanner}
onPress={chatWithAccountManager}
shouldShowCloseButton
/>
)}
<DragAndDropProvider isDisabled={!isCurrentReportLoadedFromOnyx || !ReportUtils.canUserPerformWriteAction(report)}>
<View
style={[styles.flex1, styles.justifyContentEnd, styles.overflowHidden]}
onLayout={onListLayout}
>
{shouldShowReportActionList && (
<ReportActionsView
reportActions={reportActions}
report={report}
parentReportAction={parentReportAction}
isLoadingInitialReportActions={reportMetadata?.isLoadingInitialReportActions}
isLoadingNewerReportActions={reportMetadata?.isLoadingNewerReportActions}
isLoadingOlderReportActions={reportMetadata?.isLoadingOlderReportActions}
isReadyForCommentLinking={!shouldShowSkeleton}
transactionThreadReportID={transactionThreadReportID}
/>
)}

{/* Note: The ReportActionsSkeletonView should be allowed to mount even if the initial report actions are not loaded.
If we prevent rendering the report while they are loading then
we'll unnecessarily unmount the ReportActionsView which will clear the new marker lines initial state. */}
{shouldShowSkeleton && <ReportActionsSkeletonView />}

{isCurrentReportLoadedFromOnyx ? (
<ReportFooter
onComposerFocus={() => setIsComposerFocus(true)}
onComposerBlur={() => setIsComposerFocus(false)}
report={report}
pendingAction={reportPendingAction}
isComposerFullSize={!!isComposerFullSize}
listHeight={listHeight}
isEmptyChat={isEmptyChat}
lastReportAction={lastReportAction}
/>
) : null}
</View>
</DragAndDropProvider>
</FullPageNotFoundView>
</ScreenWrapper>
</MenuItemGroup>
</ReactionListContext.Provider>
</ActionListContext.Provider>
);
Expand Down
7 changes: 4 additions & 3 deletions src/pages/settings/Profile/ProfilePage.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, {useEffect} from 'react';
import React, {useContext, useEffect} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Illustrations from '@components/Icon/Illustrations';
import MenuItemGroup from '@components/MenuItemGroup';
import MenuItemGroup, {MenuItemGroupContext} from '@components/MenuItemGroup';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import ScreenWrapper from '@components/ScreenWrapper';
import ScrollView from '@components/ScrollView';
Expand Down Expand Up @@ -61,6 +61,7 @@ function ProfilePage({
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const {isSmallScreenWidth} = useWindowDimensions();
const {waitForNavigate} = useContext(MenuItemGroupContext) ?? {};

const getPronouns = (): string => {
const pronounsKey = currentUserPersonalDetails?.pronouns?.replace(CONST.PRONOUNS.PREFIX, '') ?? '';
Expand Down Expand Up @@ -179,7 +180,7 @@ function ProfilePage({
title={detail.title}
description={detail.description}
wrapperStyle={styles.sectionMenuItemTopDescription}
onPress={() => Navigation.navigate(detail.pageRoute)}
onPress={waitForNavigate ? waitForNavigate(() => Navigation.navigate(detail.pageRoute)) : () => Navigation.navigate(detail.pageRoute)}
/>
))}
</>
Expand Down
Loading