Skip to content

Commit

Permalink
Merge pull request #34646 from kubabutkiewicz/ts-migration/ReportActi…
Browse files Browse the repository at this point in the history
…onCompose

[TS migration] Migrate 'ReportActionCompose' component to TypeScript
  • Loading branch information
luacmartins authored Feb 28, 2024
2 parents 1d17193 + 64368d5 commit fc828da
Show file tree
Hide file tree
Showing 38 changed files with 834 additions and 977 deletions.
8 changes: 4 additions & 4 deletions src/components/AttachmentModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ type AttachmentModalProps = AttachmentModalOnyxProps & {
source?: AvatarSource;

/** Optional callback to fire when we want to preview an image and approve it for use. */
onConfirm?: ((file: Partial<FileObject>) => void) | null;
onConfirm?: ((file: FileObject) => void) | null;

/** Whether the modal should be open by default */
defaultOpen?: boolean;
Expand Down Expand Up @@ -264,7 +264,7 @@ function AttachmentModal({
}

if (onConfirm) {
onConfirm(Object.assign(file ?? {}, {source: sourceState}));
onConfirm(Object.assign(file ?? {}, {source: sourceState} as FileObject));
}

setIsModalOpen(false);
Expand Down Expand Up @@ -318,7 +318,7 @@ function AttachmentModal({

const validateAndDisplayFileToUpload = useCallback(
(data: FileObject) => {
if (!isDirectoryCheck(data)) {
if (!data || !isDirectoryCheck(data)) {
return;
}
let fileObject = data;
Expand Down Expand Up @@ -617,4 +617,4 @@ export default withOnyx<AttachmentModalProps, AttachmentModalOnyxProps>({
},
})(memo(AttachmentModal));

export type {Attachment};
export type {Attachment, FileObject};
2 changes: 1 addition & 1 deletion src/components/AvatarWithImagePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ function AvatarWithImagePicker({
setError(null, {});
setIsMenuVisible(false);
setImageData({
uri: image.uri,
uri: image.uri ?? '',
name: image.name,
type: image.type,
});
Expand Down
3 changes: 2 additions & 1 deletion src/components/Composer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function Composer(
shouldContainScroll = false,
...props
}: ComposerProps,
ref: ForwardedRef<TextInput>,
ref: ForwardedRef<TextInput | HTMLInputElement>,
) {
const theme = useTheme();
const styles = useThemeStyles();
Expand Down Expand Up @@ -278,6 +278,7 @@ function Composer(
if (!onKeyPress || isEnterWhileComposition(e as unknown as KeyboardEvent)) {
return;
}

onKeyPress(e);
},
[onKeyPress],
Expand Down
12 changes: 3 additions & 9 deletions src/components/Composer/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type {NativeSyntheticEvent, StyleProp, TextInputFocusEventData, TextInputKeyPressEventData, TextInputSelectionChangeEventData, TextStyle} from 'react-native';
import type {NativeSyntheticEvent, StyleProp, TextInputProps, TextInputSelectionChangeEventData, TextStyle} from 'react-native';

type TextSelection = {
start: number;
end?: number;
};

type ComposerProps = {
type ComposerProps = TextInputProps & {
/** identify id in the text input */
id?: string;

Expand All @@ -31,7 +31,7 @@ type ComposerProps = {
onNumberOfLinesChange?: (numberOfLines: number) => void;

/** Callback method to handle pasting a file */
onPasteFile?: (file?: File) => void;
onPasteFile?: (file: File) => void;

/** General styles to apply to the text input */
// eslint-disable-next-line react/forbid-prop-types
Expand Down Expand Up @@ -74,12 +74,6 @@ type ComposerProps = {
/** Whether the sull composer is open */
isComposerFullSize?: boolean;

onKeyPress?: (event: NativeSyntheticEvent<TextInputKeyPressEventData>) => void;

onFocus?: (event: NativeSyntheticEvent<TextInputFocusEventData>) => void;

onBlur?: (event: NativeSyntheticEvent<TextInputFocusEventData>) => void;

/** Should make the input only scroll inside the element avoid scroll out to parent */
shouldContainScroll?: boolean;
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/LocaleContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,4 @@ Provider.displayName = 'withOnyx(LocaleContextProvider)';

export {Provider as LocaleContextProvider, LocaleContext};

export type {LocaleContextProps};
export type {LocaleContextProps, Locale};
9 changes: 6 additions & 3 deletions src/components/MentionSuggestions.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, {useCallback} from 'react';
import type {MeasureInWindowOnSuccessCallback} from 'react-native';
import {View} from 'react-native';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
Expand All @@ -18,7 +19,7 @@ type Mention = {
alternateText: string;

/** Email/phone number of the user */
login: string;
login?: string;

/** Array of icons of the user. We use the first element of this array */
icons: Icon[];
Expand All @@ -32,7 +33,7 @@ type MentionSuggestionsProps = {
mentions: Mention[];

/** Fired when the user selects a mention */
onSelect: () => void;
onSelect: (highlightedMentionIndex: number) => void;

/** Mention prefix that follows the @ sign */
prefix: string;
Expand All @@ -43,7 +44,7 @@ type MentionSuggestionsProps = {
isMentionPickerLarge: boolean;

/** Measures the parent container's position and dimensions. */
measureParentContainer: () => void;
measureParentContainer: (callback: MeasureInWindowOnSuccessCallback) => void;
};

/**
Expand Down Expand Up @@ -142,3 +143,5 @@ function MentionSuggestions({prefix, mentions, highlightedMentionIndex = 0, onSe
MentionSuggestions.displayName = 'MentionSuggestions';

export default MentionSuggestions;

export type {Mention};
4 changes: 3 additions & 1 deletion src/libs/API/parameters/AddCommentOrAttachementParams.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type {FileObject} from '@components/AttachmentModal';

type AddCommentOrAttachementParams = {
reportID: string;
reportActionID?: string;
commentReportActionID?: string | null;
reportComment?: string;
file?: File;
file?: FileObject;
timezone?: string;
shouldAllowActionableMentionWhispers?: boolean;
clientCreatedTime?: string;
Expand Down
2 changes: 1 addition & 1 deletion src/libs/DateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ function formatToLongDateWithWeekday(datetime: string | Date): string {
*
* @returns Sunday
*/
function formatToDayOfWeek(datetime: string): string {
function formatToDayOfWeek(datetime: Date): string {
return format(new Date(datetime), CONST.DATE.WEEKDAY_TIME_FORMAT);
}

Expand Down
4 changes: 2 additions & 2 deletions src/libs/E2E/tests/chatOpeningTest.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type {NativeConfig} from 'react-native-config';
import E2ELogin from '@libs/E2E/actions/e2eLogin';
import waitForAppLoaded from '@libs/E2E/actions/waitForAppLoaded';
import E2EClient from '@libs/E2E/client';
import type {TestConfig} from '@libs/E2E/types';
import getConfigValueOrThrow from '@libs/E2E/utils/getConfigValueOrThrow';
import Navigation from '@libs/Navigation/Navigation';
import Performance from '@libs/Performance';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';

const test = (config: TestConfig) => {
const test = (config: NativeConfig) => {
// check for login (if already logged in the action will simply resolve)
console.debug('[E2E] Logging in for chat opening');

Expand Down
4 changes: 2 additions & 2 deletions src/libs/E2E/tests/reportTypingTest.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type {NativeConfig} from 'react-native-config';
import Config from 'react-native-config';
import E2ELogin from '@libs/E2E/actions/e2eLogin';
import waitForAppLoaded from '@libs/E2E/actions/waitForAppLoaded';
import waitForKeyboard from '@libs/E2E/actions/waitForKeyboard';
import E2EClient from '@libs/E2E/client';
import type {TestConfig} from '@libs/E2E/types';
import getConfigValueOrThrow from '@libs/E2E/utils/getConfigValueOrThrow';
import Navigation from '@libs/Navigation/Navigation';
import Performance from '@libs/Performance';
Expand All @@ -12,7 +12,7 @@ import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import * as NativeCommands from '../../../../tests/e2e/nativeCommands/NativeCommandsAction';

const test = (config: TestConfig) => {
const test = (config: NativeConfig) => {
// check for login (if already logged in the action will simply resolve)
console.debug('[E2E] Logging in for typing');

Expand Down
2 changes: 1 addition & 1 deletion src/libs/E2E/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type NetworkCacheMap = Record<

type TestConfig = {
name: string;
[key: string]: string;
[key: string]: string | {autoFocus: boolean};
};

export type {SigninParams, IsE2ETestSession, NetworkCacheMap, NetworkCacheEntry, TestConfig};
3 changes: 1 addition & 2 deletions src/libs/EmojiUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type {FrequentlyUsedEmoji, Locale} from '@src/types/onyx';
import type {ReportActionReaction, UsersReactions} from '@src/types/onyx/ReportActionReactions';
import type IconAsset from '@src/types/utils/IconAsset';
import type {SupportedLanguage} from './EmojiTrie';

type HeaderIndice = {code: string; index: number; icon: IconAsset};
type EmojiSpacer = {code: string; spacer: boolean};
Expand Down Expand Up @@ -384,7 +383,7 @@ function replaceAndExtractEmojis(text: string, preferredSkinTone: number = CONST
* Suggest emojis when typing emojis prefix after colon
* @param [limit] - matching emojis limit
*/
function suggestEmojis(text: string, lang: SupportedLanguage, limit: number = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS): Emoji[] | undefined {
function suggestEmojis(text: string, lang: Locale, limit: number = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS): Emoji[] | undefined {
// emojisTrie is importing the emoji JSON file on the app starting and we want to avoid it
const emojisTrie = require('./EmojiTrie').default;

Expand Down
5 changes: 3 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import lodashIsEqual from 'lodash/isEqual';
import type {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import type {FileObject} from '@components/AttachmentModal';
import * as Expensicons from '@components/Icon/Expensicons';
import * as defaultWorkspaceAvatars from '@components/Icon/WorkspaceDefaultAvatars';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -1323,7 +1324,7 @@ function getRoomWelcomeMessage(report: OnyxEntry<Report>, isUserPolicyAdmin: boo
/**
* Returns true if Concierge is one of the chat participants (1:1 as well as group chats)
*/
function chatIncludesConcierge(report: OnyxEntry<Report>): boolean {
function chatIncludesConcierge(report: Partial<OnyxEntry<Report>>): boolean {
return Boolean(report?.participantAccountIDs?.length && report?.participantAccountIDs?.includes(CONST.ACCOUNT_ID.CONCIERGE));
}

Expand Down Expand Up @@ -2698,7 +2699,7 @@ function getPolicyDescriptionText(policy: Policy): string {
return parser.htmlToText(policy.description);
}

function buildOptimisticAddCommentReportAction(text?: string, file?: File, actorAccountID?: number): OptimisticReportAction {
function buildOptimisticAddCommentReportAction(text?: string, file?: FileObject, actorAccountID?: number): OptimisticReportAction {
const parser = new ExpensiMark();
const commentText = getParsedComment(text ?? '');
const isAttachment = !text && file !== undefined;
Expand Down
2 changes: 1 addition & 1 deletion src/libs/actions/EmojiPickerAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function showEmojiPicker(
/**
* Hide the Emoji Picker modal.
*/
function hideEmojiPicker(isNavigating: boolean) {
function hideEmojiPicker(isNavigating?: boolean) {
if (!emojiPickerRef.current) {
return;
}
Expand Down
5 changes: 3 additions & 2 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {NullishDeep, OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-nat
import Onyx from 'react-native-onyx';
import type {PartialDeep, ValueOf} from 'type-fest';
import type {Emoji} from '@assets/emojis/types';
import type {FileObject} from '@components/AttachmentModal';
import * as ActiveClientManager from '@libs/ActiveClientManager';
import * as API from '@libs/API';
import type {
Expand Down Expand Up @@ -355,7 +356,7 @@ function notifyNewAction(reportID: string, accountID?: number, reportActionID?:
* - Adding one attachment
* - Add both a comment and attachment simultaneously
*/
function addActions(reportID: string, text = '', file?: File) {
function addActions(reportID: string, text = '', file?: FileObject) {
let reportCommentText = '';
let reportCommentAction: OptimisticAddCommentReportAction | undefined;
let attachmentAction: OptimisticAddCommentReportAction | undefined;
Expand Down Expand Up @@ -514,7 +515,7 @@ function addActions(reportID: string, text = '', file?: File) {
}

/** Add an attachment and optional comment. */
function addAttachment(reportID: string, file: File, text = '') {
function addAttachment(reportID: string, file: FileObject, text = '') {
addActions(reportID, text, file);
}

Expand Down
6 changes: 2 additions & 4 deletions src/libs/actions/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import playSoundExcludingMobile from '@libs/Sound/playSoundExcludingMobile';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {FrequentlyUsedEmoji} from '@src/types/onyx';
import type {BlockedFromConcierge, FrequentlyUsedEmoji} from '@src/types/onyx';
import type Login from '@src/types/onyx/Login';
import type {OnyxServerUpdate} from '@src/types/onyx/OnyxUpdatesFromServer';
import type OnyxPersonalDetails from '@src/types/onyx/PersonalDetails';
Expand All @@ -47,8 +47,6 @@ import * as OnyxUpdates from './OnyxUpdates';
import * as Report from './Report';
import * as Session from './Session';

type BlockedFromConciergeNVP = {expiresAt: number};

let currentUserAccountID = -1;
let currentEmail = '';
Onyx.connect({
Expand Down Expand Up @@ -447,7 +445,7 @@ function validateSecondaryLogin(contactMethod: string, validateCode: string) {
* and if so whether the expiresAt date of a user's ban is before right now
*
*/
function isBlockedFromConcierge(blockedFromConciergeNVP: OnyxEntry<BlockedFromConciergeNVP>): boolean {
function isBlockedFromConcierge(blockedFromConciergeNVP: OnyxEntry<BlockedFromConcierge>): boolean {
if (isEmptyObject(blockedFromConciergeNVP)) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import lodashGet from 'lodash/get';
import React, {useEffect, useState} from 'react';
import {View} from 'react-native';
import participantPropTypes from '@components/participantPropTypes';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import DateUtils from '@libs/DateUtils';
import Timers from '@libs/Timers';
import type {Locale} from '@src/components/LocaleContextProvider';
import CONST from '@src/CONST';
import type {PersonalDetails} from '@src/types/onyx';

const propTypes = {
type ParticipantLocalTimeProps = {
/** Personal details of the participant */
participant: participantPropTypes.isRequired,

...withLocalizePropTypes,
participant: PersonalDetails;
};

function getParticipantLocalTime(participant, preferredLocale) {
const reportRecipientTimezone = lodashGet(participant, 'timezone', CONST.DEFAULT_TIME_ZONE);
const reportTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale, null, reportRecipientTimezone.selected);
function getParticipantLocalTime(participant: PersonalDetails, preferredLocale: Locale) {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null
const reportRecipientTimezone = participant.timezone || CONST.DEFAULT_TIME_ZONE;
const reportTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale, undefined, reportRecipientTimezone.selected);
const currentTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale);
const reportRecipientDay = DateUtils.formatToDayOfWeek(reportTimezone);
const currentUserDay = DateUtils.formatToDayOfWeek(currentTimezone);
Expand All @@ -28,9 +27,9 @@ function getParticipantLocalTime(participant, preferredLocale) {
return `${DateUtils.formatToLocalTime(reportTimezone)}`;
}

function ParticipantLocalTime(props) {
function ParticipantLocalTime({participant}: ParticipantLocalTimeProps) {
const {translate, preferredLocale} = useLocalize();
const styles = useThemeStyles();
const {participant, preferredLocale, translate} = props;

const [localTime, setLocalTime] = useState(() => getParticipantLocalTime(participant, preferredLocale));
useEffect(() => {
Expand All @@ -44,7 +43,8 @@ function ParticipantLocalTime(props) {
};
}, [participant, preferredLocale]);

const reportRecipientDisplayName = lodashGet(props, 'participant.firstName') || lodashGet(props, 'participant.displayName');
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null
const reportRecipientDisplayName = participant.firstName || participant.displayName;

if (!reportRecipientDisplayName) {
return null;
Expand All @@ -65,7 +65,6 @@ function ParticipantLocalTime(props) {
);
}

ParticipantLocalTime.propTypes = propTypes;
ParticipantLocalTime.displayName = 'ParticipantLocalTime';

export default withLocalize(ParticipantLocalTime);
export default ParticipantLocalTime;
Loading

0 comments on commit fc828da

Please sign in to comment.