Skip to content

Commit

Permalink
Merge pull request #38722 from rayane-djouah/Feat-Redesign-thread-anc…
Browse files Browse the repository at this point in the history
…estry

[HIGH] Feat: Redesign thread ancestry
  • Loading branch information
chiragsalian authored Mar 28, 2024
2 parents d6fc25a + 311399a commit 903fe8a
Show file tree
Hide file tree
Showing 18 changed files with 143 additions and 45 deletions.
3 changes: 3 additions & 0 deletions assets/images/thread.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/components/AvatarWithDisplayName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ function AvatarWithDisplayName({
<ParentNavigationSubtitle
parentNavigationSubtitleData={parentNavigationSubtitleData}
parentReportID={report?.parentReportID}
parentReportActionID={report?.parentReportActionID}
pressableStyles={[styles.alignSelfStart, styles.mw100]}
/>
)}
Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Expensicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ import Sync from '@assets/images/sync.svg';
import Tag from '@assets/images/tag.svg';
import Task from '@assets/images/task.svg';
import Tax from '@assets/images/tax.svg';
import Thread from '@assets/images/thread.svg';
import ThreeDots from '@assets/images/three-dots.svg';
import ThumbsUp from '@assets/images/thumbs-up.svg';
import Transfer from '@assets/images/transfer.svg';
Expand Down Expand Up @@ -230,6 +231,7 @@ export {
Folder,
Tag,
Tax,
Thread,
Gallery,
Gear,
Globe,
Expand Down
7 changes: 5 additions & 2 deletions src/components/ParentNavigationSubtitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ type ParentNavigationSubtitleProps = {
/** parent Report ID */
parentReportID?: string;

/** parent Report Action ID */
parentReportActionID?: string;

/** PressableWithoutFeedack additional styles */
pressableStyles?: StyleProp<ViewStyle>;
};

function ParentNavigationSubtitle({parentNavigationSubtitleData, parentReportID = '', pressableStyles}: ParentNavigationSubtitleProps) {
function ParentNavigationSubtitle({parentNavigationSubtitleData, parentReportActionID, parentReportID = '', pressableStyles}: ParentNavigationSubtitleProps) {
const styles = useThemeStyles();
const {workspaceName, reportName} = parentNavigationSubtitleData;

Expand All @@ -28,7 +31,7 @@ function ParentNavigationSubtitle({parentNavigationSubtitleData, parentReportID
return (
<PressableWithoutFeedback
onPress={() => {
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(parentReportID));
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(parentReportID, parentReportActionID));
}}
accessibilityLabel={translate('threads.parentNavigationSummary', {reportName, workspaceName})}
role={CONST.ROLE.LINK}
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2408,6 +2408,7 @@ export default {
hiddenMessage: '[Hidden message]',
},
threads: {
thread: 'Thread',
replies: 'Replies',
reply: 'Reply',
from: 'From',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2900,6 +2900,7 @@ export default {
hiddenMessage: '[Mensaje oculto]',
},
threads: {
thread: 'Hilo',
replies: 'Respuestas',
reply: 'Respuesta',
from: 'De',
Expand Down
7 changes: 1 addition & 6 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,6 @@ type Ancestor = {
report: Report;
reportAction: ReportAction;
shouldDisplayNewMarker: boolean;
shouldHideThreadDividerLine: boolean;
};

type AncestorIDs = {
Expand Down Expand Up @@ -5349,7 +5348,7 @@ function shouldDisableThread(reportAction: OnyxEntry<ReportAction>, reportID: st
);
}

function getAllAncestorReportActions(report: Report | null | undefined, shouldHideThreadDividerLine: boolean): Ancestor[] {
function getAllAncestorReportActions(report: Report | null | undefined): Ancestor[] {
if (!report) {
return [];
}
Expand All @@ -5359,7 +5358,6 @@ function getAllAncestorReportActions(report: Report | null | undefined, shouldHi

// Store the child of parent report
let currentReport = report;
let currentUnread = shouldHideThreadDividerLine;

while (parentReportID) {
const parentReport = getReport(parentReportID);
Expand All @@ -5374,14 +5372,11 @@ function getAllAncestorReportActions(report: Report | null | undefined, shouldHi
report: currentReport,
reportAction: parentReportAction,
shouldDisplayNewMarker: isParentReportActionUnread,
// We should hide the thread divider line if the previous ancestor action is unread
shouldHideThreadDividerLine: currentUnread,
});
parentReportID = parentReport?.parentReportID;
parentReportActionID = parentReport?.parentReportActionID;
if (!isEmptyObject(parentReport)) {
currentReport = parentReport;
currentUnread = isParentReportActionUnread;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/pages/ReportDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
<ParentNavigationSubtitle
parentNavigationSubtitleData={parentNavigationSubtitleData}
parentReportID={report?.parentReportID}
parentReportActionID={report?.parentReportActionID}
pressableStyles={[styles.mt1, styles.mw100]}
/>
)}
Expand Down
1 change: 1 addition & 0 deletions src/pages/home/HeaderView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ function HeaderView({report, personalDetails, parentReport, parentReportAction,
<ParentNavigationSubtitle
parentNavigationSubtitleData={parentNavigationSubtitleData}
parentReportID={report.parentReportID}
parentReportActionID={report.parentReportActionID}
pressableStyles={[styles.alignSelfStart, styles.mw100]}
/>
)}
Expand Down
36 changes: 36 additions & 0 deletions src/pages/home/report/RepliesDivider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import {View} from 'react-native';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';

type RepliesDividerProps = {
/** Whether we should hide thread divider line */
shouldHideThreadDividerLine: boolean;
};

function RepliesDivider({shouldHideThreadDividerLine}: RepliesDividerProps) {
const styles = useThemeStyles();
const theme = useTheme();
const {translate} = useLocalize();

return (
<View style={[styles.flexRow, styles.alignItemsCenter, styles.ml5, styles.mt3, styles.mb1]}>
<Icon
src={Expensicons.Thread}
fill={theme.icon}
width={variables.iconSizeExtraSmall}
height={variables.iconSizeExtraSmall}
/>
<Text style={[styles.threadDividerText, styles.textSupporting, styles.ml1]}>{translate('threads.replies')}</Text>
{!shouldHideThreadDividerLine && <View style={[styles.threadDividerLine]} />}
</View>
);
}

RepliesDivider.displayName = 'RepliesDivider';
export default RepliesDivider;
2 changes: 1 addition & 1 deletion src/pages/home/report/ReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ function ReportActionItem({
checkIfContextMenuActive={toggleContextMenuFromActiveReportAction}
setIsEmojiPickerActive={setIsEmojiPickerActive}
/>
<View style={StyleUtils.getReportActionItemStyle(hovered || isWhisper || isContextMenuActive || !!isEmojiPickerActive || draftMessage !== undefined)}>
<View style={StyleUtils.getReportActionItemStyle(hovered || isWhisper || isContextMenuActive || !!isEmojiPickerActive || draftMessage !== undefined, !!onPress)}>
<OfflineWithFeedback
onClose={() => ReportActions.clearAllRelatedReportActionErrors(report.reportID, action)}
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
Expand Down
16 changes: 11 additions & 5 deletions src/pages/home/report/ReportActionItemParentAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import AnimatedEmptyStateBackground from './AnimatedEmptyStateBackground';
import RepliesDivider from './RepliesDivider';
import ReportActionItem from './ReportActionItem';
import ThreadDivider from './ThreadDivider';

type ReportActionItemParentActionProps = {
/** Flag to show, hide the thread divider line */
Expand All @@ -31,9 +33,12 @@ type ReportActionItemParentActionProps = {

/** Report actions belonging to the report's parent */
parentReportAction: OnyxEntry<OnyxTypes.ReportAction>;

/** Whether we should display "Replies" divider */
shouldDisplayReplyDivider: boolean;
};

function ReportActionItemParentAction({report, parentReportAction, index = 0, shouldHideThreadDividerLine = false}: ReportActionItemParentActionProps) {
function ReportActionItemParentAction({report, parentReportAction, index = 0, shouldHideThreadDividerLine = false, shouldDisplayReplyDivider}: ReportActionItemParentActionProps) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {isSmallScreenWidth} = useWindowDimensions();
Expand All @@ -48,15 +53,15 @@ function ReportActionItemParentAction({report, parentReportAction, index = 0, sh
onyxSubscribe({
key: `${ONYXKEYS.COLLECTION.REPORT}${ancestorReportID}`,
callback: () => {
setAllAncestors(ReportUtils.getAllAncestorReportActions(report, shouldHideThreadDividerLine));
setAllAncestors(ReportUtils.getAllAncestorReportActions(report));
},
}),
);
unsubscribeReportActions.push(
onyxSubscribe({
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${ancestorReportID}`,
callback: () => {
setAllAncestors(ReportUtils.getAllAncestorReportActions(report, shouldHideThreadDividerLine));
setAllAncestors(ReportUtils.getAllAncestorReportActions(report));
},
}),
);
Expand All @@ -82,8 +87,9 @@ function ReportActionItemParentAction({report, parentReportAction, index = 0, sh
errorRowStyles={[styles.ml10, styles.mr2]}
onClose={() => Report.navigateToConciergeChatAndDeleteReport(ancestor.report.reportID)}
>
<ThreadDivider ancestor={ancestor} />
<ReportActionItem
onPress={() => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(ancestor.report.reportID))}
onPress={() => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(ancestor.report.parentReportID ?? '', ancestor.reportAction.reportActionID))}
parentReportAction={parentReportAction}
report={ancestor.report}
action={ancestor.reportAction}
Expand All @@ -92,9 +98,9 @@ function ReportActionItemParentAction({report, parentReportAction, index = 0, sh
shouldDisplayNewMarker={ancestor.shouldDisplayNewMarker}
index={index}
/>
{!ancestor.shouldHideThreadDividerLine && <View style={[styles.threadDividerLine]} />}
</OfflineWithFeedback>
))}
{shouldDisplayReplyDivider && <RepliesDivider shouldHideThreadDividerLine={shouldHideThreadDividerLine} />}
</View>
);
}
Expand Down
12 changes: 11 additions & 1 deletion src/pages/home/report/ReportActionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,19 @@ function ReportActionsList({
mostRecentIOUReportActionID={mostRecentIOUReportActionID}
shouldHideThreadDividerLine={shouldHideThreadDividerLine}
shouldDisplayNewMarker={shouldDisplayNewMarker(reportAction, index)}
shouldDisplayReplyDivider={sortedReportActions.length > 1}
/>
),
[report, linkedReportActionID, sortedVisibleReportActions, mostRecentIOUReportActionID, shouldHideThreadDividerLine, shouldDisplayNewMarker, parentReportAction],
[
report,
linkedReportActionID,
sortedVisibleReportActions,
sortedReportActions.length,
mostRecentIOUReportActionID,
shouldHideThreadDividerLine,
shouldDisplayNewMarker,
parentReportAction,
],
);

// Native mobile does not render updates flatlist the changes even though component did update called.
Expand Down
5 changes: 5 additions & 0 deletions src/pages/home/report/ReportActionsListItemRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type ReportActionsListItemRendererProps = {

/** Linked report action ID */
linkedReportActionID?: string;

/** Whether we should display "Replies" divider */
shouldDisplayReplyDivider: boolean;
};

function ReportActionsListItemRenderer({
Expand All @@ -46,6 +49,7 @@ function ReportActionsListItemRenderer({
shouldHideThreadDividerLine,
shouldDisplayNewMarker,
linkedReportActionID = '',
shouldDisplayReplyDivider,
}: ReportActionsListItemRendererProps) {
const shouldDisplayParentAction =
reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED && ReportUtils.isChatThread(report) && !ReportActionsUtils.isTransactionThread(parentReportAction);
Expand Down Expand Up @@ -119,6 +123,7 @@ function ReportActionsListItemRenderer({
return shouldDisplayParentAction ? (
<ReportActionItemParentAction
shouldHideThreadDividerLine={shouldDisplayParentAction && shouldHideThreadDividerLine}
shouldDisplayReplyDivider={shouldDisplayReplyDivider}
parentReportAction={parentReportAction}
reportID={report.reportID}
report={report}
Expand Down
48 changes: 48 additions & 0 deletions src/pages/home/report/ThreadDivider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import {View} from 'react-native';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import {PressableWithoutFeedback} from '@components/Pressable';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import type {Ancestor} from '@libs/ReportUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';

type ThreadDividerProps = {
/** Thread ancestor */
ancestor: Ancestor;
};

function ThreadDivider({ancestor}: ThreadDividerProps) {
const styles = useThemeStyles();
const theme = useTheme();
const {translate} = useLocalize();

return (
<View style={[styles.flexRow, styles.alignItemsCenter, styles.ml5, styles.mt3, styles.mb1]}>
<PressableWithoutFeedback
onPress={() => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(ancestor?.report?.parentReportID ?? '', ancestor.reportAction.reportActionID))}
accessibilityLabel={translate('threads.thread')}
role={CONST.ROLE.BUTTON}
style={[styles.flexRow, styles.alignItemsCenter, styles.gap1]}
>
<Icon
src={Expensicons.Thread}
fill={theme.link}
width={variables.iconSizeExtraSmall}
height={variables.iconSizeExtraSmall}
/>
<Text style={[styles.threadDividerText, styles.link]}>{translate('threads.thread')}</Text>
</PressableWithoutFeedback>
{!ancestor.shouldDisplayNewMarker && <View style={[styles.threadDividerLine]} />}
</View>
);
}

ThreadDivider.displayName = 'ThreadDivider';
export default ThreadDivider;
10 changes: 8 additions & 2 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1898,7 +1898,6 @@ const styles = (theme: ThemeColors) =>
fontFamily: FontUtils.fontFamily.platform.EXP_NEUE,
lineHeight: variables.lineHeightXLarge,
maxWidth: '100%',
...cursor.cursorAuto,
...whiteSpace.preWrap,
...wordBreak.breakWord,
},
Expand Down Expand Up @@ -2743,7 +2742,8 @@ const styles = (theme: ThemeColors) =>
height: 1,
backgroundColor: theme.border,
flexGrow: 1,
marginHorizontal: 20,
marginLeft: 8,
marginRight: 20,
},

unreadIndicatorText: {
Expand All @@ -2754,6 +2754,12 @@ const styles = (theme: ThemeColors) =>
textTransform: 'capitalize',
},

threadDividerText: {
fontFamily: FontUtils.fontFamily.platform.EXP_NEUE,
fontSize: variables.fontSizeSmall,
textTransform: 'capitalize',
},

flipUpsideDown: {
transform: `rotate(180deg)`,
},
Expand Down
4 changes: 2 additions & 2 deletions src/styles/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
/**
* Generate the styles for the ReportActionItem wrapper view.
*/
getReportActionItemStyle: (isHovered = false): ViewStyle =>
getReportActionItemStyle: (isHovered = false, isClickable = false): ViewStyle =>
// TODO: Remove this "eslint-disable-next" once the theme switching migration is done and styles are fully typed (GH Issue: https://github.com/Expensify/App/issues/27337)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
({
Expand All @@ -1465,7 +1465,7 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
: // Warning: Setting this to a non-transparent color will cause unread indicator to break on Android
theme.transparent,
opacity: 1,
...styles.cursorInitial,
...(isClickable ? styles.cursorPointer : styles.cursorInitial),
}),

/**
Expand Down
Loading

0 comments on commit 903fe8a

Please sign in to comment.