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

[TS migration] Migrate 'ReportReactionList' component to TypeScript #34549

Merged
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
ec74f83
chore: migrates reactionPropTypes, BaseReactionList and HeaderReactio…
vadymbokatov Jan 15, 2024
0972c81
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Jan 15, 2024
baaa5a5
chore: migrates BasePopoverReactionList and ReactionList to TS
vadymbokatov Jan 16, 2024
28dfadc
Update src/pages/home/report/ReactionList/HeaderReactionList.tsx
vadymbokatov Jan 16, 2024
4bee7c6
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Jan 16, 2024
952c523
chore: renames the types file and fixes its linting errors
vadymbokatov Jan 16, 2024
efe9d72
chore: removes any typed and fixes linting errors on the index file
vadymbokatov Jan 16, 2024
a303a5e
fix: some linting errors and any types
vadymbokatov Jan 16, 2024
006f1f7
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Jan 18, 2024
846f5c8
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Jan 22, 2024
0129e58
chore: converts BasePopoverReactionList to functional component
vadymbokatov Jan 23, 2024
29f41f2
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Jan 23, 2024
85dcf30
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Jan 24, 2024
1954ddc
chore: fixes the linting error regarding the named export
vadymbokatov Jan 24, 2024
ffe26d6
Update src/pages/home/report/ReactionList/PopoverReactionList/index.tsx
vadymbokatov Jan 24, 2024
a1a4f17
Update src/pages/home/report/ReactionList/BaseReactionList.tsx
vadymbokatov Jan 24, 2024
1059ccf
Update src/pages/home/report/ReactionList/BaseReactionList.tsx
vadymbokatov Jan 24, 2024
8765899
Update src/pages/home/report/ReactionList/PopoverReactionList/BasePop…
vadymbokatov Jan 24, 2024
37b6250
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Jan 24, 2024
ffca03e
fix: ref object not getting passed as the second arg
vadymbokatov Jan 24, 2024
32b3695
fix: types naming convention
vadymbokatov Jan 24, 2024
cebd4dc
chore: removes unneeded JSDocs
vadymbokatov Jan 24, 2024
3f82336
chore: makes isVisible prop optional
vadymbokatov Jan 24, 2024
ac5f088
fix: menu ref not getting forwarded and menu not showing up
vadymbokatov Jan 24, 2024
f2e0f53
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Jan 26, 2024
5af50d4
chore: makes hasUserReacted optional with default value
vadymbokatov Jan 26, 2024
ce370cd
chore: removes unneeded JSDocs returns and comments
vadymbokatov Jan 26, 2024
3fa2b09
fix: reuses the AnchorPosition type
vadymbokatov Jan 26, 2024
bceaca2
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Jan 31, 2024
19401b7
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Feb 1, 2024
288a67c
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Feb 2, 2024
ba47730
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Feb 5, 2024
b1b7451
Update src/hooks/useBasePopoverReactionList/index.ts
vadymbokatov Feb 8, 2024
ecccc96
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Feb 8, 2024
e9761c3
fix: adds the missing dependencies in the useEffect
vadymbokatov Feb 8, 2024
a2d1c03
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Feb 13, 2024
1925a11
fix: popover position
vadymbokatov Feb 13, 2024
cd2a45c
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Feb 15, 2024
b083179
chore: adds white space for better readability
vadymbokatov Feb 15, 2024
2bbe9cb
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Feb 19, 2024
2916ba2
Update src/pages/home/report/ReactionList/types.ts
vadymbokatov Feb 19, 2024
5dbe827
chore: removes unnecessary comments
vadymbokatov Feb 19, 2024
e5ded33
chore: removes unnecessary variable
vadymbokatov Feb 19, 2024
e4a843a
chore: removes unnecessary comments
vadymbokatov Feb 20, 2024
9dfd657
Merge branch 'Expensify:main' into 31976-report-reaction-list-migration
vadymbokatov Feb 20, 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
131 changes: 131 additions & 0 deletions src/hooks/useBasePopoverReactionList/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import {useEffect, useRef, useState} from 'react';
import type {SyntheticEvent} from 'react';
import {Dimensions} from 'react-native';
import * as EmojiUtils from '@libs/EmojiUtils';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import type {BasePopoverReactionListHookProps, ReactionListAnchor, ShowReactionList} from './types';

export default function useBasePopoverReactionList({emojiName, emojiReactions, accountID, reportActionID, preferredLocale}: BasePopoverReactionListHookProps) {
vadymbokatov marked this conversation as resolved.
Show resolved Hide resolved
const [isPopoverVisible, setIsPopoverVisible] = useState(false);
const [cursorRelativePosition, setCursorRelativePosition] = useState({horizontal: 0, vertical: 0});
const [popoverAnchorPosition, setPopoverAnchorPosition] = useState({horizontal: 0, vertical: 0});
const reactionListRef = useRef<ReactionListAnchor>(null);

function getReactionInformation() {
const selectedReaction = emojiReactions?.[emojiName];

if (!selectedReaction) {
// If there is no reaction, we return default values
return {
emojiName: '',
reactionCount: 0,
emojiCodes: [],
hasUserReacted: false,
users: [],
};
}

const {emojiCodes, reactionCount, hasUserReacted, userAccountIDs} = EmojiUtils.getEmojiReactionDetails(emojiName, selectedReaction, accountID);

const users = PersonalDetailsUtils.getPersonalDetailsByIDs(userAccountIDs, accountID, true);
return {
emojiName,
emojiCodes,
reactionCount,
hasUserReacted,
users,
};
}

/**
* Get the BasePopoverReactionList anchor position
* We calculate the achor coordinates from measureInWindow async method
*/
function getReactionListMeasuredLocation(): Promise<{x: number; y: number}> {
return new Promise((resolve) => {
const reactionListAnchor = reactionListRef.current;
if (reactionListAnchor && 'measureInWindow' in reactionListAnchor) {
reactionListAnchor.measureInWindow((x, y) => resolve({x, y}));
} else {
// If the anchor is not available or does not have the measureInWindow method, we return 0, 0
vadymbokatov marked this conversation as resolved.
Show resolved Hide resolved
resolve({x: 0, y: 0});
}
});
}

/**
* Show the ReactionList modal popover.
*
* @param event - Object - A press event.
* @param reactionListAnchor - Element - reactionListAnchor
*/
const showReactionList: ShowReactionList = (event, reactionListAnchor) => {
// We get the cursor coordinates and the reactionListAnchor coordinates to calculate the popover position
const nativeEvent = (event as SyntheticEvent<ReactionListAnchor, MouseEvent>)?.nativeEvent || {};
reactionListRef.current = reactionListAnchor;
getReactionListMeasuredLocation().then(({x, y}) => {
setCursorRelativePosition({horizontal: nativeEvent.pageX - x, vertical: nativeEvent.pageY - y});
setPopoverAnchorPosition({
horizontal: nativeEvent.pageX,
vertical: nativeEvent.pageY,
MonilBhavsar marked this conversation as resolved.
Show resolved Hide resolved
});
setIsPopoverVisible(true);
});
};

/**
* Hide the ReactionList modal popover.
*/
function hideReactionList() {
setIsPopoverVisible(false);
}

useEffect(() => {
const dimensionsEventListener = Dimensions.addEventListener('change', () => {
if (!isPopoverVisible) {
// If the popover is not visible, we don't need to update the component
return;
}
getReactionListMeasuredLocation().then(({x, y}) => {
if (!x || !y) {
return;
}
setPopoverAnchorPosition({
horizontal: cursorRelativePosition.horizontal + x,
vertical: cursorRelativePosition.vertical + y,
});
});
});

return () => {
dimensionsEventListener.remove();
};
}, [
isPopoverVisible,
reportActionID,
preferredLocale,
cursorRelativePosition.horizontal,
cursorRelativePosition.vertical,
popoverAnchorPosition.horizontal,
popoverAnchorPosition.vertical,
]);

useEffect(() => {
if (!isPopoverVisible) {
// If the popover is not visible, we don't need to update the component
return;
}

// Hide the list when all reactions are removed
const users = emojiReactions?.[emojiName].users;
vadymbokatov marked this conversation as resolved.
Show resolved Hide resolved
const isEmptyList = users && Object.keys(users).length === 0;

if (!isEmptyList) {
return;
}
vadymbokatov marked this conversation as resolved.
Show resolved Hide resolved

hideReactionList();
});
vadymbokatov marked this conversation as resolved.
Show resolved Hide resolved

return {isPopoverVisible, cursorRelativePosition, popoverAnchorPosition, getReactionInformation, hideReactionList, reactionListRef, showReactionList};
}
60 changes: 60 additions & 0 deletions src/hooks/useBasePopoverReactionList/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type {OnyxEntry} from 'react-native-onyx';
import type {LocaleContextProps} from '@components/LocaleContextProvider';
import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails';
import type {ReactionListAnchor, ReactionListEvent} from '@pages/home/ReportScreenContext';
import type {AnchorPosition} from '@src/styles';
import type {ReportActionReactions} from '@src/types/onyx';

type BasePopoverReactionListOnyxProps = {
/** The reactions for the report action */
emojiReactions: OnyxEntry<ReportActionReactions>;
};

type BasePopoverReactionListProps = {
/** The ID of the report action */
reportActionID: string;

/** The emoji name */
emojiName: string;
};

type BasePopoverReactionListHookProps = BasePopoverReactionListProps & {
/** The reactions for the report action */
emojiReactions: OnyxEntry<ReportActionReactions>;

/** The current user's account ID */
accountID: WithCurrentUserPersonalDetailsProps['currentUserPersonalDetails']['accountID'];

preferredLocale: LocaleContextProps['preferredLocale'];
};

type BasePopoverReactionListPropsWithLocalWithOnyx = WithCurrentUserPersonalDetailsProps & BasePopoverReactionListOnyxProps & BasePopoverReactionListProps;
type BasePopoverReactionListState = {
/** Whether the popover is visible */
isPopoverVisible: boolean;

/** The horizontal and vertical position (relative to the screen) where the popover will display. */
popoverAnchorPosition: AnchorPosition;

/** The horizontal and vertical position (relative to the screen) where the cursor is. */
cursorRelativePosition: AnchorPosition;
};

type ShowReactionList = (event: ReactionListEvent | undefined, reactionListAnchor: ReactionListAnchor) => void;

type InnerReactionListRef = {
showReactionList: ShowReactionList;
hideReactionList: () => void;
isActiveReportAction: (actionID: number | string) => boolean;
};

export type {
BasePopoverReactionListProps,
BasePopoverReactionListHookProps,
BasePopoverReactionListPropsWithLocalWithOnyx,
BasePopoverReactionListState,
BasePopoverReactionListOnyxProps,
ShowReactionList,
ReactionListAnchor,
InnerReactionListRef,
};
4 changes: 2 additions & 2 deletions src/pages/home/ReportScreenContext.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type {RefObject} from 'react';
import type {RefObject, SyntheticEvent} from 'react';
import {createContext} from 'react';
import type {FlatList, GestureResponderEvent, View} from 'react-native';

type ReactionListAnchor = View | HTMLDivElement | null;

type ReactionListEvent = GestureResponderEvent | MouseEvent;
type ReactionListEvent = GestureResponderEvent | MouseEvent | SyntheticEvent<ReactionListAnchor, MouseEvent>;

type ReactionListRef = {
showReactionList: (event: ReactionListEvent | undefined, reactionListAnchor: ReactionListAnchor, emojiName: string, reportActionID: string) => void;
Expand Down
127 changes: 0 additions & 127 deletions src/pages/home/report/ReactionList/BaseReactionList.js

This file was deleted.

Loading
Loading