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

Support read only messages #40010

Merged
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
7f4f512
feat: added component for displaying static message inm onboarding
barttom Mar 21, 2024
297a231
Merge branch 'feat/38773/support-read-only-messages' of https://githu…
rezkiy37 Apr 10, 2024
cd7a95f
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 17, 2024
26bcce6
add permissions to report
rezkiy37 Apr 17, 2024
de29862
create isReadOnly
rezkiy37 Apr 17, 2024
e2ad69d
integrate OnboardingReportFooterMessage into ReportFooter
rezkiy37 Apr 17, 2024
471a02a
prettify
rezkiy37 Apr 17, 2024
b4aed0f
restrict task action in header
rezkiy37 Apr 17, 2024
0c1efc3
read only for TaskView
rezkiy37 Apr 17, 2024
d72ceab
read only for TaskPreview
rezkiy37 Apr 17, 2024
287fbe1
read only for HeaderView
rezkiy37 Apr 17, 2024
7adce5f
Merge branch 'feature/38771-tasks-for-guided-setup' of https://github…
rezkiy37 Apr 18, 2024
c386da0
fix isReadOnly condition
rezkiy37 Apr 18, 2024
8243a2b
improve OnboardingReportFooterMessage
rezkiy37 Apr 18, 2024
3896162
add permissions to report
rezkiy37 Apr 18, 2024
af3b05f
improve read only for tasks
rezkiy37 Apr 18, 2024
09a118c
Consierge read only
rezkiy37 Apr 18, 2024
cd25155
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 22, 2024
15478c0
revert dev change
rezkiy37 Apr 22, 2024
c5da50e
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 23, 2024
6b41cde
restrict actions for read-only chats
rezkiy37 Apr 23, 2024
84c583b
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 24, 2024
1b7d32a
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 25, 2024
990e3cb
translate
rezkiy37 Apr 25, 2024
8fa54e6
remove todo
rezkiy37 Apr 25, 2024
a93647a
fix translations
rezkiy37 Apr 25, 2024
23b0ba0
Concierge read-only
rezkiy37 Apr 25, 2024
ace67dc
Revert "Concierge read-only"
rezkiy37 Apr 25, 2024
517253c
improve OnboardingReportFooterMessage
rezkiy37 Apr 25, 2024
c98a79f
fix check in ContextMenuActions
rezkiy37 Apr 25, 2024
68bcbd2
fix comment
rezkiy37 Apr 25, 2024
ab9b7f2
reuse Banner
rezkiy37 Apr 25, 2024
5eb36c8
add missed line
rezkiy37 Apr 25, 2024
a35ea06
clarify type
rezkiy37 Apr 25, 2024
cfc1231
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 26, 2024
a85b757
redesign OnboardingReportFooterMessage
rezkiy37 Apr 26, 2024
4a92c91
update a place
rezkiy37 Apr 26, 2024
2f17417
rename fucntion
rezkiy37 Apr 26, 2024
ae9af7f
integrate canWriteInReport properly
rezkiy37 Apr 26, 2024
3512f7c
fix report footer styles
rezkiy37 Apr 26, 2024
0c80ad7
prettify
rezkiy37 Apr 26, 2024
9076bc0
rename the component
rezkiy37 Apr 26, 2024
62b193a
rename keys
rezkiy37 Apr 26, 2024
90a72e9
simplify admin chat getting
rezkiy37 Apr 26, 2024
907167c
improve admin chat searching
rezkiy37 Apr 26, 2024
38cbb1b
attach chatReportIDAdmins to policy optimistically
rezkiy37 Apr 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,12 @@ const CONST = {
OWNER_EMAIL_FAKE: '__FAKE__',
OWNER_ACCOUNT_ID_FAKE: 0,
DEFAULT_REPORT_NAME: 'Chat Report',
PERMISSIONS: {
READ: 'read',
WRITE: 'write',
SHARE: 'share',
OWN: 'own',
},
},
NEXT_STEP: {
FINISHED: 'Finished!',
Expand Down
30 changes: 25 additions & 5 deletions src/components/Banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import getButtonState from '@libs/getButtonState';
import CONST from '@src/CONST';
import type IconAsset from '@src/types/utils/IconAsset';
import Hoverable from './Hoverable';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
Expand All @@ -17,7 +18,13 @@ import Tooltip from './Tooltip';

type BannerProps = {
/** Text to display in the banner. */
text: string;
text?: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this become optional? A banner without text sounds weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's because I've added the content property for a case when I need to pass a react node, not a simple text.


/** Content to display in the banner. */
content?: React.ReactNode;

/** The icon asset to display to the left of the text */
icon?: IconAsset | null;

/** Should this component render the left-aligned exclamation icon? */
shouldShowIcon?: boolean;
Expand All @@ -41,7 +48,18 @@ type BannerProps = {
textStyles?: StyleProp<TextStyle>;
};

function Banner({text, onClose, onPress, containerStyles, textStyles, shouldRenderHTML = false, shouldShowIcon = false, shouldShowCloseButton = false}: BannerProps) {
function Banner({
text,
content,
icon = Expensicons.Exclamation,
onClose,
onPress,
containerStyles,
textStyles,
shouldRenderHTML = false,
shouldShowIcon = false,
shouldShowCloseButton = false,
}: BannerProps) {
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
Expand All @@ -65,15 +83,17 @@ function Banner({text, onClose, onPress, containerStyles, textStyles, shouldRend
]}
>
<View style={[styles.flexRow, styles.flexGrow1, styles.mw100, styles.alignItemsCenter]}>
{shouldShowIcon && (
{shouldShowIcon && icon && (
<View style={[styles.mr3]}>
<Icon
src={Expensicons.Exclamation}
src={icon}
fill={StyleUtils.getIconFillColor(getButtonState(shouldHighlight))}
/>
</View>
)}
{shouldRenderHTML ? (
{content && content}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB: Should we use a Boolean here? I feel like it looks a bit more readable that way

Suggested change
{content && content}
{!!content && content}


{shouldRenderHTML && text ? (
<RenderHTML html={text} />
) : (
<Text
Expand Down
4 changes: 4 additions & 0 deletions src/components/TaskHeaderActionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ function TaskHeaderActionButton({report, session}: TaskHeaderActionButtonProps)
const {translate} = useLocalize();
const styles = useThemeStyles();

if (!ReportUtils.canWriteInReport(report)) {
return null;
}

return (
<View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentEnd]}>
<Button
Expand Down
10 changes: 10 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2763,6 +2763,16 @@ export default {
},
copyReferralLink: 'Copy invite link',
},
onboardingBottomMessage: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose to name this systemChatFooterMessage

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - 62b193a.

[CONST.INTRO_CHOICES.MANAGE_TEAM]: {
phrase1: 'Chat with your setup specialist in ',
phrase2: ' for help',
},
default: {
phrase1: 'Message ',
phrase2: ' for help with setup',
},
},
violations: {
allTagLevelsRequired: 'All tags required',
autoReportedRejectedExpense: ({rejectReason, rejectedBy}: ViolationsAutoReportedRejectedExpenseParams) => `${rejectedBy} rejected this expense with the comment "${rejectReason}"`,
Expand Down
10 changes: 10 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3256,6 +3256,16 @@ export default {
},
copyReferralLink: 'Copiar enlace de invitación',
},
onboardingBottomMessage: {
[CONST.INTRO_CHOICES.MANAGE_TEAM]: {
phrase1: 'Chatea con tu especialista asignado en ',
phrase2: ' para obtener ayuda',
},
default: {
phrase1: 'Envía un email a ',
phrase2: ' para obtener ayuda con la configuración',
},
Comment on lines +3260 to +3267
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would check the style does not go crazy in Spanish because I think the translations is slightly longer

},
violations: {
allTagLevelsRequired: 'Todas las etiquetas son obligatorias',
autoReportedRejectedExpense: ({rejectedBy, rejectReason}: ViolationsAutoReportedRejectedExpenseParams) => `${rejectedBy} rechazó la solicitud y comentó "${rejectReason}"`,
Expand Down
20 changes: 18 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1173,10 +1173,25 @@ function isJoinRequestInAdminRoom(report: OnyxEntry<Report>): boolean {
return ReportActionsUtils.isActionableJoinRequestPending(report.reportID);
}

/**
* Checks if the user can write in the provided report
*/
function canWriteInReport(report: OnyxEntry<Report>): boolean {
if (Array.isArray(report?.permissions) && report?.permissions.length > 0) {
return report?.permissions?.includes(CONST.REPORT.PERMISSIONS.WRITE);
}

return true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If permissions are not an array or the array length is 0, I think this should return false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yes, because it is a new property and I am not sure if it is applied to all kinds of reports. If we return false then all legacy chats will be "read-only".
cc @mountiny

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example:

Screenshot 2024-04-26 at 17 06 19

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Web, we do not return the permissions and we dont return it from the getChats method hence in OpenApp (which uses that method) we also do not include permissions. Its only added in the structureReportForOnyx

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We however return this in the OpenReport using the getStructuredOnyxReportAndLastMessageData

So actually the only one I found that does not have the permissions is the selfDM 🤔 although I see the report should be shared with read, write permissions cc @thienlnam

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah this is because the user owns the report and is so is not in the sharedReports table. Maybe we can an owner check and then populate those permissions in the response

}

/**
* Checks if the current user is allowed to comment on the given report.
*/
function isAllowedToComment(report: OnyxEntry<Report>): boolean {
if (!canWriteInReport(report)) {
return false;
}

// Default to allowing all users to post
const capability = report?.writeCapability ?? CONST.REPORT.WRITE_CAPABILITIES.ALL;

Expand Down Expand Up @@ -5375,7 +5390,7 @@ function canUserPerformWriteAction(report: OnyxEntry<Report>) {
return false;
}

return !isArchivedRoom(report) && isEmptyObject(reportErrors) && report && isAllowedToComment(report) && !isAnonymousUser;
return !isArchivedRoom(report) && isEmptyObject(reportErrors) && report && isAllowedToComment(report) && !isAnonymousUser && canWriteInReport(report);
}

/**
Expand Down Expand Up @@ -6282,7 +6297,6 @@ export {
getParsedComment,
getParticipantAccountIDs,
getParticipants,
getPayeeName,
getPendingChatMembers,
getPersonalDetailsForAccountID,
getPolicyDescriptionText,
Expand Down Expand Up @@ -6317,6 +6331,7 @@ export {
getWorkspaceChats,
getWorkspaceIcon,
goBackToDetailsPage,
getPayeeName,
hasActionsWithErrors,
hasAutomatedExpensifyAccountIDs,
hasExpensifyGuidesEmails,
Expand Down Expand Up @@ -6404,6 +6419,7 @@ export {
isValidReport,
isValidReportIDFromPath,
isWaitingForAssigneeToCompleteTask,
canWriteInReport,
navigateToDetailsPage,
navigateToPrivateNotes,
parseReportRouteParams,
Expand Down
4 changes: 4 additions & 0 deletions src/libs/actions/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,10 @@ function canModifyTask(taskReport: OnyxEntry<OnyxTypes.Report>, sessionAccountID
return true;
}

if (!ReportUtils.canWriteInReport(ReportUtils.getReport(taskReport?.reportID))) {
return false;
}

return !isEmptyObject(taskReport) && ReportUtils.isAllowedToComment(taskReport);
}

Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/HeaderView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ function HeaderView({
}

// Task is not closed
if (report.stateNum !== CONST.REPORT.STATE_NUM.APPROVED && report.statusNum !== CONST.REPORT.STATUS_NUM.CLOSED && canModifyTask) {
if (ReportUtils.canWriteInReport(report) && report.stateNum !== CONST.REPORT.STATE_NUM.APPROVED && report.statusNum !== CONST.REPORT.STATUS_NUM.CLOSED && canModifyTask) {
threeDotMenuItems.push({
icon: Expensicons.Trashcan,
text: translate('common.delete'),
Expand Down
2 changes: 2 additions & 0 deletions src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ function ReportScreen({
isOptimisticReport: reportProp?.isOptimisticReport,
lastMentionedTime: reportProp?.lastMentionedTime,
avatarUrl: reportProp?.avatarUrl,
permissions: reportProp?.permissions,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a user signs-in via google after viewing a public room, the permissions was not getting updated. A deep comparison was required here to update the dependency. This caused #41955 where the composer was not getting displayed even after signing-in via google.

}),
[
reportProp?.lastReadTime,
Expand Down Expand Up @@ -249,6 +250,7 @@ function ReportScreen({
reportProp?.isOptimisticReport,
reportProp?.lastMentionedTime,
reportProp?.avatarUrl,
reportProp?.permissions,
],
);

Expand Down
13 changes: 13 additions & 0 deletions src/pages/home/report/ContextMenu/ContextMenuActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -517,5 +517,18 @@ const ContextMenuActions: ContextMenuAction[] = [
},
];

const restrictedReadOnlyActions: TranslationPaths[] = [
'common.download',
'reportActionContextMenu.replyInThread',
'reportActionContextMenu.editAction',
'reportActionContextMenu.joinThread',
'reportActionContextMenu.deleteAction',
];

const RestrictedReadOnlyContextMenuActions: ContextMenuAction[] = ContextMenuActions.filter(
(action) => 'textTranslateKey' in action && restrictedReadOnlyActions.includes(action.textTranslateKey),
);

export {RestrictedReadOnlyContextMenuActions};
export default ContextMenuActions;
export type {ContextMenuActionPayload, ContextMenuAction};
88 changes: 88 additions & 0 deletions src/pages/home/report/OnboardingReportFooterMessage.tsx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose to name this SystemChatReportFooterMessage

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - 9076bc0.

Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, {useMemo} from 'react';
import {withOnyx} from 'react-native-onyx';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import Banner from '@components/Banner';
import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as PolicyUtils from '@libs/PolicyUtils';
import Navigation from '@navigation/Navigation';
import * as ReportInstance from '@userActions/Report';
import type {OnboardingPurposeType} from '@src/CONST';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {Policy as PolicyType, Report} from '@src/types/onyx';

type OnboardingReportFooterMessageOnyxProps = {
/** Saved onboarding purpose selected by the user */
choice: OnyxEntry<OnboardingPurposeType>;

/** Collection of reports */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which reports? All users reports?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the app is looking for an admin chat to show in the banner.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is another way: to the active policyID by nvp_expensify_activePolicyID and find an admin chat. Let me try.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about this approach - 90a72e9?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a problem when the user creates a new account, the active policy does not exist yet.

Copy link
Contributor Author

@rezkiy37 rezkiy37 Apr 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - 907167c, 38cbb1b.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test.mp4

reports: OnyxCollection<Report>;

/** The list of this user's policies */
policies: OnyxCollection<PolicyType>;
};

type OnboardingReportFooterMessageProps = OnboardingReportFooterMessageOnyxProps;
rezkiy37 marked this conversation as resolved.
Show resolved Hide resolved

function OnboardingReportFooterMessage({choice, reports, policies}: OnboardingReportFooterMessageProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();

const adminChatReport = useMemo(() => {
const adminsReports = Object.values(reports ?? {}).filter((report) => report?.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS);
const activePolicies = Object.values(policies ?? {}).filter((policy) => PolicyUtils.shouldShowPolicy(policy, false));

return adminsReports.find((report) => activePolicies.find((policy) => policy?.id === report?.policyID));
}, [policies, reports]);

const content = useMemo(() => {
switch (choice) {
case CONST.ONBOARDING_CHOICES.MANAGE_TEAM:
return (
<>
{translate('onboardingBottomMessage.newDotManageTeam.phrase1')}
<TextLink onPress={() => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(adminChatReport?.reportID ?? ''))}>
{adminChatReport?.reportName ?? CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}
</TextLink>
{translate('onboardingBottomMessage.newDotManageTeam.phrase2')}
</>
);
default:
return (
<>
{translate('onboardingBottomMessage.default.phrase1')}
<TextLink onPress={() => ReportInstance.navigateToConciergeChat()}>{CONST?.CONCIERGE_CHAT_NAME}</TextLink>
{translate('onboardingBottomMessage.default.phrase2')}
</>
);
}
}, [adminChatReport?.reportName, adminChatReport?.reportID, choice, translate]);

return (
<Banner
containerStyles={[styles.archivedReportFooter]}
shouldShowIcon
icon={Expensicons.Lightbulb}
content={<Text suppressHighlighting>{content}</Text>}
/>
);
}

OnboardingReportFooterMessage.displayName = 'OnboardingReportFooterMessage';

export default withOnyx<OnboardingReportFooterMessageProps, OnboardingReportFooterMessageOnyxProps>({
choice: {
key: ONYXKEYS.ONBOARDING_PURPOSE_SELECTED,
},
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
},
policies: {
key: ONYXKEYS.COLLECTION.POLICY,
},
})(OnboardingReportFooterMessage);
2 changes: 2 additions & 0 deletions src/pages/home/report/ReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import type * as OnyxTypes from '@src/types/onyx';
import type {OriginalMessageActionableMentionWhisper, OriginalMessageActionableTrackedExpenseWhisper, OriginalMessageJoinPolicyChangeLog} from '@src/types/onyx/OriginalMessage';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import AnimatedEmptyStateBackground from './AnimatedEmptyStateBackground';
import {RestrictedReadOnlyContextMenuActions} from './ContextMenu/ContextMenuActions';
import MiniReportActionContextMenu from './ContextMenu/MiniReportActionContextMenu';
import * as ReportActionContextMenu from './ContextMenu/ReportActionContextMenu';
import {hideContextMenu} from './ContextMenu/ReportActionContextMenu';
Expand Down Expand Up @@ -914,6 +915,7 @@ function ReportActionItem({
originalReportID={originalReportID ?? ''}
isArchivedRoom={ReportUtils.isArchivedRoom(report)}
displayAsGroup={displayAsGroup}
disabledActions={!ReportUtils.canWriteInReport(report) ? RestrictedReadOnlyContextMenuActions : []}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coming from #43562, we also missed adding those disabledActions in the context menu.

isVisible={hovered && draftMessage === undefined && !hasErrors}
draftMessage={draftMessage}
isChronosReport={ReportUtils.chatIncludesChronos(originalReport)}
Expand Down
5 changes: 4 additions & 1 deletion src/pages/home/report/ReportFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type * as OnyxTypes from '@src/types/onyx';
import type {PendingAction} from '@src/types/onyx/OnyxCommon';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import OnboardingReportFooterMessage from './OnboardingReportFooterMessage';
import ReportActionCompose from './ReportActionCompose/ReportActionCompose';

type ReportFooterOnyxProps = {
Expand Down Expand Up @@ -81,6 +82,7 @@ function ReportFooter({

const isSmallSizeLayout = windowWidth - (isSmallScreenWidth ? 0 : variables.sideBarWidth) < variables.anonymousReportFooterBreakpoint;
const hideComposer = !ReportUtils.canUserPerformWriteAction(report);
const canWriteInReport = ReportUtils.canWriteInReport(report);

const allPersonalDetails = usePersonalDetails();

Expand Down Expand Up @@ -131,14 +133,15 @@ function ReportFooter({
return (
<>
{hideComposer && (
<View style={[styles.chatFooter, isArchivedRoom || isAnonymousUser ? styles.mt4 : {}, isSmallScreenWidth ? styles.mb5 : null]}>
<View style={[styles.chatFooter, isArchivedRoom || isAnonymousUser || !canWriteInReport ? styles.mt4 : {}, isSmallScreenWidth ? styles.mb5 : null]}>
{isAnonymousUser && !isArchivedRoom && (
<AnonymousReportFooter
report={report}
isSmallSizeLayout={isSmallSizeLayout}
/>
)}
{isArchivedRoom && <ArchivedReportFooter report={report} />}
{!canWriteInReport && <OnboardingReportFooterMessage />}
{!isSmallScreenWidth && <View style={styles.offlineIndicatorRow}>{hideComposer && <OfflineIndicator containerStyles={[styles.chatItemComposeSecondaryRow]} />}</View>}
</View>
)}
Expand Down
4 changes: 4 additions & 0 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,10 @@ const styles = (theme: ThemeColors) =>
borderRadius: variables.buttonBorderRadius,
},

borderRadiusComponentLarge: {
borderRadius: variables.componentBorderRadiusLarge,
},

bottomTabBarContainer: {
flexDirection: 'row',
height: variables.bottomTabHeight,
Expand Down
2 changes: 2 additions & 0 deletions src/types/onyx/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ type Report = OnyxCommon.OnyxValueWithOfflineFeedback<
transactionThreadReportID?: string;

fieldList?: Record<string, PolicyReportField>;

permissions?: Array<ValueOf<typeof CONST.REPORT.PERMISSIONS>>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a comment here

},
PolicyReportField['fieldID']
>;
Expand Down
Loading