From 91393c8a5690376904897337a7cd4ec6deb010dc Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Tue, 10 Dec 2024 12:43:23 +0100 Subject: [PATCH 01/19] fix displaying header for group chat --- src/libs/actions/Report.ts | 2 +- src/libs/shouldFetchReport.ts | 5 ++--- src/pages/home/ReportScreen.tsx | 4 ++-- src/pages/home/report/ReportActionsView.tsx | 3 ++- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index a346a71ddb78..2cdb4c2c1400 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -956,7 +956,7 @@ function openReport( value: {[optimisticCreatedAction.reportActionID]: optimisticCreatedAction}, }, { - onyxMethod: Onyx.METHOD.MERGE, + onyxMethod: Onyx.METHOD.SET, key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, value: { isOptimisticReport: true, diff --git a/src/libs/shouldFetchReport.ts b/src/libs/shouldFetchReport.ts index 3a29e95ecfb1..ae0384bf728d 100644 --- a/src/libs/shouldFetchReport.ts +++ b/src/libs/shouldFetchReport.ts @@ -1,9 +1,8 @@ import type {OnyxEntry} from 'react-native-onyx'; import type Report from '@src/types/onyx/Report'; -import * as ReportUtils from './ReportUtils'; +import type ReportMetadata from '@src/types/onyx/ReportMetadata'; -export default function shouldFetchReport(report: OnyxEntry) { - const reportMetadata = ReportUtils.getReportMetadata(report?.reportID); +export default function shouldFetchReport(report: OnyxEntry, reportMetadata: OnyxEntry) { // If the report is optimistic, there's no need to fetch it. The original action should create it. // If there is an error for creating the chat, there's no need to fetch it since it doesn't exist return !reportMetadata?.isOptimisticReport && !report?.errorFields?.createChat; diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 97582f75b7b1..fb82f81af178 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -484,7 +484,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro return; } - if (!shouldFetchReport(report)) { + if (!shouldFetchReport(report, reportMetadata)) { return; } // When creating an optimistic report that already exists, we need to skip openReport @@ -495,7 +495,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro } fetchReport(); - }, [report, fetchReport, reportIDFromRoute, isLoadingApp]); + }, [reportIDFromRoute, isLoadingApp, report, reportMetadata, fetchReport]); const dismissBanner = useCallback(() => { setIsBannerVisible(false); diff --git a/src/pages/home/report/ReportActionsView.tsx b/src/pages/home/report/ReportActionsView.tsx index ee7c929acc7d..07aff453fb0c 100755 --- a/src/pages/home/report/ReportActionsView.tsx +++ b/src/pages/home/report/ReportActionsView.tsx @@ -93,6 +93,7 @@ function ReportActionsView({ ReportActionsUtils.getSortedReportActionsForDisplay(reportActions, ReportUtils.canUserPerformWriteAction(report), true), }); const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID ?? -1}`); + const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report.reportID}`); const prevTransactionThreadReport = usePrevious(transactionThreadReport); const reportActionID = route?.params?.reportActionID; const prevReportActionID = usePrevious(reportActionID); @@ -116,7 +117,7 @@ function ReportActionsView({ const reportID = report.reportID; const isReportFullyVisible = useMemo((): boolean => getIsReportFullyVisible(isFocused), [isFocused]); const openReportIfNecessary = () => { - if (!shouldFetchReport(report)) { + if (!shouldFetchReport(report, reportMetadata)) { return; } From d6674075f134d77e9137a85b8c5f5d31679d771a Mon Sep 17 00:00:00 2001 From: daledah Date: Thu, 12 Dec 2024 11:47:10 +0700 Subject: [PATCH 02/19] fix: show empty search view when search API return error --- src/languages/en.ts | 2 +- src/languages/es.ts | 2 +- src/libs/actions/Search.ts | 22 ++++++++++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 7088d9df8a51..551224805e09 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -4536,7 +4536,7 @@ const translations = { searchResults: { emptyResults: { title: 'Nothing to show', - subtitle: 'Try creating something with the green + button.', + subtitle: 'Try adjusting your search criteria or try creating something with the green + button.', }, emptyExpenseResults: { title: "You haven't created any expenses yet", diff --git a/src/languages/es.ts b/src/languages/es.ts index 47e11bf716ac..40f9370089a1 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -4585,7 +4585,7 @@ const translations = { searchResults: { emptyResults: { title: 'No hay nada que ver aquí', - subtitle: 'Por favor intenta crear algo con el botón verde.', + subtitle: 'Intenta ajustar tus criterios de búsqueda o intenta crear algo con el botón verde.', }, emptyExpenseResults: { title: 'Aún no has creado ningún gasto', diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index c08a83088180..390b7428ee00 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -95,7 +95,7 @@ function getPayActionCallback(hash: number, item: TransactionListItemType | Repo goToItem(); } -function getOnyxLoadingData(hash: number): {optimisticData: OnyxUpdate[]; finallyData: OnyxUpdate[]} { +function getOnyxLoadingData(hash: number, queryJSON?: SearchQueryJSON): {optimisticData: OnyxUpdate[]; finallyData: OnyxUpdate[]; failureData: OnyxUpdate[]} { const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -120,7 +120,21 @@ function getOnyxLoadingData(hash: number): {optimisticData: OnyxUpdate[]; finall }, ]; - return {optimisticData, finallyData}; + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, + value: { + data: [], + search: { + status: queryJSON?.status, + type: queryJSON?.type, + }, + }, + }, + ]; + + return {optimisticData, finallyData, failureData}; } function saveSearch({queryJSON, newName}: {queryJSON: SearchQueryJSON; newName?: string}) { @@ -202,7 +216,7 @@ function deleteSavedSearch(hash: number) { } function search({queryJSON, offset}: {queryJSON: SearchQueryJSON; offset?: number}) { - const {optimisticData, finallyData} = getOnyxLoadingData(queryJSON.hash); + const {optimisticData, finallyData, failureData} = getOnyxLoadingData(queryJSON.hash, queryJSON); const {flatFilters, ...queryJSONWithoutFlatFilters} = queryJSON; const queryWithOffset = { ...queryJSONWithoutFlatFilters, @@ -210,7 +224,7 @@ function search({queryJSON, offset}: {queryJSON: SearchQueryJSON; offset?: numbe }; const jsonQuery = JSON.stringify(queryWithOffset); - API.write(WRITE_COMMANDS.SEARCH, {hash: queryJSON.hash, jsonQuery}, {optimisticData, finallyData}); + API.write(WRITE_COMMANDS.SEARCH, {hash: queryJSON.hash, jsonQuery}, {optimisticData, finallyData, failureData}); } /** From f58d560fe14378927207391702db5d1c5ca67fca Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 13 Dec 2024 15:41:54 +0300 Subject: [PATCH 03/19] added isFocused condition --- src/pages/home/report/ReportActionsList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/home/report/ReportActionsList.tsx b/src/pages/home/report/ReportActionsList.tsx index 3fcdc35ae300..2c1f4dd57750 100644 --- a/src/pages/home/report/ReportActionsList.tsx +++ b/src/pages/home/report/ReportActionsList.tsx @@ -420,7 +420,7 @@ function ReportActionsList({ if (!isFromCurrentUser) { return; } - if (!hasNewestReportActionRef.current) { + if (!hasNewestReportActionRef.current && isFocused) { if (isInNarrowPaneModal) { return; } @@ -429,7 +429,7 @@ function ReportActionsList({ } InteractionManager.runAfterInteractions(() => reportScrollManager.scrollToBottom()); }, - [isInNarrowPaneModal, reportScrollManager, report.reportID], + [isInNarrowPaneModal, reportScrollManager, report.reportID, isFocused], ); useEffect(() => { // Why are we doing this, when in the cleanup of the useEffect we are already calling the unsubscribe function? From 834f32fa7f67fd6d44c79bb0d673acd56e711b00 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 13 Dec 2024 17:14:08 +0300 Subject: [PATCH 04/19] changed condition to isReportScreenTopmostCentralPane --- .../isReportScreenTopmostCentralPane.ts | 17 +++++++++++++++++ src/pages/home/report/ReportActionsList.tsx | 10 ++++------ 2 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 src/libs/Navigation/isReportScreenTopmostCentralPane.ts diff --git a/src/libs/Navigation/isReportScreenTopmostCentralPane.ts b/src/libs/Navigation/isReportScreenTopmostCentralPane.ts new file mode 100644 index 000000000000..6cfc13886a56 --- /dev/null +++ b/src/libs/Navigation/isReportScreenTopmostCentralPane.ts @@ -0,0 +1,17 @@ +import SCREENS from '@src/SCREENS'; +import getTopmostCentralPaneRoute from './getTopmostCentralPaneRoute'; +import {navigationRef} from './Navigation'; +import type {RootStackParamList, State} from './types'; + +const isReportScreenTopmostCentralPane = (): boolean => { + const rootState = navigationRef.getRootState() as State; + + if (!rootState) { + return false; + } + + const topmostCentralPaneRoute = getTopmostCentralPaneRoute(rootState); + return topmostCentralPaneRoute?.name === SCREENS.REPORT; +}; + +export default isReportScreenTopmostCentralPane; diff --git a/src/pages/home/report/ReportActionsList.tsx b/src/pages/home/report/ReportActionsList.tsx index 2c1f4dd57750..160a1198602b 100644 --- a/src/pages/home/report/ReportActionsList.tsx +++ b/src/pages/home/report/ReportActionsList.tsx @@ -19,6 +19,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import DateUtils from '@libs/DateUtils'; +import isReportScreenTopmostCentralPane from '@libs/Navigation/isReportScreenTopmostCentralPane'; import isSearchTopmostCentralPane from '@libs/Navigation/isSearchTopmostCentralPane'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -417,19 +418,16 @@ function ReportActionsList({ (isFromCurrentUser: boolean) => { // If a new comment is added and it's from the current user scroll to the bottom otherwise leave the user positioned where // they are now in the list. - if (!isFromCurrentUser) { + if (!isFromCurrentUser || !isReportScreenTopmostCentralPane()) { return; } - if (!hasNewestReportActionRef.current && isFocused) { - if (isInNarrowPaneModal) { - return; - } + if (!hasNewestReportActionRef.current) { Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.reportID)); return; } InteractionManager.runAfterInteractions(() => reportScrollManager.scrollToBottom()); }, - [isInNarrowPaneModal, reportScrollManager, report.reportID, isFocused], + [reportScrollManager, report.reportID], ); useEffect(() => { // Why are we doing this, when in the cleanup of the useEffect we are already calling the unsubscribe function? From 557ea1985da86f99e55ddc519e0599d4b1762563 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 13 Dec 2024 17:16:10 +0300 Subject: [PATCH 05/19] minor fix --- src/pages/home/report/ReportActionsList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionsList.tsx b/src/pages/home/report/ReportActionsList.tsx index 160a1198602b..d8771a9085f8 100644 --- a/src/pages/home/report/ReportActionsList.tsx +++ b/src/pages/home/report/ReportActionsList.tsx @@ -158,7 +158,7 @@ function ReportActionsList({ const styles = useThemeStyles(); const {translate} = useLocalize(); const {windowHeight} = useWindowDimensions(); - const {isInNarrowPaneModal, shouldUseNarrowLayout} = useResponsiveLayout(); + const {shouldUseNarrowLayout} = useResponsiveLayout(); const {preferredLocale} = useLocalize(); const {isOffline, lastOfflineAt, lastOnlineAt} = useNetworkWithOfflineStatus(); From b6d86987b43f4937e0a7f394565af023d379b172 Mon Sep 17 00:00:00 2001 From: daledah Date: Thu, 19 Dec 2024 11:27:15 +0700 Subject: [PATCH 06/19] fix: translation --- src/languages/en.ts | 2 +- src/languages/es.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 551224805e09..fc69ae39fe82 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -4536,7 +4536,7 @@ const translations = { searchResults: { emptyResults: { title: 'Nothing to show', - subtitle: 'Try adjusting your search criteria or try creating something with the green + button.', + subtitle: 'Try adjusting your search criteria or creating something with the green + button.', }, emptyExpenseResults: { title: "You haven't created any expenses yet", diff --git a/src/languages/es.ts b/src/languages/es.ts index 40f9370089a1..e046c737419b 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -4585,7 +4585,7 @@ const translations = { searchResults: { emptyResults: { title: 'No hay nada que ver aquí', - subtitle: 'Intenta ajustar tus criterios de búsqueda o intenta crear algo con el botón verde.', + subtitle: 'Intenta ajustar tus criterios de búsqueda o crear algo con el botón verde +.', }, emptyExpenseResults: { title: 'Aún no has creado ningún gasto', From 6462cca41d295f4c2480996d2f020a5ef3a6534e Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Fri, 20 Dec 2024 11:52:25 +0800 Subject: [PATCH 07/19] fix chat isn't scrolled to bottom automatically after paying which makes the export button not fully shown --- src/libs/actions/IOU.ts | 2 +- tests/actions/IOUTest.ts | 72 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 284abf31a896..c8d6fb36f60d 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -6917,7 +6917,6 @@ function getPayMoneyRequestParams( const optimisticChatReport = { ...chatReport, lastReadTime: DateUtils.getDBTime(), - lastVisibleActionCreated: optimisticIOUReportAction.created, hasOutstandingChildRequest: false, iouReportID: null, lastMessageText: ReportActionsUtils.getReportActionText(optimisticIOUReportAction), @@ -6953,6 +6952,7 @@ function getPayMoneyRequestParams( ...iouReport, lastMessageText: ReportActionsUtils.getReportActionText(optimisticIOUReportAction), lastMessageHtml: ReportActionsUtils.getReportActionHtml(optimisticIOUReportAction), + lastVisibleActionCreated: optimisticIOUReportAction.created, hasOutstandingChildRequest: false, statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED, pendingFields: { diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 05a6612e4546..ddccff7ec5df 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -22,6 +22,7 @@ import type {Participant} from '@src/types/onyx/Report'; import {toCollectionDataSet} from '@src/types/utils/CollectionDataSet'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import createRandomPolicy, {createCategoryTaxExpenseRules} from '../utils/collections/policies'; +import createRandomReport from '../utils/collections/reports'; import createRandomTransaction from '../utils/collections/transaction'; import PusherHelper from '../utils/PusherHelper'; import type {MockFetch} from '../utils/TestHelper'; @@ -1915,6 +1916,77 @@ describe('actions/IOU', () => { }); }); + describe('payMoneyRequest', () => { + it('should apply optimistic data correctly', async () => { + // Given an outstanding IOU report + const chatReport = { + ...createRandomReport(0), + lastReadTime: DateUtils.getDBTime(), + lastVisibleActionCreated: DateUtils.getDBTime(), + }; + const iouReport = { + ...createRandomReport(1), + chatType: undefined, + type: CONST.REPORT.TYPE.IOU, + total: 10, + }; + mockFetch?.pause?.(); + + jest.advanceTimersByTime(10); + + // When paying the IOU report + IOU.payMoneyRequest(CONST.IOU.PAYMENT_TYPE.ELSEWHERE, chatReport, iouReport); + + await waitForBatchedUpdates(); + + // Then the optimistic data should be applied correctly + const payReportAction = await new Promise((resolve) => { + const connection = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`, + callback: (reportActions) => { + Onyx.disconnect(connection); + resolve(Object.values(reportActions ?? {}).pop()); + }, + }); + }); + + await new Promise((resolve) => { + const connection = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, + callback: (report) => { + Onyx.disconnect(connection); + expect(report?.lastVisibleActionCreated).toBe(chatReport.lastVisibleActionCreated); + expect(report?.hasOutstandingChildRequest).toBe(false); + expect(report?.iouReportID).toBeUndefined(); + expect(new Date(report?.lastReadTime ?? '').getTime()).toBeGreaterThan(new Date(chatReport?.lastReadTime ?? '').getTime()); + expect(report?.lastMessageText).toBe(ReportActionsUtils.getReportActionText(payReportAction)); + expect(report?.lastMessageHtml).toBe(ReportActionsUtils.getReportActionHtml(payReportAction)); + resolve(); + }, + }); + }); + + await new Promise((resolve) => { + const connection = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, + callback: (report) => { + Onyx.disconnect(connection); + expect(report?.hasOutstandingChildRequest).toBe(false); + expect(report?.statusNum).toBe(CONST.REPORT.STATUS_NUM.REIMBURSED); + expect(report?.lastVisibleActionCreated).toBe(payReportAction?.created); + expect(report?.lastMessageText).toBe(ReportActionsUtils.getReportActionText(payReportAction)); + expect(report?.lastMessageHtml).toBe(ReportActionsUtils.getReportActionHtml(payReportAction)); + expect(report?.pendingFields).toEqual({ + preview: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + reimbursed: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }); + resolve(); + }, + }); + }); + }); + }); + describe('a workspace chat with a cancelled payment', () => { const amount = 10000; const comment = '💸💸💸💸'; From 05e49db8b14d3aa95b3ec9d3485ff18b95a9bbe4 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Fri, 20 Dec 2024 09:03:02 +0100 Subject: [PATCH 08/19] fix lint changed --- src/libs/ReportActionsUtils.ts | 6 +++++- src/libs/actions/Report.ts | 12 +++++++++-- src/pages/home/report/ReportActionsView.tsx | 22 ++++++++++++--------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index dd17adbda338..455a125ad0c3 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -975,7 +975,11 @@ function getMostRecentReportActionLastModified(): string { /** * @returns The report preview action or `null` if one couldn't be found */ -function getReportPreviewAction(chatReportID: string, iouReportID: string): OnyxEntry> { +function getReportPreviewAction(chatReportID: string | undefined, iouReportID: string | undefined): OnyxEntry> { + if (!chatReportID || !iouReportID) { + return; + } + return Object.values(allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID}`] ?? {}).find( (reportAction): reportAction is ReportAction => reportAction && isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW) && getOriginalMessage(reportAction)?.linkedReportID === iouReportID, diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 24d67f3ba4b9..ab924906352e 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -1208,7 +1208,11 @@ function navigateToAndOpenChildReport(childReportID = '-1', parentReportAction: * Gets the older actions that have not been read yet. * Normally happens when you scroll up on a chat, and the actions have not been read yet. */ -function getOlderActions(reportID: string, reportActionID: string) { +function getOlderActions(reportID: string | undefined, reportActionID: string | undefined) { + if (!reportID || !reportActionID) { + return; + } + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -1262,7 +1266,11 @@ function getOlderActions(reportID: string, reportActionID: string) { * Gets the newer actions that have not been read yet. * Normally happens when you are not located at the bottom of the list and scroll down on a chat. */ -function getNewerActions(reportID: string, reportActionID: string) { +function getNewerActions(reportID: string | undefined, reportActionID: string | undefined) { + if (!reportID || !reportActionID) { + return; + } + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, diff --git a/src/pages/home/report/ReportActionsView.tsx b/src/pages/home/report/ReportActionsView.tsx index 750a1ca3aa2b..4b62c0e985fb 100755 --- a/src/pages/home/report/ReportActionsView.tsx +++ b/src/pages/home/report/ReportActionsView.tsx @@ -88,11 +88,11 @@ function ReportActionsView({ const reactionListRef = useContext(ReactionListContext); const route = useRoute>(); const [session] = useOnyx(ONYXKEYS.SESSION); - const [transactionThreadReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID ?? -1}`, { + const [transactionThreadReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID ?? CONST.DEFAULT_NUMBER_ID}`, { selector: (reportActions: OnyxEntry) => ReportActionsUtils.getSortedReportActionsForDisplay(reportActions, ReportUtils.canUserPerformWriteAction(report), true), }); - const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID ?? -1}`); + const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID ?? CONST.DEFAULT_NUMBER_ID}`); const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report.reportID}`); const prevTransactionThreadReport = usePrevious(transactionThreadReport); const reportActionID = route?.params?.reportActionID; @@ -168,7 +168,7 @@ function ReportActionsView({ actions.push(optimisticCreatedAction); } - const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(report.chatReportID ?? '', report.reportID); + const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(report.chatReportID, report.reportID); const moneyRequestActions = allReportActions.filter((action) => { const originalMessage = ReportActionsUtils.isMoneyRequestAction(action) ? ReportActionsUtils.getOriginalMessage(action) : undefined; return ( @@ -284,11 +284,11 @@ function ReportActionsView({ if (!isEmptyObject(transactionThreadReport)) { // Get newer actions based on the newest reportAction for the current report const newestActionCurrentReport = reportActionIDMap.find((item) => item.reportID === reportID); - Report.getNewerActions(newestActionCurrentReport?.reportID ?? '-1', newestActionCurrentReport?.reportActionID ?? '-1'); + Report.getNewerActions(newestActionCurrentReport?.reportID, newestActionCurrentReport?.reportActionID); // Get newer actions based on the newest reportAction for the transaction thread report const newestActionTransactionThreadReport = reportActionIDMap.find((item) => item.reportID === transactionThreadReport.reportID); - Report.getNewerActions(newestActionTransactionThreadReport?.reportID ?? '-1', newestActionTransactionThreadReport?.reportActionID ?? '-1'); + Report.getNewerActions(newestActionTransactionThreadReport?.reportID, newestActionTransactionThreadReport?.reportActionID); } else { Report.getNewerActions(reportID, newestReportAction.reportActionID); } @@ -330,7 +330,11 @@ function ReportActionsView({ }, []); const handleReportActionPagination = useCallback( - ({firstReportActionID}: {firstReportActionID: string}) => { + ({firstReportActionID}: {firstReportActionID: string | undefined}) => { + if (!firstReportActionID) { + return; + } + // This function is a placeholder as the actual pagination is handled by visibleReportActions if (!hasMoreCached && !hasNewestReportAction) { isFirstLinkedActionRender.current = false; @@ -374,11 +378,11 @@ function ReportActionsView({ if (!isEmptyObject(transactionThreadReport)) { // Get older actions based on the oldest reportAction for the current report const oldestActionCurrentReport = reportActionIDMap.findLast((item) => item.reportID === reportID); - Report.getOlderActions(oldestActionCurrentReport?.reportID ?? '-1', oldestActionCurrentReport?.reportActionID ?? '-1'); + Report.getOlderActions(oldestActionCurrentReport?.reportID, oldestActionCurrentReport?.reportActionID); // Get older actions based on the oldest reportAction for the transaction thread report const oldestActionTransactionThreadReport = reportActionIDMap.findLast((item) => item.reportID === transactionThreadReport.reportID); - Report.getOlderActions(oldestActionTransactionThreadReport?.reportID ?? '-1', oldestActionTransactionThreadReport?.reportActionID ?? '-1'); + Report.getOlderActions(oldestActionTransactionThreadReport?.reportID, oldestActionTransactionThreadReport?.reportActionID); } else { // Retrieve the next REPORT.ACTIONS.LIMIT sized page of comments Report.getOlderActions(reportID, oldestReportAction.reportActionID); @@ -416,7 +420,7 @@ function ReportActionsView({ didLoadNewerChats.current = true; if ((reportActionID && indexOfLinkedAction > -1) || !reportActionID) { - handleReportActionPagination({firstReportActionID: newestReportAction?.reportActionID ?? '-1'}); + handleReportActionPagination({firstReportActionID: newestReportAction?.reportActionID}); } }, [ From a074805ce971abe0f4cbe759eab4cf427d6e3ee2 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Fri, 20 Dec 2024 17:28:57 +0800 Subject: [PATCH 09/19] resume the mock fetch --- tests/actions/IOUTest.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index ddccff7ec5df..311e8f121c9e 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -66,6 +66,7 @@ describe('actions/IOU', () => { let mockFetch: MockFetch; beforeEach(() => { + jest.clearAllTimers(); global.fetch = TestHelper.getGlobalFetchMock(); mockFetch = fetch as MockFetch; return Onyx.clear().then(waitForBatchedUpdates); @@ -1984,6 +1985,8 @@ describe('actions/IOU', () => { }, }); }); + + mockFetch?.resume?.(); }); }); From fe1ef3560b760ebb923a049d5f841950fd0512fd Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 20 Dec 2024 14:41:37 +0000 Subject: [PATCH 10/19] useless commit to kick off HybridApp build --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fcc5e2b934e9..455f2f61197d 100644 --- a/README.md +++ b/README.md @@ -500,7 +500,7 @@ It's important to emphasise that a git submodule is just a **regular git reposit > #### For external contributors > > If you'd like to modify the `Mobile-Expensify` source code, it is best that you create your own fork. Then, you can swap origin of the remote repository by executing this command: -> +> > `cd Mobile-Expensify && git remote set-url origin ` > > This way, you'll attach the submodule to your fork repository. From 13652fcfdf4b05380302f8c2b668e5e948cf64c4 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Fri, 20 Dec 2024 14:57:50 +0000 Subject: [PATCH 11/19] Update version to 9.0.77-5 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index cf34cd05f8fd..20e86ae52073 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009007704 - versionName "9.0.77-4" + versionCode 1009007705 + versionName "9.0.77-5" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 108706d79a0c..4b9157afbcae 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -40,7 +40,7 @@ CFBundleVersion - 9.0.77.4 + 9.0.77.5 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index ea782231aaec..3e6cc8920b19 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.77.4 + 9.0.77.5 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index b14e33cdde82..d3bc23571433 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.77 CFBundleVersion - 9.0.77.4 + 9.0.77.5 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 0a2e67f38ee2..9cb175d5897a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.77-4", + "version": "9.0.77-5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.77-4", + "version": "9.0.77-5", "hasInstallScript": true, "license": "MIT", "workspaces": [ diff --git a/package.json b/package.json index c621b583452e..1ff9da459e53 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.77-4", + "version": "9.0.77-5", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 1c3f79afb920144454003cdaa041ce50fba1ebb1 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Fri, 20 Dec 2024 14:58:26 +0000 Subject: [PATCH 12/19] Update Mobile-Expensify to 9.0.77-5 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 43c5ef761b59..1d9a218bff07 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 43c5ef761b59d38a297904c5917c326d86c83fb7 +Subproject commit 1d9a218bff0706bbe75f50045c6d39eba1435f97 From ba6168a214b03d23d4845374b3c338cb86917e95 Mon Sep 17 00:00:00 2001 From: Jules Date: Fri, 20 Dec 2024 15:17:01 +0000 Subject: [PATCH 13/19] Revert "Revert "Revert "Contacts import""" --- .eslintignore | 1 - android/app/proguard-rules.pro | 1 - android/app/src/main/AndroidManifest.xml | 1 - ios/Podfile | 1 - ios/Podfile.lock | 57 +- modules/ContactsNitroModule/.gitignore | 78 -- modules/ContactsNitroModule/.watchmanconfig | 1 - .../ContactsModule.podspec | 29 - .../android/CMakeLists.txt | 29 - .../ContactsNitroModule/android/build.gradle | 130 --- .../android/gradle.properties | 5 - .../android/src/main/AndroidManifest.xml | 2 - .../android/src/main/cpp/cpp-adapter.cpp | 6 - .../nitro/contacts/ContactsModulePackage.java | 34 - .../nitro/contacts/HybridContactsModule.kt | 166 ---- modules/ContactsNitroModule/babel.config.js | 3 - .../ios/HybridContactsModule.swift | 72 -- modules/ContactsNitroModule/nitro.json | 17 - .../android/ContactsModule+autolinking.cmake | 59 -- .../android/ContactsModule+autolinking.gradle | 27 - .../android/ContactsModuleOnLoad.cpp | 42 - .../android/ContactsModuleOnLoad.hpp | 25 - .../generated/android/ContactsModuleOnLoad.kt | 1 - .../generated/android/c++/JContact.hpp | 114 --- .../generated/android/c++/JContactFields.hpp | 76 -- .../android/c++/JHybridContactsModuleSpec.cpp | 84 -- .../android/c++/JHybridContactsModuleSpec.hpp | 62 -- .../generated/android/c++/JStringHolder.hpp | 52 - .../com/margelo/nitro/contacts/Contact.kt | 27 - .../margelo/nitro/contacts/ContactFields.kt | 31 - .../contacts/HybridContactsModuleSpec.kt | 64 -- .../margelo/nitro/contacts/StringHolder.kt | 21 - .../ios/ContactsModule+autolinking.rb | 58 -- .../ios/ContactsModule-Swift-Cxx-Bridge.cpp | 33 - .../ios/ContactsModule-Swift-Cxx-Bridge.hpp | 167 ---- .../ios/ContactsModule-Swift-Cxx-Umbrella.hpp | 54 -- .../ios/ContactsModuleAutolinking.mm | 33 - .../ios/ContactsModuleAutolinking.swift | 26 - .../ios/c++/HybridContactsModuleSpecSwift.cpp | 11 - .../ios/c++/HybridContactsModuleSpecSwift.hpp | 82 -- .../generated/ios/swift/Contact.swift | 251 ----- .../generated/ios/swift/ContactFields.swift | 64 -- .../ios/swift/HybridContactsModuleSpec.swift | 36 - .../swift/HybridContactsModuleSpecCxx.swift | 123 --- .../generated/ios/swift/StringHolder.swift | 35 - .../nitrogen/generated/shared/c++/Contact.hpp | 96 -- .../generated/shared/c++/ContactFields.hpp | 102 -- .../shared/c++/HybridContactsModuleSpec.cpp | 21 - .../shared/c++/HybridContactsModuleSpec.hpp | 68 -- .../generated/shared/c++/StringHolder.hpp | 68 -- modules/ContactsNitroModule/package.json | 103 -- .../src/ContactsModule.nitro.ts | 29 - modules/ContactsNitroModule/src/index.ts | 8 - modules/ContactsNitroModule/tsconfig.json | 29 - package-lock.json | 912 +----------------- package.json | 20 +- react-native.config.js | 7 - src/CONST.ts | 8 - .../ContactPermissionModal/index.native.tsx | 73 -- .../ContactPermissionModal/index.tsx | 10 - .../ContactPermissionModal/types.ts | 19 - src/languages/en.ts | 7 - src/languages/es.ts | 7 - src/libs/ContactImport/index.native.tsx | 32 - src/libs/ContactImport/index.tsx | 11 - src/libs/ContactImport/types.ts | 20 - src/libs/ContactPermission/index.android.ts | 11 - src/libs/ContactPermission/index.ios.ts | 11 - src/libs/ContactPermission/index.ts | 16 - src/libs/ContactUtils.ts | 50 - src/libs/OptionsListUtils.ts | 117 +-- src/libs/RandomAvatarUtils.ts | 99 -- .../MoneyRequestParticipantsSelector.tsx | 184 +--- tsconfig.json | 25 +- 74 files changed, 74 insertions(+), 4380 deletions(-) delete mode 100644 modules/ContactsNitroModule/.gitignore delete mode 100644 modules/ContactsNitroModule/.watchmanconfig delete mode 100644 modules/ContactsNitroModule/ContactsModule.podspec delete mode 100644 modules/ContactsNitroModule/android/CMakeLists.txt delete mode 100644 modules/ContactsNitroModule/android/build.gradle delete mode 100644 modules/ContactsNitroModule/android/gradle.properties delete mode 100644 modules/ContactsNitroModule/android/src/main/AndroidManifest.xml delete mode 100644 modules/ContactsNitroModule/android/src/main/cpp/cpp-adapter.cpp delete mode 100644 modules/ContactsNitroModule/android/src/main/java/com/margelo/nitro/contacts/ContactsModulePackage.java delete mode 100644 modules/ContactsNitroModule/android/src/main/java/com/margelo/nitro/contacts/HybridContactsModule.kt delete mode 100644 modules/ContactsNitroModule/babel.config.js delete mode 100644 modules/ContactsNitroModule/ios/HybridContactsModule.swift delete mode 100644 modules/ContactsNitroModule/nitro.json delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/ContactsModule+autolinking.cmake delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/ContactsModule+autolinking.gradle delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.cpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.kt delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/c++/JContact.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/c++/JContactFields.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/c++/JHybridContactsModuleSpec.cpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/c++/JHybridContactsModuleSpec.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/c++/JStringHolder.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/Contact.kt delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/ContactFields.kt delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/HybridContactsModuleSpec.kt delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/StringHolder.kt delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule+autolinking.rb delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Bridge.cpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Bridge.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Umbrella.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModuleAutolinking.mm delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModuleAutolinking.swift delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/c++/HybridContactsModuleSpecSwift.cpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/c++/HybridContactsModuleSpecSwift.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/swift/Contact.swift delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/swift/ContactFields.swift delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/swift/HybridContactsModuleSpec.swift delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/swift/HybridContactsModuleSpecCxx.swift delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/ios/swift/StringHolder.swift delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/shared/c++/Contact.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/shared/c++/ContactFields.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/shared/c++/HybridContactsModuleSpec.cpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/shared/c++/HybridContactsModuleSpec.hpp delete mode 100644 modules/ContactsNitroModule/nitrogen/generated/shared/c++/StringHolder.hpp delete mode 100644 modules/ContactsNitroModule/package.json delete mode 100644 modules/ContactsNitroModule/src/ContactsModule.nitro.ts delete mode 100644 modules/ContactsNitroModule/src/index.ts delete mode 100644 modules/ContactsNitroModule/tsconfig.json delete mode 100644 src/components/ContactPermissionModal/index.native.tsx delete mode 100644 src/components/ContactPermissionModal/index.tsx delete mode 100644 src/components/ContactPermissionModal/types.ts delete mode 100644 src/libs/ContactImport/index.native.tsx delete mode 100644 src/libs/ContactImport/index.tsx delete mode 100644 src/libs/ContactImport/types.ts delete mode 100644 src/libs/ContactPermission/index.android.ts delete mode 100644 src/libs/ContactPermission/index.ios.ts delete mode 100644 src/libs/ContactPermission/index.ts delete mode 100644 src/libs/ContactUtils.ts delete mode 100644 src/libs/RandomAvatarUtils.ts diff --git a/.eslintignore b/.eslintignore index aa10a3073f4e..26ecb1ae7cc7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -14,4 +14,3 @@ web/gtm.js src/libs/SearchParser/searchParser.js src/libs/SearchParser/autocompleteParser.js help/_scripts/** -modules/** diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro index bef985265d7f..6d6406551cdd 100644 --- a/android/app/proguard-rules.pro +++ b/android/app/proguard-rules.pro @@ -10,7 +10,6 @@ # Add any project specific keep options here: -keep class com.expensify.chat.BuildConfig { *; } -keep class com.facebook.** { *; } --keep class com.margelo.nitro.** { *; } -keep, allowoptimization, allowobfuscation class expo.modules.** { *; } # Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items). diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a859703ae719..142d919a7a18 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,7 +5,6 @@ - diff --git a/ios/Podfile b/ios/Podfile index bdad8a0ec396..41dc5179752d 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -24,7 +24,6 @@ prepare_react_native_project! setup_permissions([ 'Camera', - 'Contacts', 'LocationAccuracy', 'LocationAlways', 'LocationWhenInUse' diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 0389642465da..e9532fc1ae30 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -28,28 +28,6 @@ PODS: - AppAuth/Core - AppLogs (0.1.0) - boost (1.84.0) - - ContactsModule (0.0.1): - - DoubleConversion - - glog - - hermes-engine - - NitroModules - - RCT-Folly (= 2024.01.01.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - DoubleConversion (1.1.6) - EXAV (14.0.7): - ExpoModulesCore @@ -309,29 +287,6 @@ PODS: - nanopb/encode (= 2.30908.0) - nanopb/decode (2.30908.0) - nanopb/encode (2.30908.0) - - NitroModules (0.18.1): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.01.01.00) - - RCTRequired - - RCTTypeSafety - - React-callinvoker - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-jsi - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - Onfido (29.7.2) - onfido-react-native-sdk (10.6.0): - DoubleConversion @@ -2795,7 +2750,6 @@ DEPENDENCIES: - AirshipServiceExtension - AppLogs (from `../node_modules/react-native-app-logs/AppLogsPod`) - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - - ContactsModule (from `../modules/ContactsNitroModule`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - EXAV (from `../node_modules/expo-av/ios`) - EXImageLoader (from `../node_modules/expo-image-loader/ios`) @@ -2811,7 +2765,6 @@ DEPENDENCIES: - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - lottie-react-native (from `../node_modules/lottie-react-native`) - - NitroModules (from `../node_modules/react-native-nitro-modules`) - "onfido-react-native-sdk (from `../node_modules/@onfido/react-native-sdk`)" - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) @@ -2962,8 +2915,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-app-logs/AppLogsPod" boost: :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" - ContactsModule: - :path: "../modules/ContactsNitroModule" DoubleConversion: :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" EXAV: @@ -2995,8 +2946,6 @@ EXTERNAL SOURCES: :tag: hermes-2024-08-15-RNv0.75.1-4b3bf912cc0f705b51b71ce1a5b8bd79b93a451b lottie-react-native: :path: "../node_modules/lottie-react-native" - NitroModules: - :path: "../node_modules/react-native-nitro-modules" onfido-react-native-sdk: :path: "../node_modules/@onfido/react-native-sdk" RCT-Folly: @@ -3211,7 +3160,6 @@ SPEC CHECKSUMS: AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa AppLogs: 3bc4e9b141dbf265b9464409caaa40416a9ee0e0 boost: 26992d1adf73c1c7676360643e687aee6dda994b - ContactsModule: 21671b28654413dc28795d1afc3b12eaffa28ed1 DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 EXAV: afa491e598334bbbb92a92a2f4dd33d7149ad37f EXImageLoader: ab589d67d6c5f2c33572afea9917304418566334 @@ -3251,7 +3199,6 @@ SPEC CHECKSUMS: MapboxMaps: e76b14f52c54c40b76ddecd04f40448e6f35a864 MapboxMobileEvents: de50b3a4de180dd129c326e09cd12c8adaaa46d6 nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 - NitroModules: ebe2ba2d01dc03c1f82441561fe6062b8c3c4366 Onfido: f3af62ea1c9a419589c133e3e511e5d2c4f3f8af onfido-react-native-sdk: 4ccfdeb10f9ccb4a5799d2555cdbc2a068a42c0d Plaid: c32f22ffce5ec67c9e6147eaf6c4d7d5f8086d89 @@ -3348,7 +3295,7 @@ SPEC CHECKSUMS: RNLiveMarkdown: f19d3c962fba4fb87bb9bc27ce9119216d86d92e RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 rnmapbox-maps: 460d6ff97ae49c7d5708c3212c6521697c36a0c4 - RNPermissions: 9e5c26aaa982fe00743281f6f47fbdc050ebc58f + RNPermissions: 0b1429b55af59d1d08b75a8be2459f65a8ac3f28 RNReactNativeHapticFeedback: 73756a3477a5a622fa16862a3ab0d0fc5e5edff5 RNReanimated: d95f865e1e42c34ca56b987e0719a8c72fc02dbc RNScreens: de6e57426ba0e6cbc3fb5b4f496e7f08cb2773c2 @@ -3364,6 +3311,6 @@ SPEC CHECKSUMS: VisionCamera: c95a8ad535f527562be1fb05fb2fd324578e769c Yoga: a1d7895431387402a674fd0d1c04ec85e87909b8 -PODFILE CHECKSUM: e744fa802b4bee097ff8d1977dd8f79d16b21547 +PODFILE CHECKSUM: 615266329434ea4a994dccf622008a2197313c88 COCOAPODS: 1.15.2 diff --git a/modules/ContactsNitroModule/.gitignore b/modules/ContactsNitroModule/.gitignore deleted file mode 100644 index d3b53dfce541..000000000000 --- a/modules/ContactsNitroModule/.gitignore +++ /dev/null @@ -1,78 +0,0 @@ -# OSX -# -.DS_Store - -# XDE -.expo/ - -# VSCode -.vscode/ -jsconfig.json - -# Xcode -# -build/ -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata -*.xccheckout -*.moved-aside -DerivedData -*.hmap -*.ipa -*.xcuserstate -project.xcworkspace - -# Android/IJ -# -.classpath -.cxx -.gradle -.idea -.project -.settings -local.properties -android.iml - -# Cocoapods -# -example/ios/Pods - -# Ruby -example/vendor/ - -# node.js -# -node_modules/ -npm-debug.log -yarn-debug.log -yarn-error.log - -# BUCK -buck-out/ -\.buckd/ -android/app/libs -android/keystores/debug.keystore - -# Yarn -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/releases -!.yarn/sdks -!.yarn/versions - -# Expo -.expo/ - -# Turborepo -.turbo/ - -# generated by bob -lib/ diff --git a/modules/ContactsNitroModule/.watchmanconfig b/modules/ContactsNitroModule/.watchmanconfig deleted file mode 100644 index 0967ef424bce..000000000000 --- a/modules/ContactsNitroModule/.watchmanconfig +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/modules/ContactsNitroModule/ContactsModule.podspec b/modules/ContactsNitroModule/ContactsModule.podspec deleted file mode 100644 index 5f0b012c7b52..000000000000 --- a/modules/ContactsNitroModule/ContactsModule.podspec +++ /dev/null @@ -1,29 +0,0 @@ -require "json" - -package = JSON.parse(File.read(File.join(__dir__, "package.json"))) - -Pod::Spec.new do |s| - s.name = "ContactsModule" - s.version = package["version"] - s.summary = package["description"] - s.homepage = package["homepage"] - s.license = package["license"] - s.authors = package["author"] - - s.platforms = { :ios => min_ios_version_supported } - s.source = { :git => "https://github.com/mrousavy/nitro.git", :tag => "#{s.version}" } - - s.source_files = [ - # Implementation (Swift) - "ios/**/*.{swift}", - # Autolinking/Registration (Objective-C++) - "ios/**/*.{m,mm}", - # Implementation (C++ objects) - "cpp/**/*.{hpp,cpp}", - ] - - load 'nitrogen/generated/ios/ContactsModule+autolinking.rb' - add_nitrogen_files(s) - - install_modules_dependencies(s) -end diff --git a/modules/ContactsNitroModule/android/CMakeLists.txt b/modules/ContactsNitroModule/android/CMakeLists.txt deleted file mode 100644 index beb0c308df07..000000000000 --- a/modules/ContactsNitroModule/android/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -project(ContactsModule) -cmake_minimum_required(VERSION 3.9.0) - -set (PACKAGE_NAME ContactsModule) -set (CMAKE_VERBOSE_MAKEFILE ON) -set (CMAKE_CXX_STANDARD 20) - -# Define C++ library and add all sources -add_library(${PACKAGE_NAME} SHARED - src/main/cpp/cpp-adapter.cpp -) - -# Add Nitrogen specs :) -include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ContactsModule+autolinking.cmake) - -# Set up local includes -include_directories( - "src/main/cpp" - "../cpp" -) - -find_library(LOG_LIB log) - -# Link all libraries together -target_link_libraries( - ${PACKAGE_NAME} - ${LOG_LIB} - android # <-- Android core -) diff --git a/modules/ContactsNitroModule/android/build.gradle b/modules/ContactsNitroModule/android/build.gradle deleted file mode 100644 index 0b414c88dea3..000000000000 --- a/modules/ContactsNitroModule/android/build.gradle +++ /dev/null @@ -1,130 +0,0 @@ -buildscript { - repositories { - google() - mavenCentral() - } - - dependencies { - classpath "com.android.tools.build:gradle:7.2.1" - } -} - -def reactNativeArchitectures() { - def value = rootProject.getProperties().get("reactNativeArchitectures") - return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] -} - -def isNewArchitectureEnabled() { - return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" -} - -apply plugin: "com.android.library" -apply plugin: 'org.jetbrains.kotlin.android' -apply from: '../nitrogen/generated/android/ContactsModule+autolinking.gradle' - -if (isNewArchitectureEnabled()) { - apply plugin: "com.facebook.react" -} - -def getExtOrDefault(name) { - return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["ContactsModule_" + name] -} - -def getExtOrIntegerDefault(name) { - return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ContactsModule_" + name]).toInteger() -} - -android { - namespace "com.margelo.nitro.contacts" - - ndkVersion getExtOrDefault("ndkVersion") - compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") - - defaultConfig { - minSdkVersion getExtOrIntegerDefault("minSdkVersion") - targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") - buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() - - externalNativeBuild { - cmake { - cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all" - arguments "-DANDROID_STL=c++_shared" - abiFilters (*reactNativeArchitectures()) - } - } - } - - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } - - packagingOptions { - excludes = [ - "META-INF", - "META-INF/**", - "**/libc++_shared.so", - "**/libfbjni.so", - "**/libjsi.so", - "**/libfolly_json.so", - "**/libfolly_runtime.so", - "**/libglog.so", - "**/libhermes.so", - "**/libhermes-executor-debug.so", - "**/libhermes_executor.so", - "**/libreactnativejni.so", - "**/libturbomodulejsijni.so", - "**/libreact_nativemodule_core.so", - "**/libjscexecutor.so" - ] - } - - buildFeatures { - buildConfig true - prefab true - } - - buildTypes { - release { - minifyEnabled false - } - } - - lintOptions { - disable "GradleCompatible" - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - sourceSets { - main { - if (isNewArchitectureEnabled()) { - java.srcDirs += [ - // React Codegen files - "${project.buildDir}/generated/source/codegen/java" - ] - } - } - } -} - -repositories { - mavenCentral() - google() -} - - -dependencies { - // For < 0.71, this will be from the local maven repo - // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin - //noinspection GradleDynamicVersion - implementation "com.facebook.react:react-native:+" - - // Add a dependency on NitroModules - implementation project(":react-native-nitro-modules") -} - diff --git a/modules/ContactsNitroModule/android/gradle.properties b/modules/ContactsNitroModule/android/gradle.properties deleted file mode 100644 index 59d3858d1bb9..000000000000 --- a/modules/ContactsNitroModule/android/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -ContactsModule_kotlinVersion=1.9.24 -ContactsModule_minSdkVersion=23 -ContactsModule_targetSdkVersion=34 -ContactsModule_compileSdkVersion=34 -ContactsModule_ndkVersion=26.1.10909125 diff --git a/modules/ContactsNitroModule/android/src/main/AndroidManifest.xml b/modules/ContactsNitroModule/android/src/main/AndroidManifest.xml deleted file mode 100644 index a2f47b6057db..000000000000 --- a/modules/ContactsNitroModule/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/modules/ContactsNitroModule/android/src/main/cpp/cpp-adapter.cpp b/modules/ContactsNitroModule/android/src/main/cpp/cpp-adapter.cpp deleted file mode 100644 index 7a88410f3e4d..000000000000 --- a/modules/ContactsNitroModule/android/src/main/cpp/cpp-adapter.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include "ContactsModuleOnLoad.hpp" - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { - return margelo::nitro::contacts::initialize(vm); -} diff --git a/modules/ContactsNitroModule/android/src/main/java/com/margelo/nitro/contacts/ContactsModulePackage.java b/modules/ContactsNitroModule/android/src/main/java/com/margelo/nitro/contacts/ContactsModulePackage.java deleted file mode 100644 index e8c26844ce86..000000000000 --- a/modules/ContactsNitroModule/android/src/main/java/com/margelo/nitro/contacts/ContactsModulePackage.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.margelo.nitro.contacts; - -import android.util.Log; - -import androidx.annotation.Nullable; - -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.module.model.ReactModuleInfoProvider; -import com.facebook.react.TurboReactPackage; -import com.margelo.nitro.core.HybridObject; -import com.margelo.nitro.core.HybridObjectRegistry; - -import java.util.HashMap; -import java.util.function.Supplier; - -public class ContactsModulePackage extends TurboReactPackage { - @Nullable - @Override - public NativeModule getModule(String name, ReactApplicationContext reactContext) { - return null; - } - - @Override - public ReactModuleInfoProvider getReactModuleInfoProvider() { - return () -> { - return new HashMap<>(); - }; - } - - static { - System.loadLibrary("ContactsModule"); - } -} diff --git a/modules/ContactsNitroModule/android/src/main/java/com/margelo/nitro/contacts/HybridContactsModule.kt b/modules/ContactsNitroModule/android/src/main/java/com/margelo/nitro/contacts/HybridContactsModule.kt deleted file mode 100644 index 00feaa7660c2..000000000000 --- a/modules/ContactsNitroModule/android/src/main/java/com/margelo/nitro/contacts/HybridContactsModule.kt +++ /dev/null @@ -1,166 +0,0 @@ -package com.margelo.nitro.contacts - -import android.Manifest -import android.content.pm.PackageManager -import android.provider.ContactsContract -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat -import com.facebook.react.bridge.ReactApplicationContext -import com.margelo.nitro.NitroModules -import com.margelo.nitro.core.Promise - -class HybridContactsModule : HybridContactsModuleSpec() { - @Volatile - private var estimatedMemorySize: Long = 0 - - override val memorySize: Long - get() = estimatedMemorySize - - private val context: ReactApplicationContext? = NitroModules.applicationContext - - private fun requestContactPermission(): Boolean { - val currentActivity = context?.currentActivity - return if (currentActivity != null) { - ActivityCompat.requestPermissions( - currentActivity, arrayOf(REQUIRED_PERMISSION), PERMISSION_REQUEST_CODE - ) - true - } else { - false - } - } - - private fun hasPhoneContactsPermission(): Boolean { - return context?.let { - ContextCompat.checkSelfPermission(it, Manifest.permission.READ_CONTACTS) - } == PackageManager.PERMISSION_GRANTED - } - - override fun getAll(keys: Array): Promise> { - return Promise.parallel { - val contacts = mutableListOf() - if (!hasPhoneContactsPermission()) { - requestContactPermission() - return@parallel emptyArray() - } - - context?.contentResolver?.let { resolver -> - val projection = arrayOf( - ContactsContract.Data.MIMETYPE, - ContactsContract.Data.CONTACT_ID, - ContactsContract.Data.DISPLAY_NAME, - ContactsContract.Contacts.PHOTO_URI, - ContactsContract.Contacts.PHOTO_THUMBNAIL_URI, - ContactsContract.Data.DATA1, - ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, - ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, - ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME - ) - - val selection = "${ContactsContract.Data.MIMETYPE} IN (?, ?, ?)" - val selectionArgs = arrayOf( - ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, - ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE, - ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE - ) - - val sortOrder = "${ContactsContract.Data.CONTACT_ID} ASC" - - resolver.query( - ContactsContract.Data.CONTENT_URI, - projection, - selection, - selectionArgs, - sortOrder - )?.use { cursor -> - val mimeTypeIndex = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE) - val contactIdIndex = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID) - val photoUriIndex = cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI) - val thumbnailUriIndex = - cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_THUMBNAIL_URI) - val data1Index = cursor.getColumnIndex(ContactsContract.Data.DATA1) - val givenNameIndex = - cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME) - val familyNameIndex = - cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME) - val middleNameIndex = - cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME) - - var currentContact: Contact? = null - var currentContactId: String? = null - val currentPhoneNumbers = mutableListOf() - val currentEmailAddresses = mutableListOf() - - while (cursor.moveToNext()) { - val contactId = cursor.getString(contactIdIndex) - val mimeType = cursor.getString(mimeTypeIndex) - - if (contactId != currentContactId) { - currentContact?.let { contact -> - contacts.add( - contact.copy( - phoneNumbers = currentPhoneNumbers.toTypedArray(), - emailAddresses = currentEmailAddresses.toTypedArray() - ) - ) - } - currentPhoneNumbers.clear() - currentEmailAddresses.clear() - currentContact = Contact( - firstName = "", - lastName = "", - middleName = null, - phoneNumbers = emptyArray(), - emailAddresses = emptyArray(), - imageData = cursor.getString(photoUriIndex) ?: "", - thumbnailImageData = cursor.getString(thumbnailUriIndex) ?: "" - ) - currentContactId = contactId - } - - when (mimeType) { - ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE -> { - currentContact = currentContact?.copy( - firstName = cursor.getString(givenNameIndex) ?: "", - lastName = cursor.getString(familyNameIndex) ?: "", - middleName = cursor.getString(middleNameIndex) - ) - } - - ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE -> { - cursor.getString(data1Index)?.let { phone -> - currentPhoneNumbers.add(StringHolder(phone)) - } - } - - ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE -> { - cursor.getString(data1Index)?.let { email -> - currentEmailAddresses.add(StringHolder(email)) - } - } - } - } - - // Add the last contact - currentContact?.let { contact -> - contacts.add( - contact.copy( - phoneNumbers = currentPhoneNumbers.toTypedArray(), - emailAddresses = currentEmailAddresses.toTypedArray() - ) - ) - } - } - } - - // Update memory size based on contact count - estimatedMemorySize = contacts.size.toLong() * 1024 // Assume ~1KB per contact - contacts.toTypedArray() - } - } - - companion object { - const val PERMISSION_REQUEST_CODE = 1 - const val REQUIRED_PERMISSION = Manifest.permission.READ_CONTACTS - } -} diff --git a/modules/ContactsNitroModule/babel.config.js b/modules/ContactsNitroModule/babel.config.js deleted file mode 100644 index 3e0218e68fc3..000000000000 --- a/modules/ContactsNitroModule/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: ['module:@react-native/babel-preset'], -} diff --git a/modules/ContactsNitroModule/ios/HybridContactsModule.swift b/modules/ContactsNitroModule/ios/HybridContactsModule.swift deleted file mode 100644 index 59cc3ea31702..000000000000 --- a/modules/ContactsNitroModule/ios/HybridContactsModule.swift +++ /dev/null @@ -1,72 +0,0 @@ -import NitroModules -import Contacts -import Foundation - -final class HybridContactsModule: HybridContactsModuleSpec { - public var hybridContext = margelo.nitro.HybridContext() - public var memorySize: Int { MemoryLayout.size } - - private let contactStore = CNContactStore() - private let imageDirectory: URL - private let fieldToKeyDescriptor: [ContactFields: CNKeyDescriptor] = [ - .firstName: CNContactGivenNameKey as CNKeyDescriptor, - .lastName: CNContactFamilyNameKey as CNKeyDescriptor, - .phoneNumbers: CNContactPhoneNumbersKey as CNKeyDescriptor, - .emailAddresses: CNContactEmailAddressesKey as CNKeyDescriptor, - .middleName: CNContactMiddleNameKey as CNKeyDescriptor, - .imageData: CNContactImageDataKey as CNKeyDescriptor, - .thumbnailImageData: CNContactThumbnailImageDataKey as CNKeyDescriptor, - .givenNameKey: CNContactGivenNameKey as CNKeyDescriptor - ] - - init() { - imageDirectory = FileManager.default.temporaryDirectory.appendingPathComponent("ContactImages") - try? FileManager.default.createDirectory(at: imageDirectory, withIntermediateDirectories: true) - } - - func getAll(keys: [ContactFields]) throws -> Promise<[Contact]> { - Promise.async { [unowned self] in - let keysSet = Set(keys) - let keysToFetch = keys.compactMap { self.fieldToKeyDescriptor[$0] } - guard !keysToFetch.isEmpty else { return [] } - - let request = CNContactFetchRequest(keysToFetch: keysToFetch) - var contacts = [Contact]() - contacts.reserveCapacity(1000) - - try self.contactStore.enumerateContacts(with: request) { contact, _ in - contacts.append(self.processContact(contact, keysSet: keysSet)) - } - - return contacts - } - } - - @inline(__always) - private func processContact(_ contact: CNContact, keysSet: Set) -> Contact { - Contact( - firstName: keysSet.contains(.firstName) ? contact.givenName : nil, - lastName: keysSet.contains(.lastName) ? contact.familyName : nil, - middleName: keysSet.contains(.middleName) ? contact.middleName : nil, - phoneNumbers: keysSet.contains(.phoneNumbers) ? contact.phoneNumbers.map { StringHolder(value: $0.value.stringValue) } : nil, - emailAddresses: keysSet.contains(.emailAddresses) ? contact.emailAddresses.map { StringHolder(value: $0.value as String) } : nil, - imageData: keysSet.contains(.imageData) ? getImagePath(for: contact, isThumbnail: false) : nil, - thumbnailImageData: keysSet.contains(.thumbnailImageData) ? getImagePath(for: contact, isThumbnail: true) : nil - ) - } - - @inline(__always) - private func getImagePath(for contact: CNContact, isThumbnail: Bool) -> String? { - let imageData = isThumbnail ? contact.thumbnailImageData : contact.imageData - guard let data = imageData else { return nil } - - let fileName = "\(contact.identifier)_\(isThumbnail ? "thumb" : "full").jpg" - let fileURL = imageDirectory.appendingPathComponent(fileName) - - if !FileManager.default.fileExists(atPath: fileURL.path) { - try? data.write(to: fileURL, options: .atomic) - } - - return fileURL.path - } -} diff --git a/modules/ContactsNitroModule/nitro.json b/modules/ContactsNitroModule/nitro.json deleted file mode 100644 index 426f8486118a..000000000000 --- a/modules/ContactsNitroModule/nitro.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "cxxNamespace": ["contacts"], - "ios": { - "iosModuleName": "ContactsModule" - }, - "android": { - "androidNamespace": ["contacts"], - "androidCxxLibName": "ContactsModule" - }, - "autolinking": { - "ContactsModule": { - "swift": "HybridContactsModule", - "kotlin": "HybridContactsModule" - } - }, - "ignorePaths": ["node_modules"] -} diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModule+autolinking.cmake b/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModule+autolinking.cmake deleted file mode 100644 index 5478bc224b05..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModule+autolinking.cmake +++ /dev/null @@ -1,59 +0,0 @@ -# -# ContactsModule+autolinking.cmake -# This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -# https://github.com/mrousavy/nitro -# Copyright © 2024 Marc Rousavy @ Margelo -# - -# This is a CMake file that adds all files generated by Nitrogen -# to the current CMake project. -# -# To use it, add this to your CMakeLists.txt: -# ```cmake -# include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ContactsModule+autolinking.cmake) -# ``` - -# Add all headers that were generated by Nitrogen -include_directories( - "../nitrogen/generated/shared/c++" - "../nitrogen/generated/android/c++" - "../nitrogen/generated/android/" -) - -# Add all .cpp sources that were generated by Nitrogen -target_sources( - # CMake project name (Android C++ library name) - ContactsModule PRIVATE - # Autolinking Setup - ../nitrogen/generated/android/ContactsModuleOnLoad.cpp - # Shared Nitrogen C++ sources - ../nitrogen/generated/shared/c++/HybridContactsModuleSpec.cpp - # Android-specific Nitrogen C++ sources - ../nitrogen/generated/android/c++/JHybridContactsModuleSpec.cpp -) - -# Add all libraries required by the generated specs -find_package(fbjni REQUIRED) # <-- Used for communication between Java <-> C++ -find_package(ReactAndroid REQUIRED) # <-- Used to set up React Native bindings (e.g. CallInvoker/TurboModule) -find_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library - -# Link all libraries together -target_link_libraries( - ContactsModule - fbjni::fbjni # <-- Facebook C++ JNI helpers - ReactAndroid::jsi # <-- RN: JSI - react-native-nitro-modules::NitroModules # <-- NitroModules Core :) -) - -# Link react-native (different prefab between RN 0.75 and RN 0.76) -if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76) - target_link_libraries( - ContactsModule - ReactAndroid::reactnative # <-- RN: Native Modules umbrella prefab - ) -else() - target_link_libraries( - ContactsModule - ReactAndroid::react_nativemodule_core # <-- RN: TurboModules Core - ) -endif() diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModule+autolinking.gradle b/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModule+autolinking.gradle deleted file mode 100644 index 2d19cd2ced32..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModule+autolinking.gradle +++ /dev/null @@ -1,27 +0,0 @@ -/// -/// ContactsModule+autolinking.gradle -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -/// This is a Gradle file that adds all files generated by Nitrogen -/// to the current Gradle project. -/// -/// To use it, add this to your build.gradle: -/// ```gradle -/// apply from: '../nitrogen/generated/android/ContactsModule+autolinking.gradle' -/// ``` - -logger.warn("[NitroModules] 🔥 ContactsModule is boosted by nitro!") - -android { - sourceSets { - main { - java.srcDirs += [ - // Nitrogen files - "${project.projectDir}/../nitrogen/generated/android/kotlin" - ] - } - } -} diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.cpp b/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.cpp deleted file mode 100644 index 156ea811e509..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/// -/// ContactsModuleOnLoad.cpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#include "ContactsModuleOnLoad.hpp" - -#include -#include -#include - -#include "JHybridContactsModuleSpec.hpp" -#include -#include - -namespace margelo::nitro::contacts { - -int initialize(JavaVM* vm) { - using namespace margelo::nitro; - using namespace margelo::nitro::contacts; - using namespace facebook; - - return facebook::jni::initialize(vm, [] { - // Register native JNI methods - margelo::nitro::contacts::JHybridContactsModuleSpec::registerNatives(); - - // Register Nitro Hybrid Objects - HybridObjectRegistry::registerHybridObjectConstructor( - "ContactsModule", - []() -> std::shared_ptr { - static DefaultConstructableObject object("com/margelo/nitro/contacts/HybridContactsModule"); - auto instance = object.create(); - auto globalRef = jni::make_global(instance); - return JNISharedPtr::make_shared_from_jni(globalRef); - } - ); - }); -} - -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.hpp b/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.hpp deleted file mode 100644 index b71adaca07bf..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/// -/// ContactsModuleOnLoad.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#include -#include - -namespace margelo::nitro::contacts { - - /** - * Initializes the native (C++) part of ContactsModule, and autolinks all Hybrid Objects. - * Call this in your `JNI_OnLoad` function (probably inside `cpp-adapter.cpp`). - * Example: - * ```cpp (cpp-adapter.cpp) - * JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { - * return margelo::nitro::contacts::initialize(vm); - * } - * ``` - */ - int initialize(JavaVM* vm); - -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.kt b/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.kt deleted file mode 100644 index 8b137891791f..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/ContactsModuleOnLoad.kt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/c++/JContact.hpp b/modules/ContactsNitroModule/nitrogen/generated/android/c++/JContact.hpp deleted file mode 100644 index bbd5354163a2..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/c++/JContact.hpp +++ /dev/null @@ -1,114 +0,0 @@ -/// -/// JContact.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -#include -#include "Contact.hpp" - -#include "JStringHolder.hpp" -#include "StringHolder.hpp" -#include -#include -#include - -namespace margelo::nitro::contacts { - - using namespace facebook; - - /** - * The C++ JNI bridge between the C++ struct "Contact" and the the Kotlin data class "Contact". - */ - struct JContact final: public jni::JavaClass { - public: - static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/contacts/Contact;"; - - public: - /** - * Convert this Java/Kotlin-based struct to the C++ struct Contact by copying all values to C++. - */ - [[maybe_unused]] - Contact toCpp() const { - static const auto clazz = javaClassStatic(); - static const auto fieldFirstName = clazz->getField("firstName"); - jni::local_ref firstName = this->getFieldValue(fieldFirstName); - static const auto fieldLastName = clazz->getField("lastName"); - jni::local_ref lastName = this->getFieldValue(fieldLastName); - static const auto fieldMiddleName = clazz->getField("middleName"); - jni::local_ref middleName = this->getFieldValue(fieldMiddleName); - static const auto fieldPhoneNumbers = clazz->getField>("phoneNumbers"); - jni::local_ref> phoneNumbers = this->getFieldValue(fieldPhoneNumbers); - static const auto fieldEmailAddresses = clazz->getField>("emailAddresses"); - jni::local_ref> emailAddresses = this->getFieldValue(fieldEmailAddresses); - static const auto fieldImageData = clazz->getField("imageData"); - jni::local_ref imageData = this->getFieldValue(fieldImageData); - static const auto fieldThumbnailImageData = clazz->getField("thumbnailImageData"); - jni::local_ref thumbnailImageData = this->getFieldValue(fieldThumbnailImageData); - return Contact( - firstName != nullptr ? std::make_optional(firstName->toStdString()) : std::nullopt, - lastName != nullptr ? std::make_optional(lastName->toStdString()) : std::nullopt, - middleName != nullptr ? std::make_optional(middleName->toStdString()) : std::nullopt, - phoneNumbers != nullptr ? std::make_optional([&]() { - size_t __size = phoneNumbers->size(); - std::vector __vector; - __vector.reserve(__size); - for (size_t __i = 0; __i < __size; __i++) { - auto __element = phoneNumbers->getElement(__i); - __vector.push_back(__element->toCpp()); - } - return __vector; - }()) : std::nullopt, - emailAddresses != nullptr ? std::make_optional([&]() { - size_t __size = emailAddresses->size(); - std::vector __vector; - __vector.reserve(__size); - for (size_t __i = 0; __i < __size; __i++) { - auto __element = emailAddresses->getElement(__i); - __vector.push_back(__element->toCpp()); - } - return __vector; - }()) : std::nullopt, - imageData != nullptr ? std::make_optional(imageData->toStdString()) : std::nullopt, - thumbnailImageData != nullptr ? std::make_optional(thumbnailImageData->toStdString()) : std::nullopt - ); - } - - public: - /** - * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java. - */ - [[maybe_unused]] - static jni::local_ref fromCpp(const Contact& value) { - return newInstance( - value.firstName.has_value() ? jni::make_jstring(value.firstName.value()) : nullptr, - value.lastName.has_value() ? jni::make_jstring(value.lastName.value()) : nullptr, - value.middleName.has_value() ? jni::make_jstring(value.middleName.value()) : nullptr, - value.phoneNumbers.has_value() ? [&]() { - size_t __size = value.phoneNumbers.value().size(); - jni::local_ref> __array = jni::JArrayClass::newArray(__size); - for (size_t __i = 0; __i < __size; __i++) { - const auto& __element = value.phoneNumbers.value()[__i]; - __array->setElement(__i, *JStringHolder::fromCpp(__element)); - } - return __array; - }() : nullptr, - value.emailAddresses.has_value() ? [&]() { - size_t __size = value.emailAddresses.value().size(); - jni::local_ref> __array = jni::JArrayClass::newArray(__size); - for (size_t __i = 0; __i < __size; __i++) { - const auto& __element = value.emailAddresses.value()[__i]; - __array->setElement(__i, *JStringHolder::fromCpp(__element)); - } - return __array; - }() : nullptr, - value.imageData.has_value() ? jni::make_jstring(value.imageData.value()) : nullptr, - value.thumbnailImageData.has_value() ? jni::make_jstring(value.thumbnailImageData.value()) : nullptr - ); - } - }; - -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/c++/JContactFields.hpp b/modules/ContactsNitroModule/nitrogen/generated/android/c++/JContactFields.hpp deleted file mode 100644 index 371b6607d105..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/c++/JContactFields.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/// -/// JContactFields.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -#include -#include "ContactFields.hpp" - -namespace margelo::nitro::contacts { - - using namespace facebook; - - /** - * The C++ JNI bridge between the C++ enum "ContactFields" and the the Kotlin enum "ContactFields". - */ - struct JContactFields final: public jni::JavaClass { - public: - static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/contacts/ContactFields;"; - - public: - /** - * Convert this Java/Kotlin-based enum to the C++ enum ContactFields. - */ - [[maybe_unused]] - ContactFields toCpp() const { - static const auto clazz = javaClassStatic(); - static const auto fieldOrdinal = clazz->getField("_ordinal"); - int ordinal = this->getFieldValue(fieldOrdinal); - return static_cast(ordinal); - } - - public: - /** - * Create a Java/Kotlin-based enum with the given C++ enum's value. - */ - [[maybe_unused]] - static jni::alias_ref fromCpp(ContactFields value) { - static const auto clazz = javaClassStatic(); - static const auto fieldFIRST_NAME = clazz->getStaticField("FIRST_NAME"); - static const auto fieldLAST_NAME = clazz->getStaticField("LAST_NAME"); - static const auto fieldMIDDLE_NAME = clazz->getStaticField("MIDDLE_NAME"); - static const auto fieldPHONE_NUMBERS = clazz->getStaticField("PHONE_NUMBERS"); - static const auto fieldEMAIL_ADDRESSES = clazz->getStaticField("EMAIL_ADDRESSES"); - static const auto fieldIMAGE_DATA = clazz->getStaticField("IMAGE_DATA"); - static const auto fieldTHUMBNAIL_IMAGE_DATA = clazz->getStaticField("THUMBNAIL_IMAGE_DATA"); - static const auto fieldGIVEN_NAME_KEY = clazz->getStaticField("GIVEN_NAME_KEY"); - - switch (value) { - case ContactFields::FIRST_NAME: - return clazz->getStaticFieldValue(fieldFIRST_NAME); - case ContactFields::LAST_NAME: - return clazz->getStaticFieldValue(fieldLAST_NAME); - case ContactFields::MIDDLE_NAME: - return clazz->getStaticFieldValue(fieldMIDDLE_NAME); - case ContactFields::PHONE_NUMBERS: - return clazz->getStaticFieldValue(fieldPHONE_NUMBERS); - case ContactFields::EMAIL_ADDRESSES: - return clazz->getStaticFieldValue(fieldEMAIL_ADDRESSES); - case ContactFields::IMAGE_DATA: - return clazz->getStaticFieldValue(fieldIMAGE_DATA); - case ContactFields::THUMBNAIL_IMAGE_DATA: - return clazz->getStaticFieldValue(fieldTHUMBNAIL_IMAGE_DATA); - case ContactFields::GIVEN_NAME_KEY: - return clazz->getStaticFieldValue(fieldGIVEN_NAME_KEY); - default: - std::string stringValue = std::to_string(static_cast(value)); - throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); - } - } - }; - -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/c++/JHybridContactsModuleSpec.cpp b/modules/ContactsNitroModule/nitrogen/generated/android/c++/JHybridContactsModuleSpec.cpp deleted file mode 100644 index e0505ee46d36..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/c++/JHybridContactsModuleSpec.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/// -/// JHybridContactsModuleSpec.cpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#include "JHybridContactsModuleSpec.hpp" - -// Forward declaration of `Contact` to properly resolve imports. -namespace margelo::nitro::contacts { struct Contact; } -// Forward declaration of `StringHolder` to properly resolve imports. -namespace margelo::nitro::contacts { struct StringHolder; } -// Forward declaration of `ContactFields` to properly resolve imports. -namespace margelo::nitro::contacts { enum class ContactFields; } - -#include -#include -#include "Contact.hpp" -#include -#include "JContact.hpp" -#include -#include -#include "StringHolder.hpp" -#include "JStringHolder.hpp" -#include "ContactFields.hpp" -#include "JContactFields.hpp" - -namespace margelo::nitro::contacts { - - jni::local_ref JHybridContactsModuleSpec::initHybrid(jni::alias_ref jThis) { - return makeCxxInstance(jThis); - } - - void JHybridContactsModuleSpec::registerNatives() { - registerHybrid({ - makeNativeMethod("initHybrid", JHybridContactsModuleSpec::initHybrid), - }); - } - - size_t JHybridContactsModuleSpec::getExternalMemorySize() noexcept { - static const auto method = _javaPart->getClass()->getMethod("getMemorySize"); - return method(_javaPart); - } - - // Properties - - - // Methods - std::shared_ptr>> JHybridContactsModuleSpec::getAll(const std::vector& keys) { - static const auto method = _javaPart->getClass()->getMethod(jni::alias_ref> /* keys */)>("getAll"); - auto __result = method(_javaPart, [&]() { - size_t __size = keys.size(); - jni::local_ref> __array = jni::JArrayClass::newArray(__size); - for (size_t __i = 0; __i < __size; __i++) { - const auto& __element = keys[__i]; - __array->setElement(__i, *JContactFields::fromCpp(__element)); - } - return __array; - }()); - return [&]() { - auto __promise = Promise>::create(); - __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { - auto __result = jni::static_ref_cast>(__boxedResult); - __promise->resolve([&]() { - size_t __size = __result->size(); - std::vector __vector; - __vector.reserve(__size); - for (size_t __i = 0; __i < __size; __i++) { - auto __element = __result->getElement(__i); - __vector.push_back(__element->toCpp()); - } - return __vector; - }()); - }); - __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) { - jni::JniException __jniError(__throwable); - __promise->reject(std::make_exception_ptr(__jniError)); - }); - return __promise; - }(); - } - -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/c++/JHybridContactsModuleSpec.hpp b/modules/ContactsNitroModule/nitrogen/generated/android/c++/JHybridContactsModuleSpec.hpp deleted file mode 100644 index 6b94d3be37e7..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/c++/JHybridContactsModuleSpec.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/// -/// HybridContactsModuleSpec.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -#include -#include -#include "HybridContactsModuleSpec.hpp" - - - - -namespace margelo::nitro::contacts { - - using namespace facebook; - - class JHybridContactsModuleSpec: public jni::HybridClass, - public virtual HybridContactsModuleSpec { - public: - static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/contacts/HybridContactsModuleSpec;"; - static jni::local_ref initHybrid(jni::alias_ref jThis); - static void registerNatives(); - - protected: - // C++ constructor (called from Java via `initHybrid()`) - explicit JHybridContactsModuleSpec(jni::alias_ref jThis) : - HybridObject(HybridContactsModuleSpec::TAG), - _javaPart(jni::make_global(jThis)) {} - - public: - virtual ~JHybridContactsModuleSpec() { - // Hermes GC can destroy JS objects on a non-JNI Thread. - jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); }); - } - - public: - size_t getExternalMemorySize() noexcept override; - - public: - inline const jni::global_ref& getJavaPart() const noexcept { - return _javaPart; - } - - public: - // Properties - - - public: - // Methods - std::shared_ptr>> getAll(const std::vector& keys) override; - - private: - friend HybridBase; - using HybridBase::HybridBase; - jni::global_ref _javaPart; - }; - -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/c++/JStringHolder.hpp b/modules/ContactsNitroModule/nitrogen/generated/android/c++/JStringHolder.hpp deleted file mode 100644 index 29695fe48d58..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/c++/JStringHolder.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/// -/// JStringHolder.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -#include -#include "StringHolder.hpp" - -#include - -namespace margelo::nitro::contacts { - - using namespace facebook; - - /** - * The C++ JNI bridge between the C++ struct "StringHolder" and the the Kotlin data class "StringHolder". - */ - struct JStringHolder final: public jni::JavaClass { - public: - static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/contacts/StringHolder;"; - - public: - /** - * Convert this Java/Kotlin-based struct to the C++ struct StringHolder by copying all values to C++. - */ - [[maybe_unused]] - StringHolder toCpp() const { - static const auto clazz = javaClassStatic(); - static const auto fieldValue = clazz->getField("value"); - jni::local_ref value = this->getFieldValue(fieldValue); - return StringHolder( - value->toStdString() - ); - } - - public: - /** - * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java. - */ - [[maybe_unused]] - static jni::local_ref fromCpp(const StringHolder& value) { - return newInstance( - jni::make_jstring(value.value) - ); - } - }; - -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/Contact.kt b/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/Contact.kt deleted file mode 100644 index a6d9e59a2b2b..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/Contact.kt +++ /dev/null @@ -1,27 +0,0 @@ -/// -/// Contact.kt -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -package com.margelo.nitro.contacts - -import androidx.annotation.Keep -import com.facebook.proguard.annotations.DoNotStrip -import com.margelo.nitro.core.* - -/** - * Represents the JavaScript object/struct "Contact". - */ -@DoNotStrip -@Keep -data class Contact( - val firstName: String?, - val lastName: String?, - val middleName: String?, - val phoneNumbers: Array?, - val emailAddresses: Array?, - val imageData: String?, - val thumbnailImageData: String? -) diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/ContactFields.kt b/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/ContactFields.kt deleted file mode 100644 index 841d6c82a32b..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/ContactFields.kt +++ /dev/null @@ -1,31 +0,0 @@ -/// -/// ContactFields.kt -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -package com.margelo.nitro.contacts - -import androidx.annotation.Keep -import com.facebook.proguard.annotations.DoNotStrip - -/** - * Represents the JavaScript enum/union "ContactFields". - */ -@DoNotStrip -@Keep -enum class ContactFields { - FIRST_NAME, - LAST_NAME, - MIDDLE_NAME, - PHONE_NUMBERS, - EMAIL_ADDRESSES, - IMAGE_DATA, - THUMBNAIL_IMAGE_DATA, - GIVEN_NAME_KEY; - - @DoNotStrip - @Keep - private val _ordinal = ordinal -} diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/HybridContactsModuleSpec.kt b/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/HybridContactsModuleSpec.kt deleted file mode 100644 index 63a118b8be57..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/HybridContactsModuleSpec.kt +++ /dev/null @@ -1,64 +0,0 @@ -/// -/// HybridContactsModuleSpec.kt -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -package com.margelo.nitro.contacts - -import android.util.Log -import androidx.annotation.Keep -import com.facebook.jni.HybridData -import com.facebook.proguard.annotations.DoNotStrip -import com.margelo.nitro.core.* - -/** - * A Kotlin class representing the ContactsModule HybridObject. - * Implement this abstract class to create Kotlin-based instances of ContactsModule. - */ -@DoNotStrip -@Keep -@Suppress("RedundantSuppression", "KotlinJniMissingFunction", "PropertyName", "RedundantUnitReturnType", "unused") -abstract class HybridContactsModuleSpec: HybridObject() { - @DoNotStrip - private var mHybridData: HybridData = initHybrid() - - init { - // Pass this `HybridData` through to it's base class, - // to represent inheritance to JHybridObject on C++ side - super.updateNative(mHybridData) - } - - /** - * Call from a child class to initialize HybridData with a child. - */ - override fun updateNative(hybridData: HybridData) { - mHybridData = hybridData - } - - // Properties - - - // Methods - @DoNotStrip - @Keep - abstract fun getAll(keys: Array): Promise> - - private external fun initHybrid(): HybridData - - companion object { - private const val TAG = "HybridContactsModuleSpec" - init { - try { - Log.i(TAG, "Loading ContactsModule C++ library...") - System.loadLibrary("ContactsModule") - Log.i(TAG, "Successfully loaded ContactsModule C++ library!") - } catch (e: Error) { - Log.e(TAG, "Failed to load ContactsModule C++ library! Is it properly installed and linked? " + - "Is the name correct? (see `CMakeLists.txt`, at `add_library(...)`)", e) - throw e - } - } - } -} diff --git a/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/StringHolder.kt b/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/StringHolder.kt deleted file mode 100644 index b6af53e53217..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/android/kotlin/com/margelo/nitro/contacts/StringHolder.kt +++ /dev/null @@ -1,21 +0,0 @@ -/// -/// StringHolder.kt -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -package com.margelo.nitro.contacts - -import androidx.annotation.Keep -import com.facebook.proguard.annotations.DoNotStrip -import com.margelo.nitro.core.* - -/** - * Represents the JavaScript object/struct "StringHolder". - */ -@DoNotStrip -@Keep -data class StringHolder( - val value: String -) diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule+autolinking.rb b/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule+autolinking.rb deleted file mode 100644 index 35bc19c47bf7..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule+autolinking.rb +++ /dev/null @@ -1,58 +0,0 @@ -# -# ContactsModule+autolinking.rb -# This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -# https://github.com/mrousavy/nitro -# Copyright © 2024 Marc Rousavy @ Margelo -# - -# This is a Ruby script that adds all files generated by Nitrogen -# to the given podspec. -# -# To use it, add this to your .podspec: -# ```ruby -# Pod::Spec.new do |spec| -# # ... -# -# # Add all files generated by Nitrogen -# load 'nitrogen/generated/ios/ContactsModule+autolinking.rb' -# add_nitrogen_files(spec) -# end -# ``` - -def add_nitrogen_files(spec) - Pod::UI.puts "[NitroModules] 🔥 ContactsModule is boosted by nitro!" - - spec.dependency "NitroModules" - - current_source_files = Array(spec.attributes_hash['source_files']) - spec.source_files = current_source_files + [ - # Generated cross-platform specs - "nitrogen/generated/shared/**/*.{h,hpp,c,cpp,swift}", - # Generated bridges for the cross-platform specs - "nitrogen/generated/ios/**/*.{h,hpp,c,cpp,mm,swift}", - ] - - current_public_header_files = Array(spec.attributes_hash['public_header_files']) - spec.public_header_files = current_public_header_files + [ - # Generated specs - "nitrogen/generated/shared/**/*.{h,hpp}", - # Swift to C++ bridging helpers - "nitrogen/generated/ios/ContactsModule-Swift-Cxx-Bridge.hpp" - ] - - current_private_header_files = Array(spec.attributes_hash['private_header_files']) - spec.private_header_files = current_private_header_files + [ - # iOS specific specs - "nitrogen/generated/ios/c++/**/*.{h,hpp}", - ] - - current_pod_target_xcconfig = spec.attributes_hash['pod_target_xcconfig'] || {} - spec.pod_target_xcconfig = current_pod_target_xcconfig.merge({ - # Use C++ 20 - "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", - # Enables C++ <-> Swift interop (by default it's only C) - "SWIFT_OBJC_INTEROP_MODE" => "objcxx", - # Enables stricter modular headers - "DEFINES_MODULE" => "YES", - }) -end diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Bridge.cpp b/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Bridge.cpp deleted file mode 100644 index 4746dbadaa18..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Bridge.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/// -/// ContactsModule-Swift-Cxx-Bridge.cpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#include "ContactsModule-Swift-Cxx-Bridge.hpp" - -// Include C++ implementation defined types -#include "ContactsModule-Swift-Cxx-Umbrella.hpp" -#include "HybridContactsModuleSpecSwift.hpp" -#include - -namespace margelo::nitro::contacts::bridge::swift { - - // pragma MARK: std::shared_ptr - std::shared_ptr create_std__shared_ptr_margelo__nitro__contacts__HybridContactsModuleSpec_(void* _Nonnull swiftUnsafePointer) { - ContactsModule::HybridContactsModuleSpecCxx swiftPart = ContactsModule::HybridContactsModuleSpecCxxUnsafe::fromUnsafe(swiftUnsafePointer); - return HybridContext::getOrCreate(swiftPart); - } - void* _Nonnull get_std__shared_ptr_margelo__nitro__contacts__HybridContactsModuleSpec_(std__shared_ptr_margelo__nitro__contacts__HybridContactsModuleSpec_ cppType) { - std::shared_ptr swiftWrapper = std::dynamic_pointer_cast(cppType); - #ifdef NITRO_DEBUG - if (swiftWrapper == nullptr) [[unlikely]] { - throw std::runtime_error("Class \"HybridContactsModuleSpec\" is not implemented in Swift!"); - } - #endif - ContactsModule::HybridContactsModuleSpecCxx swiftPart = swiftWrapper->getSwiftPart(); - return ContactsModule::HybridContactsModuleSpecCxxUnsafe::toUnsafe(swiftPart); - } - -} // namespace margelo::nitro::contacts::bridge::swift diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Bridge.hpp b/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Bridge.hpp deleted file mode 100644 index 76d584613df2..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Bridge.hpp +++ /dev/null @@ -1,167 +0,0 @@ -/// -/// ContactsModule-Swift-Cxx-Bridge.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -// Forward declarations of C++ defined types -// Forward declaration of `ContactFields` to properly resolve imports. -namespace margelo::nitro::contacts { enum class ContactFields; } -// Forward declaration of `Contact` to properly resolve imports. -namespace margelo::nitro::contacts { struct Contact; } -// Forward declaration of `HybridContactsModuleSpec` to properly resolve imports. -namespace margelo::nitro::contacts { class HybridContactsModuleSpec; } -// Forward declaration of `StringHolder` to properly resolve imports. -namespace margelo::nitro::contacts { struct StringHolder; } - -// Forward declarations of Swift defined types -// Forward declaration of `HybridContactsModuleSpecCxx` to properly resolve imports. -namespace ContactsModule { class HybridContactsModuleSpecCxx; } - -// Include C++ defined types -#include "Contact.hpp" -#include "ContactFields.hpp" -#include "HybridContactsModuleSpec.hpp" -#include "StringHolder.hpp" -#include -#include -#include -#include -#include -#include -#include - -/** - * Contains specialized versions of C++ templated types so they can be accessed from Swift, - * as well as helper functions to interact with those C++ types from Swift. - */ -namespace margelo::nitro::contacts::bridge::swift { - - // pragma MARK: std::optional - /** - * Specialized version of `std::optional`. - */ - using std__optional_std__string_ = std::optional; - inline std::optional create_std__optional_std__string_(const std::string& value) { - return std::optional(value); - } - - // pragma MARK: std::vector - /** - * Specialized version of `std::vector`. - */ - using std__vector_StringHolder_ = std::vector; - inline std::vector create_std__vector_StringHolder_(size_t size) { - std::vector vector; - vector.reserve(size); - return vector; - } - - // pragma MARK: std::optional> - /** - * Specialized version of `std::optional>`. - */ - using std__optional_std__vector_StringHolder__ = std::optional>; - inline std::optional> create_std__optional_std__vector_StringHolder__(const std::vector& value) { - return std::optional>(value); - } - - // pragma MARK: std::vector - /** - * Specialized version of `std::vector`. - */ - using std__vector_Contact_ = std::vector; - inline std::vector create_std__vector_Contact_(size_t size) { - std::vector vector; - vector.reserve(size); - return vector; - } - - // pragma MARK: std::shared_ptr>> - /** - * Specialized version of `std::shared_ptr>>`. - */ - using std__shared_ptr_Promise_std__vector_Contact___ = std::shared_ptr>>; - inline std::shared_ptr>> create_std__shared_ptr_Promise_std__vector_Contact___() { - return Promise>::create(); - } - - // pragma MARK: std::function& /* result */)> - /** - * Specialized version of `std::function&)>`. - */ - using Func_void_std__vector_Contact_ = std::function& /* result */)>; - /** - * Wrapper class for a `std::function& / * result * /)>`, this can be used from Swift. - */ - class Func_void_std__vector_Contact__Wrapper final { - public: - explicit Func_void_std__vector_Contact__Wrapper(const std::function& /* result */)>& func): _function(func) {} - explicit Func_void_std__vector_Contact__Wrapper(std::function& /* result */)>&& func): _function(std::move(func)) {} - inline void call(std::vector result) const { - _function(result); - } - private: - std::function& /* result */)> _function; - }; - inline Func_void_std__vector_Contact_ create_Func_void_std__vector_Contact_(void* _Nonnull closureHolder, void(* _Nonnull call)(void* _Nonnull /* closureHolder */, std::vector), void(* _Nonnull destroy)(void* _Nonnull)) { - std::shared_ptr sharedClosureHolder(closureHolder, destroy); - return Func_void_std__vector_Contact_([sharedClosureHolder, call](const std::vector& result) -> void { - call(sharedClosureHolder.get(), result); - }); - } - inline std::shared_ptr share_Func_void_std__vector_Contact_(const Func_void_std__vector_Contact_& value) { - return std::make_shared(value); - } - - // pragma MARK: std::function - /** - * Specialized version of `std::function`. - */ - using Func_void_std__exception_ptr = std::function; - /** - * Wrapper class for a `std::function`, this can be used from Swift. - */ - class Func_void_std__exception_ptr_Wrapper final { - public: - explicit Func_void_std__exception_ptr_Wrapper(const std::function& func): _function(func) {} - explicit Func_void_std__exception_ptr_Wrapper(std::function&& func): _function(std::move(func)) {} - inline void call(std::exception_ptr error) const { - _function(error); - } - private: - std::function _function; - }; - inline Func_void_std__exception_ptr create_Func_void_std__exception_ptr(void* _Nonnull closureHolder, void(* _Nonnull call)(void* _Nonnull /* closureHolder */, std::exception_ptr), void(* _Nonnull destroy)(void* _Nonnull)) { - std::shared_ptr sharedClosureHolder(closureHolder, destroy); - return Func_void_std__exception_ptr([sharedClosureHolder, call](const std::exception_ptr& error) -> void { - call(sharedClosureHolder.get(), error); - }); - } - inline std::shared_ptr share_Func_void_std__exception_ptr(const Func_void_std__exception_ptr& value) { - return std::make_shared(value); - } - - // pragma MARK: std::vector - /** - * Specialized version of `std::vector`. - */ - using std__vector_ContactFields_ = std::vector; - inline std::vector create_std__vector_ContactFields_(size_t size) { - std::vector vector; - vector.reserve(size); - return vector; - } - - // pragma MARK: std::shared_ptr - /** - * Specialized version of `std::shared_ptr`. - */ - using std__shared_ptr_margelo__nitro__contacts__HybridContactsModuleSpec_ = std::shared_ptr; - std::shared_ptr create_std__shared_ptr_margelo__nitro__contacts__HybridContactsModuleSpec_(void* _Nonnull swiftUnsafePointer); - void* _Nonnull get_std__shared_ptr_margelo__nitro__contacts__HybridContactsModuleSpec_(std__shared_ptr_margelo__nitro__contacts__HybridContactsModuleSpec_ cppType); - -} // namespace margelo::nitro::contacts::bridge::swift diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Umbrella.hpp b/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Umbrella.hpp deleted file mode 100644 index 6f38d7c7e417..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModule-Swift-Cxx-Umbrella.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/// -/// ContactsModule-Swift-Cxx-Umbrella.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -// Forward declarations of C++ defined types -// Forward declaration of `ContactFields` to properly resolve imports. -namespace margelo::nitro::contacts { enum class ContactFields; } -// Forward declaration of `Contact` to properly resolve imports. -namespace margelo::nitro::contacts { struct Contact; } -// Forward declaration of `HybridContactsModuleSpec` to properly resolve imports. -namespace margelo::nitro::contacts { class HybridContactsModuleSpec; } -// Forward declaration of `StringHolder` to properly resolve imports. -namespace margelo::nitro::contacts { struct StringHolder; } - -// Include C++ defined types -#include "Contact.hpp" -#include "ContactFields.hpp" -#include "HybridContactsModuleSpec.hpp" -#include "StringHolder.hpp" -#include -#include -#include -#include -#include - -// C++ helpers for Swift -#include "ContactsModule-Swift-Cxx-Bridge.hpp" - -// Common C++ types used in Swift -#include -#include -#include -#include - -// Forward declarations of Swift defined types -// Forward declaration of `HybridContactsModuleSpecCxx` to properly resolve imports. -namespace ContactsModule { class HybridContactsModuleSpecCxx; } - -// Include Swift defined types -#if __has_include("ContactsModule-Swift.h") -// This header is generated by Xcode/Swift on every app build. -// If it cannot be found, make sure the Swift module's name (= podspec name) is actually "ContactsModule". -#include "ContactsModule-Swift.h" -// Same as above, but used when building with frameworks (`use_frameworks`) -#elif __has_include() -#include -#else -#error ContactsModule's autogenerated Swift header cannot be found! Make sure the Swift module's name (= podspec name) is actually "ContactsModule", and try building the app first. -#endif diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModuleAutolinking.mm b/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModuleAutolinking.mm deleted file mode 100644 index e769fb6a6806..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModuleAutolinking.mm +++ /dev/null @@ -1,33 +0,0 @@ -/// -/// ContactsModuleAutolinking.mm -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#import -#import -#import "ContactsModule-Swift-Cxx-Umbrella.hpp" -#import - -#include "HybridContactsModuleSpecSwift.hpp" - -@interface ContactsModuleAutolinking : NSObject -@end - -@implementation ContactsModuleAutolinking - -+ (void) load { - using namespace margelo::nitro; - using namespace margelo::nitro::contacts; - - HybridObjectRegistry::registerHybridObjectConstructor( - "ContactsModule", - []() -> std::shared_ptr { - std::shared_ptr hybridObject = ContactsModule::ContactsModuleAutolinking::createContactsModule(); - return hybridObject; - } - ); -} - -@end diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModuleAutolinking.swift b/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModuleAutolinking.swift deleted file mode 100644 index 15d9d9b9064e..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/ContactsModuleAutolinking.swift +++ /dev/null @@ -1,26 +0,0 @@ -/// -/// ContactsModuleAutolinking.swift -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -public final class ContactsModuleAutolinking { - public typealias bridge = margelo.nitro.contacts.bridge.swift - - /** - * Creates an instance of a Swift class that implements `HybridContactsModuleSpec`, - * and wraps it in a Swift class that can directly interop with C++ (`HybridContactsModuleSpecCxx`) - * - * This is generated by Nitrogen and will initialize the class specified - * in the `"autolinking"` property of `nitro.json` (in this case, `HybridContactsModule`). - */ - public static func createContactsModule() -> bridge.std__shared_ptr_margelo__nitro__contacts__HybridContactsModuleSpec_ { - let hybridObject = HybridContactsModule() - return { () -> bridge.std__shared_ptr_margelo__nitro__contacts__HybridContactsModuleSpec_ in - let __cxxWrapped = HybridContactsModuleSpecCxx(hybridObject) - let __pointer = HybridContactsModuleSpecCxxUnsafe.toUnsafe(__cxxWrapped) - return bridge.create_std__shared_ptr_margelo__nitro__contacts__HybridContactsModuleSpec_(__pointer) - }() - } -} diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/c++/HybridContactsModuleSpecSwift.cpp b/modules/ContactsNitroModule/nitrogen/generated/ios/c++/HybridContactsModuleSpecSwift.cpp deleted file mode 100644 index 71151f3c1883..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/c++/HybridContactsModuleSpecSwift.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/// -/// HybridContactsModuleSpecSwift.cpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#include "HybridContactsModuleSpecSwift.hpp" - -namespace margelo::nitro::contacts { -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/c++/HybridContactsModuleSpecSwift.hpp b/modules/ContactsNitroModule/nitrogen/generated/ios/c++/HybridContactsModuleSpecSwift.hpp deleted file mode 100644 index dbb4fe829dc2..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/c++/HybridContactsModuleSpecSwift.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/// -/// HybridContactsModuleSpecSwift.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -#include "HybridContactsModuleSpec.hpp" - -// Forward declaration of `HybridContactsModuleSpecCxx` to properly resolve imports. -namespace ContactsModule { class HybridContactsModuleSpecCxx; } - -// Forward declaration of `Contact` to properly resolve imports. -namespace margelo::nitro::contacts { struct Contact; } -// Forward declaration of `StringHolder` to properly resolve imports. -namespace margelo::nitro::contacts { struct StringHolder; } -// Forward declaration of `ContactFields` to properly resolve imports. -namespace margelo::nitro::contacts { enum class ContactFields; } - -#include -#include -#include "Contact.hpp" -#include -#include -#include "StringHolder.hpp" -#include "ContactFields.hpp" - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - -#include "ContactsModule-Swift-Cxx-Umbrella.hpp" - -namespace margelo::nitro::contacts { - - /** - * The C++ part of HybridContactsModuleSpecCxx.swift. - * - * HybridContactsModuleSpecSwift (C++) accesses HybridContactsModuleSpecCxx (Swift), and might - * contain some additional bridging code for C++ <> Swift interop. - * - * Since this obviously introduces an overhead, I hope at some point in - * the future, HybridContactsModuleSpecCxx can directly inherit from the C++ class HybridContactsModuleSpec - * to simplify the whole structure and memory management. - */ - class HybridContactsModuleSpecSwift: public virtual HybridContactsModuleSpec { - public: - // Constructor from a Swift instance - explicit HybridContactsModuleSpecSwift(const ContactsModule::HybridContactsModuleSpecCxx& swiftPart): - HybridObject(HybridContactsModuleSpec::TAG), - _swiftPart(swiftPart) { } - - public: - // Get the Swift part - inline ContactsModule::HybridContactsModuleSpecCxx getSwiftPart() noexcept { return _swiftPart; } - - public: - // Get memory pressure - inline size_t getExternalMemorySize() noexcept override { - return _swiftPart.getMemorySize(); - } - - public: - // Properties - - - public: - // Methods - inline std::shared_ptr>> getAll(const std::vector& keys) override { - auto __result = _swiftPart.getAll(keys); - return __result; - } - - private: - ContactsModule::HybridContactsModuleSpecCxx _swiftPart; - }; - -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/swift/Contact.swift b/modules/ContactsNitroModule/nitrogen/generated/ios/swift/Contact.swift deleted file mode 100644 index 404d6ba86b25..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/swift/Contact.swift +++ /dev/null @@ -1,251 +0,0 @@ -/// -/// Contact.swift -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -import NitroModules - -/** - * Represents an instance of `Contact`, backed by a C++ struct. - */ -public typealias Contact = margelo.nitro.contacts.Contact - -public extension Contact { - private typealias bridge = margelo.nitro.contacts.bridge.swift - - /** - * Create a new instance of `Contact`. - */ - init(firstName: String?, lastName: String?, middleName: String?, phoneNumbers: [StringHolder]?, emailAddresses: [StringHolder]?, imageData: String?, thumbnailImageData: String?) { - self.init({ () -> bridge.std__optional_std__string_ in - if let __unwrappedValue = firstName { - return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) - } else { - return .init() - } - }(), { () -> bridge.std__optional_std__string_ in - if let __unwrappedValue = lastName { - return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) - } else { - return .init() - } - }(), { () -> bridge.std__optional_std__string_ in - if let __unwrappedValue = middleName { - return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) - } else { - return .init() - } - }(), { () -> bridge.std__optional_std__vector_StringHolder__ in - if let __unwrappedValue = phoneNumbers { - return bridge.create_std__optional_std__vector_StringHolder__({ () -> bridge.std__vector_StringHolder_ in - var __vector = bridge.create_std__vector_StringHolder_(__unwrappedValue.count) - for __item in __unwrappedValue { - __vector.push_back(__item) - } - return __vector - }()) - } else { - return .init() - } - }(), { () -> bridge.std__optional_std__vector_StringHolder__ in - if let __unwrappedValue = emailAddresses { - return bridge.create_std__optional_std__vector_StringHolder__({ () -> bridge.std__vector_StringHolder_ in - var __vector = bridge.create_std__vector_StringHolder_(__unwrappedValue.count) - for __item in __unwrappedValue { - __vector.push_back(__item) - } - return __vector - }()) - } else { - return .init() - } - }(), { () -> bridge.std__optional_std__string_ in - if let __unwrappedValue = imageData { - return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) - } else { - return .init() - } - }(), { () -> bridge.std__optional_std__string_ in - if let __unwrappedValue = thumbnailImageData { - return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) - } else { - return .init() - } - }()) - } - - var firstName: String? { - @inline(__always) - get { - return { () -> String? in - if let __unwrapped = self.__firstName.value { - return String(__unwrapped) - } else { - return nil - } - }() - } - @inline(__always) - set { - self.__firstName = { () -> bridge.std__optional_std__string_ in - if let __unwrappedValue = newValue { - return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) - } else { - return .init() - } - }() - } - } - - var lastName: String? { - @inline(__always) - get { - return { () -> String? in - if let __unwrapped = self.__lastName.value { - return String(__unwrapped) - } else { - return nil - } - }() - } - @inline(__always) - set { - self.__lastName = { () -> bridge.std__optional_std__string_ in - if let __unwrappedValue = newValue { - return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) - } else { - return .init() - } - }() - } - } - - var middleName: String? { - @inline(__always) - get { - return { () -> String? in - if let __unwrapped = self.__middleName.value { - return String(__unwrapped) - } else { - return nil - } - }() - } - @inline(__always) - set { - self.__middleName = { () -> bridge.std__optional_std__string_ in - if let __unwrappedValue = newValue { - return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) - } else { - return .init() - } - }() - } - } - - var phoneNumbers: [StringHolder]? { - @inline(__always) - get { - return { () -> [StringHolder]? in - if let __unwrapped = self.__phoneNumbers.value { - return __unwrapped.map({ __item in __item }) - } else { - return nil - } - }() - } - @inline(__always) - set { - self.__phoneNumbers = { () -> bridge.std__optional_std__vector_StringHolder__ in - if let __unwrappedValue = newValue { - return bridge.create_std__optional_std__vector_StringHolder__({ () -> bridge.std__vector_StringHolder_ in - var __vector = bridge.create_std__vector_StringHolder_(__unwrappedValue.count) - for __item in __unwrappedValue { - __vector.push_back(__item) - } - return __vector - }()) - } else { - return .init() - } - }() - } - } - - var emailAddresses: [StringHolder]? { - @inline(__always) - get { - return { () -> [StringHolder]? in - if let __unwrapped = self.__emailAddresses.value { - return __unwrapped.map({ __item in __item }) - } else { - return nil - } - }() - } - @inline(__always) - set { - self.__emailAddresses = { () -> bridge.std__optional_std__vector_StringHolder__ in - if let __unwrappedValue = newValue { - return bridge.create_std__optional_std__vector_StringHolder__({ () -> bridge.std__vector_StringHolder_ in - var __vector = bridge.create_std__vector_StringHolder_(__unwrappedValue.count) - for __item in __unwrappedValue { - __vector.push_back(__item) - } - return __vector - }()) - } else { - return .init() - } - }() - } - } - - var imageData: String? { - @inline(__always) - get { - return { () -> String? in - if let __unwrapped = self.__imageData.value { - return String(__unwrapped) - } else { - return nil - } - }() - } - @inline(__always) - set { - self.__imageData = { () -> bridge.std__optional_std__string_ in - if let __unwrappedValue = newValue { - return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) - } else { - return .init() - } - }() - } - } - - var thumbnailImageData: String? { - @inline(__always) - get { - return { () -> String? in - if let __unwrapped = self.__thumbnailImageData.value { - return String(__unwrapped) - } else { - return nil - } - }() - } - @inline(__always) - set { - self.__thumbnailImageData = { () -> bridge.std__optional_std__string_ in - if let __unwrappedValue = newValue { - return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) - } else { - return .init() - } - }() - } - } -} diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/swift/ContactFields.swift b/modules/ContactsNitroModule/nitrogen/generated/ios/swift/ContactFields.swift deleted file mode 100644 index ce38940795d9..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/swift/ContactFields.swift +++ /dev/null @@ -1,64 +0,0 @@ -/// -/// ContactFields.swift -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -/** - * Represents the JS union `ContactFields`, backed by a C++ enum. - */ -public typealias ContactFields = margelo.nitro.contacts.ContactFields - -public extension ContactFields { - /** - * Get a ContactFields for the given String value, or - * return `nil` if the given value was invalid/unknown. - */ - init?(fromString string: String) { - switch string { - case "FIRST_NAME": - self = .firstName - case "LAST_NAME": - self = .lastName - case "MIDDLE_NAME": - self = .middleName - case "PHONE_NUMBERS": - self = .phoneNumbers - case "EMAIL_ADDRESSES": - self = .emailAddresses - case "IMAGE_DATA": - self = .imageData - case "THUMBNAIL_IMAGE_DATA": - self = .thumbnailImageData - case "GIVEN_NAME_KEY": - self = .givenNameKey - default: - return nil - } - } - - /** - * Get the String value this ContactFields represents. - */ - var stringValue: String { - switch self { - case .firstName: - return "FIRST_NAME" - case .lastName: - return "LAST_NAME" - case .middleName: - return "MIDDLE_NAME" - case .phoneNumbers: - return "PHONE_NUMBERS" - case .emailAddresses: - return "EMAIL_ADDRESSES" - case .imageData: - return "IMAGE_DATA" - case .thumbnailImageData: - return "THUMBNAIL_IMAGE_DATA" - case .givenNameKey: - return "GIVEN_NAME_KEY" - } - } -} diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/swift/HybridContactsModuleSpec.swift b/modules/ContactsNitroModule/nitrogen/generated/ios/swift/HybridContactsModuleSpec.swift deleted file mode 100644 index 611110efca1d..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/swift/HybridContactsModuleSpec.swift +++ /dev/null @@ -1,36 +0,0 @@ -/// -/// HybridContactsModuleSpec.swift -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -import Foundation -import NitroModules - -/** - * A Swift protocol representing the ContactsModule HybridObject. - * Implement this protocol to create Swift-based instances of ContactsModule. - * - * When implementing this protocol, make sure to initialize `hybridContext` - example: - * ``` - * public class HybridContactsModule : HybridContactsModuleSpec { - * // Initialize HybridContext - * var hybridContext = margelo.nitro.HybridContext() - * - * // Return size of the instance to inform JS GC about memory pressure - * var memorySize: Int { - * return getSizeOf(self) - * } - * - * // ... - * } - * ``` - */ -public protocol HybridContactsModuleSpec: AnyObject, HybridObjectSpec { - // Properties - - - // Methods - func getAll(keys: [ContactFields]) throws -> Promise<[Contact]> -} diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/swift/HybridContactsModuleSpecCxx.swift b/modules/ContactsNitroModule/nitrogen/generated/ios/swift/HybridContactsModuleSpecCxx.swift deleted file mode 100644 index 156cdf86bd7f..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/swift/HybridContactsModuleSpecCxx.swift +++ /dev/null @@ -1,123 +0,0 @@ -/// -/// HybridContactsModuleSpecCxx.swift -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -import Foundation -import NitroModules - -/** - * Helper class for converting instances of `HybridContactsModuleSpecCxx` from- and to unsafe pointers. - * This is useful to pass Swift classes to C++, without having to strongly type the C++ function signature. - * The actual Swift type can be included in the .cpp file, without having to forward-declare anything in .hpp. - */ -public final class HybridContactsModuleSpecCxxUnsafe { - /** - * Casts a `HybridContactsModuleSpecCxx` instance to a retained unsafe raw pointer. - * This acquires one additional strong reference on the object! - */ - public static func toUnsafe(_ instance: HybridContactsModuleSpecCxx) -> UnsafeMutableRawPointer { - return Unmanaged.passRetained(instance).toOpaque() - } - - /** - * Casts an unsafe pointer to a `HybridContactsModuleSpecCxx`. - * The pointer has to be a retained opaque `Unmanaged`. - * This removes one strong reference from the object! - */ - public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridContactsModuleSpecCxx { - return Unmanaged.fromOpaque(pointer).takeRetainedValue() - } -} - -/** - * A class implementation that bridges HybridContactsModuleSpec over to C++. - * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined. - * - * Also, some Swift types need to be bridged with special handling: - * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330) - * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper - * - Throwing methods need to be wrapped with a Result type, as exceptions cannot be propagated to C++ - */ -public class HybridContactsModuleSpecCxx { - /** - * The Swift <> C++ bridge's namespace (`margelo::nitro::contacts::bridge::swift`) - * from `ContactsModule-Swift-Cxx-Bridge.hpp`. - * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift. - */ - public typealias bridge = margelo.nitro.contacts.bridge.swift - - /** - * Holds an instance of the `HybridContactsModuleSpec` Swift protocol. - */ - private var __implementation: any HybridContactsModuleSpec - - /** - * Create a new `HybridContactsModuleSpecCxx` that wraps the given `HybridContactsModuleSpec`. - * All properties and methods bridge to C++ types. - */ - public init(_ implementation: some HybridContactsModuleSpec) { - self.__implementation = implementation - /* no base class */ - } - - /** - * Get the actual `HybridContactsModuleSpec` instance this class wraps. - */ - @inline(__always) - public func getHybridContactsModuleSpec() -> any HybridContactsModuleSpec { - return __implementation - } - - /** - * Contains a (weak) reference to the C++ HybridObject to cache it. - */ - public var hybridContext: margelo.nitro.HybridContext { - @inline(__always) - get { - return self.__implementation.hybridContext - } - @inline(__always) - set { - self.__implementation.hybridContext = newValue - } - } - - /** - * Get the memory size of the Swift class (plus size of any other allocations) - * so the JS VM can properly track it and garbage-collect the JS object if needed. - */ - @inline(__always) - public var memorySize: Int { - return self.__implementation.memorySize - } - - // Properties - - - // Methods - @inline(__always) - public func getAll(keys: bridge.std__vector_ContactFields_) -> bridge.std__shared_ptr_Promise_std__vector_Contact___ { - do { - let __result = try self.__implementation.getAll(keys: keys.map({ __item in __item })) - return { () -> bridge.std__shared_ptr_Promise_std__vector_Contact___ in - let __promise = bridge.create_std__shared_ptr_Promise_std__vector_Contact___() - __result - .then({ __result in __promise.pointee.resolve({ () -> bridge.std__vector_Contact_ in - var __vector = bridge.create_std__vector_Contact_(__result.count) - for __item in __result { - __vector.push_back(__item) - } - return __vector - }()) }) - .catch({ __error in __promise.pointee.reject(__error.toCpp()) }) - return __promise - }() - } catch { - let __message = "\(error.localizedDescription)" - fatalError("Swift errors can currently not be propagated to C++! See https://github.com/swiftlang/swift/issues/75290 (Error: \(__message))") - } - } -} diff --git a/modules/ContactsNitroModule/nitrogen/generated/ios/swift/StringHolder.swift b/modules/ContactsNitroModule/nitrogen/generated/ios/swift/StringHolder.swift deleted file mode 100644 index 477279082456..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/ios/swift/StringHolder.swift +++ /dev/null @@ -1,35 +0,0 @@ -/// -/// StringHolder.swift -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -import NitroModules - -/** - * Represents an instance of `StringHolder`, backed by a C++ struct. - */ -public typealias StringHolder = margelo.nitro.contacts.StringHolder - -public extension StringHolder { - private typealias bridge = margelo.nitro.contacts.bridge.swift - - /** - * Create a new instance of `StringHolder`. - */ - init(value: String) { - self.init(std.string(value)) - } - - var value: String { - @inline(__always) - get { - return String(self.__value) - } - @inline(__always) - set { - self.__value = std.string(newValue) - } - } -} diff --git a/modules/ContactsNitroModule/nitrogen/generated/shared/c++/Contact.hpp b/modules/ContactsNitroModule/nitrogen/generated/shared/c++/Contact.hpp deleted file mode 100644 index 6e4a5bd0c27e..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/shared/c++/Contact.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/// -/// Contact.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - -// Forward declaration of `StringHolder` to properly resolve imports. -namespace margelo::nitro::contacts { struct StringHolder; } - -#include -#include -#include -#include "StringHolder.hpp" - -namespace margelo::nitro::contacts { - - /** - * A struct which can be represented as a JavaScript object (Contact). - */ - struct Contact { - public: - std::optional firstName SWIFT_PRIVATE; - std::optional lastName SWIFT_PRIVATE; - std::optional middleName SWIFT_PRIVATE; - std::optional> phoneNumbers SWIFT_PRIVATE; - std::optional> emailAddresses SWIFT_PRIVATE; - std::optional imageData SWIFT_PRIVATE; - std::optional thumbnailImageData SWIFT_PRIVATE; - - public: - explicit Contact(std::optional firstName, std::optional lastName, std::optional middleName, std::optional> phoneNumbers, std::optional> emailAddresses, std::optional imageData, std::optional thumbnailImageData): firstName(firstName), lastName(lastName), middleName(middleName), phoneNumbers(phoneNumbers), emailAddresses(emailAddresses), imageData(imageData), thumbnailImageData(thumbnailImageData) {} - }; - -} // namespace margelo::nitro::contacts - -namespace margelo::nitro { - - using namespace margelo::nitro::contacts; - - // C++ Contact <> JS Contact (object) - template <> - struct JSIConverter { - static inline Contact fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - jsi::Object obj = arg.asObject(runtime); - return Contact( - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "firstName")), - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "lastName")), - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "middleName")), - JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, "phoneNumbers")), - JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, "emailAddresses")), - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "imageData")), - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "thumbnailImageData")) - ); - } - static inline jsi::Value toJSI(jsi::Runtime& runtime, const Contact& arg) { - jsi::Object obj(runtime); - obj.setProperty(runtime, "firstName", JSIConverter>::toJSI(runtime, arg.firstName)); - obj.setProperty(runtime, "lastName", JSIConverter>::toJSI(runtime, arg.lastName)); - obj.setProperty(runtime, "middleName", JSIConverter>::toJSI(runtime, arg.middleName)); - obj.setProperty(runtime, "phoneNumbers", JSIConverter>>::toJSI(runtime, arg.phoneNumbers)); - obj.setProperty(runtime, "emailAddresses", JSIConverter>>::toJSI(runtime, arg.emailAddresses)); - obj.setProperty(runtime, "imageData", JSIConverter>::toJSI(runtime, arg.imageData)); - obj.setProperty(runtime, "thumbnailImageData", JSIConverter>::toJSI(runtime, arg.thumbnailImageData)); - return obj; - } - static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { - if (!value.isObject()) { - return false; - } - jsi::Object obj = value.getObject(runtime); - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "firstName"))) return false; - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "lastName"))) return false; - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "middleName"))) return false; - if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, "phoneNumbers"))) return false; - if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, "emailAddresses"))) return false; - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "imageData"))) return false; - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "thumbnailImageData"))) return false; - return true; - } - }; - -} // namespace margelo::nitro diff --git a/modules/ContactsNitroModule/nitrogen/generated/shared/c++/ContactFields.hpp b/modules/ContactsNitroModule/nitrogen/generated/shared/c++/ContactFields.hpp deleted file mode 100644 index c3e8c115465e..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/shared/c++/ContactFields.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/// -/// ContactFields.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - -namespace margelo::nitro::contacts { - - /** - * An enum which can be represented as a JavaScript union (ContactFields). - */ - enum class ContactFields { - FIRST_NAME SWIFT_NAME(firstName) = 0, - LAST_NAME SWIFT_NAME(lastName) = 1, - MIDDLE_NAME SWIFT_NAME(middleName) = 2, - PHONE_NUMBERS SWIFT_NAME(phoneNumbers) = 3, - EMAIL_ADDRESSES SWIFT_NAME(emailAddresses) = 4, - IMAGE_DATA SWIFT_NAME(imageData) = 5, - THUMBNAIL_IMAGE_DATA SWIFT_NAME(thumbnailImageData) = 6, - GIVEN_NAME_KEY SWIFT_NAME(givenNameKey) = 7, - } CLOSED_ENUM; - -} // namespace margelo::nitro::contacts - -namespace margelo::nitro { - - using namespace margelo::nitro::contacts; - - // C++ ContactFields <> JS ContactFields (union) - template <> - struct JSIConverter { - static inline ContactFields fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - std::string unionValue = JSIConverter::fromJSI(runtime, arg); - switch (hashString(unionValue.c_str(), unionValue.size())) { - case hashString("FIRST_NAME"): return ContactFields::FIRST_NAME; - case hashString("LAST_NAME"): return ContactFields::LAST_NAME; - case hashString("MIDDLE_NAME"): return ContactFields::MIDDLE_NAME; - case hashString("PHONE_NUMBERS"): return ContactFields::PHONE_NUMBERS; - case hashString("EMAIL_ADDRESSES"): return ContactFields::EMAIL_ADDRESSES; - case hashString("IMAGE_DATA"): return ContactFields::IMAGE_DATA; - case hashString("THUMBNAIL_IMAGE_DATA"): return ContactFields::THUMBNAIL_IMAGE_DATA; - case hashString("GIVEN_NAME_KEY"): return ContactFields::GIVEN_NAME_KEY; - default: [[unlikely]] - throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum ContactFields - invalid value!"); - } - } - static inline jsi::Value toJSI(jsi::Runtime& runtime, ContactFields arg) { - switch (arg) { - case ContactFields::FIRST_NAME: return JSIConverter::toJSI(runtime, "FIRST_NAME"); - case ContactFields::LAST_NAME: return JSIConverter::toJSI(runtime, "LAST_NAME"); - case ContactFields::MIDDLE_NAME: return JSIConverter::toJSI(runtime, "MIDDLE_NAME"); - case ContactFields::PHONE_NUMBERS: return JSIConverter::toJSI(runtime, "PHONE_NUMBERS"); - case ContactFields::EMAIL_ADDRESSES: return JSIConverter::toJSI(runtime, "EMAIL_ADDRESSES"); - case ContactFields::IMAGE_DATA: return JSIConverter::toJSI(runtime, "IMAGE_DATA"); - case ContactFields::THUMBNAIL_IMAGE_DATA: return JSIConverter::toJSI(runtime, "THUMBNAIL_IMAGE_DATA"); - case ContactFields::GIVEN_NAME_KEY: return JSIConverter::toJSI(runtime, "GIVEN_NAME_KEY"); - default: [[unlikely]] - throw std::invalid_argument("Cannot convert ContactFields to JS - invalid value: " - + std::to_string(static_cast(arg)) + "!"); - } - } - static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { - if (!value.isString()) { - return false; - } - std::string unionValue = JSIConverter::fromJSI(runtime, value); - switch (hashString(unionValue.c_str(), unionValue.size())) { - case hashString("FIRST_NAME"): - case hashString("LAST_NAME"): - case hashString("MIDDLE_NAME"): - case hashString("PHONE_NUMBERS"): - case hashString("EMAIL_ADDRESSES"): - case hashString("IMAGE_DATA"): - case hashString("THUMBNAIL_IMAGE_DATA"): - case hashString("GIVEN_NAME_KEY"): - return true; - default: - return false; - } - } - }; - -} // namespace margelo::nitro diff --git a/modules/ContactsNitroModule/nitrogen/generated/shared/c++/HybridContactsModuleSpec.cpp b/modules/ContactsNitroModule/nitrogen/generated/shared/c++/HybridContactsModuleSpec.cpp deleted file mode 100644 index eba17de8d910..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/shared/c++/HybridContactsModuleSpec.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/// -/// HybridContactsModuleSpec.cpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#include "HybridContactsModuleSpec.hpp" - -namespace margelo::nitro::contacts { - - void HybridContactsModuleSpec::loadHybridMethods() { - // load base methods/properties - HybridObject::loadHybridMethods(); - // load custom methods/properties - registerHybrids(this, [](Prototype& prototype) { - prototype.registerHybridMethod("getAll", &HybridContactsModuleSpec::getAll); - }); - } - -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/shared/c++/HybridContactsModuleSpec.hpp b/modules/ContactsNitroModule/nitrogen/generated/shared/c++/HybridContactsModuleSpec.hpp deleted file mode 100644 index 6c298086f493..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/shared/c++/HybridContactsModuleSpec.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/// -/// HybridContactsModuleSpec.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - -// Forward declaration of `Contact` to properly resolve imports. -namespace margelo::nitro::contacts { struct Contact; } -// Forward declaration of `ContactFields` to properly resolve imports. -namespace margelo::nitro::contacts { enum class ContactFields; } - -#include -#include -#include "Contact.hpp" -#include "ContactFields.hpp" - -namespace margelo::nitro::contacts { - - using namespace margelo::nitro; - - /** - * An abstract base class for `ContactsModule` - * Inherit this class to create instances of `HybridContactsModuleSpec` in C++. - * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. - * @example - * ```cpp - * class HybridContactsModule: public HybridContactsModuleSpec { - * public: - * HybridContactsModule(...): HybridObject(TAG) { ... } - * // ... - * }; - * ``` - */ - class HybridContactsModuleSpec: public virtual HybridObject { - public: - // Constructor - explicit HybridContactsModuleSpec(): HybridObject(TAG) { } - - // Destructor - virtual ~HybridContactsModuleSpec() { } - - public: - // Properties - - - public: - // Methods - virtual std::shared_ptr>> getAll(const std::vector& keys) = 0; - - protected: - // Hybrid Setup - void loadHybridMethods() override; - - protected: - // Tag for logging - static constexpr auto TAG = "ContactsModule"; - }; - -} // namespace margelo::nitro::contacts diff --git a/modules/ContactsNitroModule/nitrogen/generated/shared/c++/StringHolder.hpp b/modules/ContactsNitroModule/nitrogen/generated/shared/c++/StringHolder.hpp deleted file mode 100644 index 1a666ed1faca..000000000000 --- a/modules/ContactsNitroModule/nitrogen/generated/shared/c++/StringHolder.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/// -/// StringHolder.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © 2024 Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - - - -#include - -namespace margelo::nitro::contacts { - - /** - * A struct which can be represented as a JavaScript object (StringHolder). - */ - struct StringHolder { - public: - std::string value SWIFT_PRIVATE; - - public: - explicit StringHolder(std::string value): value(value) {} - }; - -} // namespace margelo::nitro::contacts - -namespace margelo::nitro { - - using namespace margelo::nitro::contacts; - - // C++ StringHolder <> JS StringHolder (object) - template <> - struct JSIConverter { - static inline StringHolder fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - jsi::Object obj = arg.asObject(runtime); - return StringHolder( - JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "value")) - ); - } - static inline jsi::Value toJSI(jsi::Runtime& runtime, const StringHolder& arg) { - jsi::Object obj(runtime); - obj.setProperty(runtime, "value", JSIConverter::toJSI(runtime, arg.value)); - return obj; - } - static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { - if (!value.isObject()) { - return false; - } - jsi::Object obj = value.getObject(runtime); - if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "value"))) return false; - return true; - } - }; - -} // namespace margelo::nitro diff --git a/modules/ContactsNitroModule/package.json b/modules/ContactsNitroModule/package.json deleted file mode 100644 index 6f70882a2193..000000000000 --- a/modules/ContactsNitroModule/package.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "name": "contacts-nitro-module", - "version": "0.0.1", - "main": "src/index", - "react-native": "src/index", - "description": "React Native Contacts Module with Nitro optimization", - "source": "src/index", - "files": [ - "src", - "react-native.config.js", - "lib", - "android/build.gradle", - "android/gradle.properties", - "android/CMakeLists.txt", - "android/src", - "ios/**/*.h", - "ios/**/*.m", - "ios/**/*.mm", - "ios/**/*.cpp", - "ios/**/*.swift", - "app.plugin.js", - "*.podspec", - "README.md" - ], - "scripts": { - "postinstall": "tsc || exit 0;", - "typecheck": "tsc --noEmit", - "clean": "del-cli android/build node_modules/**/android/build lib", - "lint": "eslint \"**/*.{js,ts,tsx}\" --fix", - "lint-ci": "eslint \"**/*.{js,ts,tsx}\" -f @jamesacarr/github-actions", - "typescript": "tsc --noEmit false", - "specs-debug": "bun run --filter=\"**\" typescript && bun nitro-codegen --logLevel=\"debug\"", - "specs": "bun nitro-codegen" - }, - "keywords": [ - "react-native", - "nitro" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/mrousavy/nitro.git" - }, - "author": "Marc Rousavy (https://github.com/mrousavy)", - "license": "MIT", - "bugs": { - "url": "https://github.com/mrousavy/nitro/issues" - }, - "homepage": "https://github.com/mrousavy/nitro#readme", - "publishConfig": { - "registry": "https://registry.npmjs.org/" - }, - "devDependencies": { - "@react-native/eslint-config": "^0.75.2", - "@types/jest": "^29.5.12", - "@types/react": "^18.3.4", - "del-cli": "^5.1.0", - "eslint": "^8.57.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.2.1", - "nitro-codegen": "0.18.1", - "prettier": "^3.3.3", - "react": "^18.3.1", - "react-native": "0.75.2", - "react-native-nitro-modules": "*", - "typescript": "^5.5.4" - }, - "peerDependencies": { - "react": "*", - "react-native": "*" - }, - "eslintConfig": { - "root": true, - "extends": [ - "@react-native", - "prettier" - ], - "plugins": ["prettier"], - "rules": { - "prettier/prettier": [ - "warn", - { - "quoteProps": "consistent", - "singleQuote": true, - "tabWidth": 2, - "trailingComma": "es5", - "useTabs": false - } - ] - } - }, - "eslintIgnore": [ - "node_modules/", - "lib/" - ], - "prettier": { - "quoteProps": "consistent", - "singleQuote": true, - "tabWidth": 2, - "trailingComma": "es5", - "useTabs": false, - "semi": false - } -} diff --git a/modules/ContactsNitroModule/src/ContactsModule.nitro.ts b/modules/ContactsNitroModule/src/ContactsModule.nitro.ts deleted file mode 100644 index 8df839f550e8..000000000000 --- a/modules/ContactsNitroModule/src/ContactsModule.nitro.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { HybridObject } from 'react-native-nitro-modules' - -interface StringHolder { - value: string -} - -export interface Contact { - firstName?: string - lastName?: string - middleName?: string - phoneNumbers?: StringHolder[] - emailAddresses?: StringHolder[] - imageData?: string - thumbnailImageData?: string -} -export type ContactFields = - | 'FIRST_NAME' - | 'LAST_NAME' - | 'MIDDLE_NAME' - | 'PHONE_NUMBERS' - | 'EMAIL_ADDRESSES' - | 'IMAGE_DATA' - | 'THUMBNAIL_IMAGE_DATA' - | 'GIVEN_NAME_KEY' - -export interface ContactsModule - extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> { - getAll(keys: ContactFields[]): Promise -} diff --git a/modules/ContactsNitroModule/src/index.ts b/modules/ContactsNitroModule/src/index.ts deleted file mode 100644 index acc7c7c1fb76..000000000000 --- a/modules/ContactsNitroModule/src/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { ContactsModule } from './ContactsModule.nitro' -import type { Contact } from './ContactsModule.nitro' -import { NitroModules } from 'react-native-nitro-modules' - -export const ContactsNitroModule = - NitroModules.createHybridObject('ContactsModule') - -export type { Contact } diff --git a/modules/ContactsNitroModule/tsconfig.json b/modules/ContactsNitroModule/tsconfig.json deleted file mode 100644 index e30dc47ac169..000000000000 --- a/modules/ContactsNitroModule/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "include": ["src"], - "compilerOptions": { - "composite": true, - "outDir": "lib", - "rootDir": "src", - "allowUnreachableCode": false, - "allowUnusedLabels": false, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "jsx": "react", - "lib": ["esnext"], - "module": "esnext", - "moduleResolution": "node", - "noEmit": false, - "noFallthroughCasesInSwitch": true, - "noImplicitReturns": true, - "noImplicitUseStrict": false, - "noStrictGenericChecks": false, - "noUncheckedIndexedAccess": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "esnext", - "verbatimModuleSyntax": true - } -} diff --git a/package-lock.json b/package-lock.json index 9cb175d5897a..0ded98fa58eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,6 @@ "version": "9.0.77-5", "hasInstallScript": true, "license": "MIT", - "workspaces": [ - "modules/ContactsNitroModule" - ], "dependencies": { "@dotlottie/react-player": "^1.6.3", "@expensify/react-native-live-markdown": "0.1.209", @@ -49,7 +46,6 @@ "awesome-phonenumber": "^5.4.0", "babel-polyfill": "^6.26.0", "canvas-size": "^1.2.6", - "contacts-nitro-module": "./modules/ContactsNitroModule", "core-js": "^3.32.0", "date-fns": "^4.1.0", "date-fns-tz": "^3.2.0", @@ -99,7 +95,6 @@ "react-native-launch-arguments": "^4.0.2", "react-native-localize": "^2.2.6", "react-native-modal": "^13.0.0", - "react-native-nitro-modules": "^0.18.1", "react-native-onyx": "2.0.86", "react-native-pager-view": "6.5.1", "react-native-pdf": "6.7.3", @@ -280,114 +275,10 @@ "webpack-dev-server": "^5.0.4", "webpack-merge": "^5.8.0", "xlsx": "file:vendor/xlsx-0.20.3.tgz" - } - }, - "modules/ContactsNitroModule": { - "name": "contacts-nitro-module", - "version": "0.0.1", - "hasInstallScript": true, - "license": "MIT", - "devDependencies": { - "@react-native/eslint-config": "^0.75.2", - "@types/jest": "^29.5.12", - "@types/react": "^18.3.4", - "del-cli": "^5.1.0", - "eslint": "^8.57.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.2.1", - "nitro-codegen": "0.18.1", - "prettier": "^3.3.3", - "react": "^18.3.1", - "react-native": "0.75.2", - "react-native-nitro-modules": "*", - "typescript": "^5.5.4" - }, - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, - "modules/ContactsNitroModule/node_modules/@types/jest": { - "version": "29.5.14", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", - "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "modules/ContactsNitroModule/node_modules/@types/react": { - "version": "18.3.17", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.17.tgz", - "integrity": "sha512-opAQ5no6LqJNo9TqnxBKsgnkIYHozW9KSTlFVoSUJYh1Fl/sswkEoqIugRSm7tbh6pABtYjGAjW+GOS23j8qbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "modules/ContactsNitroModule/node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "modules/ContactsNitroModule/node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "modules/ContactsNitroModule/node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" + "node": "20.18.0", + "npm": "10.8.2" } }, "node_modules/@actions/core": { @@ -7308,19 +7199,6 @@ "node": ">=14" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz", @@ -9431,83 +9309,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@react-native/eslint-config": { - "version": "0.75.4", - "resolved": "https://registry.npmjs.org/@react-native/eslint-config/-/eslint-config-0.75.4.tgz", - "integrity": "sha512-3KBHYwp4HnBdaCFx9KDPvQY+sGrv5fHX2qDkXGKmN3uYBz+zfnMQXTiht6OuBbWULUF0y0o8m+uH1yYAn/V9mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.20.0", - "@babel/eslint-parser": "^7.20.0", - "@react-native/eslint-plugin": "0.75.4", - "@typescript-eslint/eslint-plugin": "^7.1.1", - "@typescript-eslint/parser": "^7.1.1", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-eslint-comments": "^3.2.0", - "eslint-plugin-ft-flow": "^2.0.1", - "eslint-plugin-jest": "^27.9.0", - "eslint-plugin-react": "^7.30.1", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-native": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "eslint": ">=8", - "prettier": ">=2" - } - }, - "node_modules/@react-native/eslint-config/node_modules/eslint-config-prettier": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", - "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", - "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/@react-native/eslint-config/node_modules/eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/utils": "^5.10.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0", - "jest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, - "node_modules/@react-native/eslint-plugin": { - "version": "0.75.4", - "resolved": "https://registry.npmjs.org/@react-native/eslint-plugin/-/eslint-plugin-0.75.4.tgz", - "integrity": "sha512-1kEZzC8UKi3baHnH7tBVCNpF4aoAmT7g7hEa5/rtZ+Z7vcpaxeY6wjNYt3j02Z9n310yX0NKDJox30CqvzEvsg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/@react-native/gradle-plugin": { "version": "0.75.2", "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.75.2.tgz", @@ -13304,44 +13105,6 @@ "node": ">=10.13.0" } }, - "node_modules/@ts-morph/common": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.25.0.tgz", - "integrity": "sha512-kMnZz+vGGHi4GoHnLmMhGNjm44kGtKUXGnOvrKmMwAuvNjM/PgKVGfUnL7IDvK7Jb2QQ82jq3Zmp04Gy+r3Dkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimatch": "^9.0.4", - "path-browserify": "^1.0.1", - "tinyglobby": "^0.2.9" - } - }, - "node_modules/@ts-morph/common/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@ts-morph/common/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "dev": true, @@ -13862,13 +13625,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/ms": { "version": "0.7.34", "dev": true, @@ -13910,13 +13666,6 @@ "@types/node": "*" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/parse-json": { "version": "4.0.0", "dev": true, @@ -15749,16 +15498,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/asap": { "version": "2.0.6", "license": "MIT" @@ -17553,38 +17292,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/camelize": { "version": "1.0.1", "license": "MIT", @@ -17948,13 +17655,6 @@ "node": ">= 0.12.0" } }, - "node_modules/code-block-writer": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", - "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", - "dev": true, - "license": "MIT" - }, "node_modules/collect-v8-coverage": { "version": "1.0.1", "dev": true, @@ -18446,10 +18146,6 @@ "dev": true, "license": "MIT" }, - "node_modules/contacts-nitro-module": { - "resolved": "modules/ContactsNitroModule", - "link": true - }, "node_modules/content-disposition": { "version": "0.5.4", "dev": true, @@ -19166,56 +18862,6 @@ } } }, - "node_modules/decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/decimal.js": { "version": "10.4.3", "dev": true, @@ -19408,184 +19054,6 @@ "node": ">=6" } }, - "node_modules/del-cli": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/del-cli/-/del-cli-5.1.0.tgz", - "integrity": "sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "del": "^7.1.0", - "meow": "^10.1.3" - }, - "bin": { - "del": "cli.js", - "del-cli": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli/node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli/node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli/node_modules/del": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/del/-/del-7.1.0.tgz", - "integrity": "sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "globby": "^13.1.2", - "graceful-fs": "^4.2.10", - "is-glob": "^4.0.3", - "is-path-cwd": "^3.0.0", - "is-path-inside": "^4.0.0", - "p-map": "^5.5.0", - "rimraf": "^3.0.2", - "slash": "^4.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli/node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli/node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli/node_modules/is-path-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-3.0.0.tgz", - "integrity": "sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli/node_modules/is-path-inside": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", - "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli/node_modules/p-map": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", - "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/del/node_modules/array-union": { "version": "1.0.2", "dev": true, @@ -23928,16 +23396,6 @@ "node": ">=0.10.0" } }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/has": { "version": "1.0.3", "dev": true, @@ -25336,16 +24794,6 @@ "node": ">=6" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-plain-object": { "version": "5.0.0", "dev": true, @@ -28979,19 +28427,6 @@ "tmpl": "1.0.5" } }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/map-or-similar": { "version": "1.5.0", "dev": true, @@ -29198,92 +28633,6 @@ "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", "integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==" }, - "node_modules/meow": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", - "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimist": "^1.2.2", - "camelcase-keys": "^7.0.0", - "decamelize": "^5.0.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.2", - "read-pkg-up": "^8.0.0", - "redent": "^4.0.0", - "trim-newlines": "^4.0.2", - "type-fest": "^1.2.2", - "yargs-parser": "^20.2.9" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/redent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", - "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", - "dev": true, - "license": "MIT", - "dependencies": { - "indent-string": "^5.0.0", - "strip-indent": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "min-indent": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -29879,21 +29228,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/minipass": { "version": "3.3.6", "license": "ISC", @@ -30133,37 +29467,6 @@ "version": "1.0.5", "license": "MIT" }, - "node_modules/nitro-codegen": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/nitro-codegen/-/nitro-codegen-0.18.1.tgz", - "integrity": "sha512-gDOHIIFFY89Ibo/Q8Dlzx4Rk9fCaGnby4Er5Dh1xV4J5hMqTfqo2VjG+RxScdUTYy/SKOc0UsB2faQybs5+GDw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "react-native-nitro-modules": "^0.18.1", - "ts-morph": "^24.0.0", - "yargs": "^17.7.2", - "zod": "^3.23.8" - }, - "bin": { - "nitro-codegen": "lib/index.js" - } - }, - "node_modules/nitro-codegen/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/no-case": { "version": "3.0.4", "dev": true, @@ -30397,22 +29700,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "license": "MIT", @@ -32869,17 +32156,6 @@ "react-native": ">=0.65.0" } }, - "node_modules/react-native-nitro-modules": { - "version": "0.18.2", - "resolved": "https://registry.npmjs.org/react-native-nitro-modules/-/react-native-nitro-modules-0.18.2.tgz", - "integrity": "sha512-eHsq1cRfm/Bz1Nq7KctTqxAqhzVSNo0WGX281xARZh+vOq8633Qxn1NHRZ5/Rno2Bla6HOXlUW6RoW0wKM/7kg==", - "hasInstallScript": true, - "license": "MIT", - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, "node_modules/react-native-onyx": { "version": "2.0.86", "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-2.0.86.tgz", @@ -33681,69 +32957,6 @@ "node": ">=6" } }, - "node_modules/read-pkg": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", - "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^3.0.2", - "parse-json": "^5.2.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", - "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^5.0.0", - "read-pkg": "^6.0.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/readable-stream": { "version": "2.3.8", "license": "MIT", @@ -35143,17 +34356,6 @@ "version": "0.0.2", "dev": true }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, "node_modules/spdx-exceptions": { "version": "2.3.0", "dev": true, @@ -35866,23 +35068,6 @@ "dev": true, "license": "MIT" }, - "node_modules/synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/tabbable": { "version": "6.2.0", "license": "MIT" @@ -36316,48 +35501,6 @@ "dev": true, "license": "MIT" }, - "node_modules/tinyglobby": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", - "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.4.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", - "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/tinyqueue": { "version": "2.0.3", "license": "ISC" @@ -36473,19 +35616,6 @@ "tree-kill": "cli.js" } }, - "node_modules/trim-newlines": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", - "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/trim-right": { "version": "1.0.1", "license": "MIT", @@ -36590,15 +35720,12 @@ "node": ">=10" } }, - "node_modules/ts-morph": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-24.0.0.tgz", - "integrity": "sha512-2OAOg/Ob5yx9Et7ZX4CvTCc0UFoZHwLEJ+dpDPSUi5TgwwlTlX47w+iFRrEwzUZwYACjq83cgjS/Da50Ga37uw==", + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", "dev": true, - "license": "MIT", - "dependencies": { - "@ts-morph/common": "~0.25.0", - "code-block-writer": "^13.0.3" + "license": "ISC", + "engines": { + "node": ">=12" } }, "node_modules/ts-node": { @@ -37374,17 +36501,6 @@ "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "node_modules/validate-npm-package-name": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", @@ -38377,20 +37493,18 @@ "node": ">=12" } }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "node_modules/yargs/node_modules/y18n": { + "version": "5.0.8", "license": "ISC", "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/yargs/node_modules/y18n": { - "version": "5.0.8", + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yauzl": { diff --git a/package.json b/package.json index 1ff9da459e53..0896f83e10d0 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "perf-test": "NODE_OPTIONS=--experimental-vm-modules npx reassure", "typecheck": "NODE_OPTIONS=--max_old_space_size=8192 tsc", "lint": "NODE_OPTIONS=--max_old_space_size=8192 eslint . --max-warnings=0 --cache --cache-location=node_modules/.cache/eslint", - "lint-changed": "NODE_OPTIONS=--max_old_space_size=8192 eslint --max-warnings=0 --config ./.eslintrc.changed.js $(git diff --diff-filter=AM --name-only origin/main HEAD -- \"*.ts\" \"*.tsx\" \":!modules/**\")", + "lint-changed": "NODE_OPTIONS=--max_old_space_size=8192 eslint --max-warnings=0 --config ./.eslintrc.changed.js $(git diff --diff-filter=AM --name-only origin/main HEAD -- \"*.ts\" \"*.tsx\")", "lint-watch": "npx eslint-watch --watch --changed", "shellcheck": "./scripts/shellCheck.sh", "prettier": "prettier --write .", @@ -111,7 +111,6 @@ "awesome-phonenumber": "^5.4.0", "babel-polyfill": "^6.26.0", "canvas-size": "^1.2.6", - "contacts-nitro-module": "./modules/ContactsNitroModule", "core-js": "^3.32.0", "date-fns": "^4.1.0", "date-fns-tz": "^3.2.0", @@ -162,7 +161,6 @@ "react-native-localize": "^2.2.6", "react-native-modal": "^13.0.0", "react-native-onyx": "2.0.86", - "react-native-nitro-modules": "^0.18.1", "react-native-pager-view": "6.5.1", "react-native-pdf": "6.7.3", "react-native-performance": "^5.1.0", @@ -378,7 +376,17 @@ ] } }, - "workspaces": [ - "modules/ContactsNitroModule" - ] + "electronmon": { + "patterns": [ + "!src/**", + "!ios/**", + "!android/**", + "!tests/**", + "*.test.*" + ] + }, + "engines": { + "node": "20.18.0", + "npm": "10.8.2" + } } diff --git a/react-native.config.js b/react-native.config.js index ffbc8f5c65cb..773375378acd 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -1,5 +1,3 @@ -const path = require('path'); -const pak = require('./modules/ContactsNitroModule/package.json'); const iosSourceDir = process.env.PROJECT_ROOT_PATH ? process.env.PROJECT_ROOT_PATH + 'ios' : 'ios'; const androidSourceDir = process.env.PROJECT_ROOT_PATH ? process.env.PROJECT_ROOT_PATH + 'android' : 'android'; @@ -9,9 +7,4 @@ module.exports = { android: {sourceDir: androidSourceDir}, }, assets: ['./assets/fonts/native'], - dependencies: { - [pak.name]: { - root: path.join(__dirname, 'modules', 'ContactsNitroModule'), - }, - }, }; diff --git a/src/CONST.ts b/src/CONST.ts index 53197d41b85e..e317c19d96d2 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6435,14 +6435,6 @@ const CONST = { }, }, - DEVICE_CONTACT: { - FIRST_NAME: 'FIRST_NAME', - LAST_NAME: 'LAST_NAME', - PHONE_NUMBERS: 'PHONE_NUMBERS', - EMAIL_ADDRESSES: 'EMAIL_ADDRESSES', - IMAGE_DATA: 'IMAGE_DATA', - }, - HYBRID_APP: { REORDERING_REACT_NATIVE_ACTIVITY_TO_FRONT: 'reorderingReactNativeActivityToFront', }, diff --git a/src/components/ContactPermissionModal/index.native.tsx b/src/components/ContactPermissionModal/index.native.tsx deleted file mode 100644 index 825c8bc4afbe..000000000000 --- a/src/components/ContactPermissionModal/index.native.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import React, {useEffect, useState} from 'react'; -import {InteractionManager} from 'react-native'; -import {RESULTS} from 'react-native-permissions'; -import ConfirmModal from '@components/ConfirmModal'; -import * as Illustrations from '@components/Icon/Illustrations'; -import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {getContactPermission} from '@libs/ContactPermission'; -import type {ContactPermissionModalProps} from './types'; - -function ContactPermissionModal({startPermissionFlow, resetPermissionFlow, onDeny, onGrant}: ContactPermissionModalProps) { - const [isModalVisible, setIsModalVisible] = useState(false); - - const styles = useThemeStyles(); - const {translate} = useLocalize(); - - useEffect(() => { - if (!startPermissionFlow) { - return; - } - getContactPermission().then((status) => { - if (status === RESULTS.GRANTED || status === RESULTS.LIMITED) { - return onGrant(); - } - if (status === RESULTS.BLOCKED) { - return; - } - setIsModalVisible(true); - }); - // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- We only want to run this effect when startPermissionFlow changes - }, [startPermissionFlow]); - - const handleGrantPermission = () => { - setIsModalVisible(false); - InteractionManager.runAfterInteractions(onGrant); - }; - - const handleDenyPermission = () => { - onDeny(RESULTS.DENIED); - setIsModalVisible(false); - }; - - const handleCloseModal = () => { - setIsModalVisible(false); - resetPermissionFlow(); - }; - - return ( - - ); -} - -ContactPermissionModal.displayName = 'ContactPermissionModal'; - -export default ContactPermissionModal; diff --git a/src/components/ContactPermissionModal/index.tsx b/src/components/ContactPermissionModal/index.tsx deleted file mode 100644 index 3f7e25bac590..000000000000 --- a/src/components/ContactPermissionModal/index.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import type {ContactPermissionModalProps} from './types'; - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function ContactPermissionModal(props: ContactPermissionModalProps) { - return null; -} - -ContactPermissionModal.displayName = 'ContactPermissionModal'; - -export default ContactPermissionModal; diff --git a/src/components/ContactPermissionModal/types.ts b/src/components/ContactPermissionModal/types.ts deleted file mode 100644 index 5c831410656f..000000000000 --- a/src/components/ContactPermissionModal/types.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type {PermissionStatus} from 'react-native-permissions'; - -type ContactPermissionModalProps = { - /** A callback to call when the permission has been granted */ - onGrant: () => void; - - /** A callback to call when the permission has been denied */ - onDeny: (permission: PermissionStatus) => void; - - /** Should start the permission flow? */ - startPermissionFlow: boolean; - - /** Reset the permission flow */ - resetPermissionFlow: () => void; -}; - -export default {}; - -export type {ContactPermissionModalProps}; diff --git a/src/languages/en.ts b/src/languages/en.ts index 9818c8aec472..80a75f9b9528 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -502,13 +502,6 @@ const translations = { allowPermission: 'allow location access in settings', tryAgain: 'and try again.', }, - contact: { - importContacts: 'Import contacts', - importContactsTitle: 'Import your contacts', - importContactsText: 'Import contacts from your phone so your favorite people are always a tap away.', - importContactsExplanation: 'so your favorite people are always a tap away.', - importContactsNativeText: 'Just one more step! Give us the green light to import your contacts.', - }, anonymousReportFooter: { logoTagline: 'Join the discussion.', }, diff --git a/src/languages/es.ts b/src/languages/es.ts index 4af85c4faa73..54d80365e0fd 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -497,13 +497,6 @@ const translations = { allowPermission: 'habilita el permiso de ubicación en la configuración', tryAgain: 'e inténtalo de nuevo.', }, - contact: { - importContacts: 'Importar contactos', - importContactsTitle: 'Importa tus contactos', - importContactsText: 'Importa contactos desde tu teléfono para que tus personas favoritas siempre estén a un toque de distancia.', - importContactsExplanation: 'para que tus personas favoritas estén siempre a un toque de distancia.', - importContactsNativeText: '¡Solo un paso más! Danos luz verde para importar tus contactos.', - }, anonymousReportFooter: { logoTagline: 'Únete a la discusión.', }, diff --git a/src/libs/ContactImport/index.native.tsx b/src/libs/ContactImport/index.native.tsx deleted file mode 100644 index 564bbba6805f..000000000000 --- a/src/libs/ContactImport/index.native.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import {ContactsNitroModule} from 'contacts-nitro-module'; -import type {Contact} from 'contacts-nitro-module'; -import {RESULTS} from 'react-native-permissions'; -import type {PermissionStatus} from 'react-native-permissions'; -import {requestContactPermission} from '@libs/ContactPermission'; -import CONST from '@src/CONST'; -import type {ContactImportResult} from './types'; - -function contactImport(): Promise { - let permissionStatus: PermissionStatus = RESULTS.UNAVAILABLE; - - return requestContactPermission() - .then((response: PermissionStatus) => { - permissionStatus = response; - if (response === RESULTS.GRANTED) { - return ContactsNitroModule.getAll([ - CONST.DEVICE_CONTACT.FIRST_NAME, - CONST.DEVICE_CONTACT.LAST_NAME, - CONST.DEVICE_CONTACT.PHONE_NUMBERS, - CONST.DEVICE_CONTACT.EMAIL_ADDRESSES, - CONST.DEVICE_CONTACT.IMAGE_DATA, - ]); - } - return [] as Contact[]; - }) - .then((deviceContacts) => ({ - contactList: Array.isArray(deviceContacts) ? deviceContacts : [], - permissionStatus, - })); -} - -export default contactImport; diff --git a/src/libs/ContactImport/index.tsx b/src/libs/ContactImport/index.tsx deleted file mode 100644 index b3fe3dc27868..000000000000 --- a/src/libs/ContactImport/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import {RESULTS} from 'react-native-permissions'; -import type {ContactImportResult} from './types'; - -const contactImport = (): Promise => { - return Promise.resolve({ - contactList: [], - permissionStatus: RESULTS.UNAVAILABLE, - }); -}; - -export default contactImport; diff --git a/src/libs/ContactImport/types.ts b/src/libs/ContactImport/types.ts deleted file mode 100644 index 8247bdf8e2ec..000000000000 --- a/src/libs/ContactImport/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type {PermissionStatus} from 'react-native-permissions'; - -type StringHolder = { - value: string; -}; - -type ContactImportResult = { - contactList: DeviceContact[] | []; - permissionStatus: PermissionStatus; -}; - -type DeviceContact = { - firstName?: string; - lastName?: string; - emailAddresses?: StringHolder[]; - phoneNumbers?: Array<{value: string}>; - imageData?: string; -}; - -export type {StringHolder, ContactImportResult, DeviceContact}; diff --git a/src/libs/ContactPermission/index.android.ts b/src/libs/ContactPermission/index.android.ts deleted file mode 100644 index 8ef0eace7135..000000000000 --- a/src/libs/ContactPermission/index.android.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {check, PERMISSIONS, request} from 'react-native-permissions'; - -function requestContactPermission() { - return request(PERMISSIONS.ANDROID.READ_CONTACTS); -} - -function getContactPermission() { - return check(PERMISSIONS.ANDROID.READ_CONTACTS); -} - -export {requestContactPermission, getContactPermission}; diff --git a/src/libs/ContactPermission/index.ios.ts b/src/libs/ContactPermission/index.ios.ts deleted file mode 100644 index 590373c9bd7d..000000000000 --- a/src/libs/ContactPermission/index.ios.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {check, PERMISSIONS, request} from 'react-native-permissions'; - -function requestContactPermission() { - return request(PERMISSIONS.IOS.CONTACTS); -} - -function getContactPermission() { - return check(PERMISSIONS.IOS.CONTACTS); -} - -export {requestContactPermission, getContactPermission}; diff --git a/src/libs/ContactPermission/index.ts b/src/libs/ContactPermission/index.ts deleted file mode 100644 index 0216a5022dda..000000000000 --- a/src/libs/ContactPermission/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {RESULTS} from 'react-native-permissions'; -import type {PermissionStatus} from 'react-native-permissions'; - -function requestContactPermission(): Promise { - return new Promise((resolve) => { - resolve(RESULTS.GRANTED); - }); -} - -function getContactPermission(): Promise { - return new Promise((resolve) => { - resolve(RESULTS.GRANTED); - }); -} - -export {requestContactPermission, getContactPermission}; diff --git a/src/libs/ContactUtils.ts b/src/libs/ContactUtils.ts deleted file mode 100644 index 5769e6cde2a4..000000000000 --- a/src/libs/ContactUtils.ts +++ /dev/null @@ -1,50 +0,0 @@ -import CONST from '@src/CONST'; -import type {PersonalDetails} from '@src/types/onyx'; -import type {DeviceContact, StringHolder} from './ContactImport/types'; -import * as OptionsListUtils from './OptionsListUtils'; -import {getAvatarForContact} from './RandomAvatarUtils'; - -function sortEmailObjects(emails?: StringHolder[]): string[] { - if (!emails?.length) { - return []; - } - - const expensifyDomain = CONST.EMAIL.EXPENSIFY_EMAIL_DOMAIN.toLowerCase(); - - return emails - .filter((email) => email?.value) - .map((email) => email.value) - .sort((a, b) => { - const isExpensifyA = a.toLowerCase().includes(expensifyDomain); - const isExpensifyB = b.toLowerCase().includes(expensifyDomain); - - // Prioritize Expensify emails, then sort alphabetically - return isExpensifyA !== isExpensifyB ? Number(isExpensifyB) - Number(isExpensifyA) : a.localeCompare(b); - }); -} - -const getContacts = (deviceContacts: DeviceContact[] | []): Array> => { - return deviceContacts - .map((contact) => { - const email = sortEmailObjects(contact?.emailAddresses ?? [])?.at(0) ?? ''; - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const avatarSource = (contact?.imageData || getAvatarForContact(`${contact?.firstName}${email}${contact?.lastName}`)) ?? ''; - const phoneNumber = contact.phoneNumbers?.[0]?.value ?? ''; - const firstName = contact?.firstName ?? ''; - const lastName = contact?.lastName ?? ''; - - return OptionsListUtils.getUserToInviteContactOption({ - selectedOptions: [], - optionsToExclude: [], - searchValue: email || phoneNumber || firstName || '', - firstName, - lastName, - email, - phone: phoneNumber, - avatar: avatarSource, - }); - }) - .filter((contact): contact is OptionsListUtils.SearchOption => contact !== null); -}; - -export default getContacts; diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 35b7b6a023ce..16d5bb03860c 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -115,11 +115,6 @@ type GetUserToInviteConfig = { searchValue: string; optionsToExclude?: Array>; reportActions?: ReportActions; - firstName?: string; - lastName?: string; - email?: string; - phone?: string; - avatar?: UserUtils.AvatarSource; shouldAcceptName?: boolean; } & Pick; @@ -365,29 +360,25 @@ function getParticipantsOption(participant: ReportUtils.OptionData | Participant const detail = getPersonalDetailsForAccountIDs([participant.accountID ?? -1], personalDetails)[participant.accountID ?? -1]; // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const login = detail?.login || participant.login || ''; - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const displayName = participant?.displayName || LocalePhoneNumber.formatPhoneNumber(PersonalDetailsUtils.getDisplayNameOrDefault(detail, login || participant.text)); + const displayName = LocalePhoneNumber.formatPhoneNumber(PersonalDetailsUtils.getDisplayNameOrDefault(detail, login || participant.text)); return { keyForList: String(detail?.accountID), login, accountID: detail?.accountID ?? -1, text: displayName, - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - firstName: (detail?.firstName || ('firstName' in participant ? participant.firstName : '')) ?? '', - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - lastName: (detail?.lastName || ('lastName' in participant ? participant.lastName : '')) ?? '', + firstName: detail?.firstName ?? '', + lastName: detail?.lastName ?? '', alternateText: LocalePhoneNumber.formatPhoneNumber(login) || displayName, icons: [ { - source: ('avatar' in participant ? participant.avatar : detail?.avatar) ?? FallbackAvatar, + source: detail?.avatar ?? FallbackAvatar, name: login, type: CONST.ICON_TYPE_AVATAR, id: detail?.accountID, }, ], - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - phoneNumber: (detail?.phoneNumber || participant?.phoneNumber) ?? '', + phoneNumber: detail?.phoneNumber ?? '', selected: participant.selected, isSelected: participant.selected, searchText: participant.searchText ?? undefined, @@ -1101,101 +1092,6 @@ function getUserToInviteOption({ return userToInvite; } -function getUserToInviteContactOption({ - searchValue, - optionsToExclude = [], - selectedOptions = [], - firstName, - lastName, - email, - phone, - avatar, -}: GetUserToInviteConfig): SearchOption | null { - // If email is provided, use it as the primary identifier - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const effectiveSearchValue = email || searchValue; - - // Handle phone number parsing for either provided phone or searchValue - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const phoneToCheck = phone || searchValue; - const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(phoneToCheck))); - - const isCurrentUserLogin = isCurrentUser({login: effectiveSearchValue} as PersonalDetails); - const isInSelectedOption = selectedOptions.some((option) => 'login' in option && option.login === effectiveSearchValue); - - // Validate email (either provided email or searchValue) - const isValidEmail = Str.isValidEmail(effectiveSearchValue) && !Str.isDomainEmail(effectiveSearchValue) && !Str.endsWith(effectiveSearchValue, CONST.SMS.DOMAIN); - - const isValidPhoneNumber = parsedPhoneNumber.possible && Str.isValidE164Phone(LoginUtils.getPhoneNumberWithoutSpecialChars(parsedPhoneNumber.number?.input ?? '')); - - const isInOptionToExclude = - optionsToExclude.findIndex((optionToExclude) => 'login' in optionToExclude && optionToExclude.login === PhoneNumber.addSMSDomainIfPhoneNumber(effectiveSearchValue).toLowerCase()) !== - -1; - - if (!effectiveSearchValue || isCurrentUserLogin || isInSelectedOption || (!isValidEmail && !isValidPhoneNumber) || isInOptionToExclude) { - return null; - } - - // Generates an optimistic account ID for new users not yet saved in Onyx - const optimisticAccountID = UserUtils.generateAccountID(effectiveSearchValue); - - // Construct display name if firstName/lastName are provided - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const displayName = firstName && lastName ? `${firstName} ${lastName}` : firstName || lastName || effectiveSearchValue; - - // Create the base user details that will be used in both item and participantsList - const userDetails = { - accountID: optimisticAccountID, - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - avatar: avatar || FallbackAvatar, - firstName: firstName ?? '', - lastName: lastName ?? '', - displayName, - login: effectiveSearchValue, - pronouns: '', - phoneNumber: phone ?? '', - validated: true, - }; - - const userToInvite = { - item: userDetails, - text: displayName, - alternateText: displayName !== effectiveSearchValue ? effectiveSearchValue : undefined, - brickRoadIndicator: null, - icons: [ - { - source: userDetails.avatar, - type: CONST.ICON_TYPE_AVATAR, - name: effectiveSearchValue, - id: optimisticAccountID, - }, - ], - tooltipText: null, - participantsList: [userDetails], - accountID: optimisticAccountID, - login: effectiveSearchValue, - reportID: '', - phoneNumber: phone ?? '', - hasDraftComment: false, - keyForList: optimisticAccountID.toString(), - isDefaultRoom: false, - isPinned: false, - isWaitingOnBankAccount: false, - isIOUReportOwner: false, - iouReportAmount: 0, - isChatRoom: false, - shouldShowSubscript: false, - isPolicyExpenseChat: false, - isOwnPolicyExpenseChat: false, - isExpenseReport: false, - lastMessageText: '', - isBold: true, - isOptimisticAccount: true, - }; - - return userToInvite; -} - /** * Options are reports and personal details. This function filters out the options that are not valid to be displayed. */ @@ -1946,7 +1842,6 @@ export { getFirstKeyForList, canCreateOptimisticPersonalDetailOption, getUserToInviteOption, - getUserToInviteContactOption, getPersonalDetailSearchTerms, getCurrentUserSearchTerms, getEmptyOptions, @@ -1956,4 +1851,4 @@ export { hasReportErrors, }; -export type {MemberForList, Options, OptionList, SearchOption, PayeePersonalDetails, Option, OptionTree, GetUserToInviteConfig, Section, SectionBase}; +export type {Section, SectionBase, MemberForList, Options, OptionList, SearchOption, PayeePersonalDetails, Option, OptionTree}; diff --git a/src/libs/RandomAvatarUtils.ts b/src/libs/RandomAvatarUtils.ts deleted file mode 100644 index 2aad23b13583..000000000000 --- a/src/libs/RandomAvatarUtils.ts +++ /dev/null @@ -1,99 +0,0 @@ -import type {FC} from 'react'; -import type {SvgProps} from 'react-native-svg'; -import Avatar1 from '@assets/images/avatars/user/default-avatar_1.svg'; -import Avatar2 from '@assets/images/avatars/user/default-avatar_2.svg'; -import Avatar3 from '@assets/images/avatars/user/default-avatar_3.svg'; -import Avatar4 from '@assets/images/avatars/user/default-avatar_4.svg'; -import Avatar5 from '@assets/images/avatars/user/default-avatar_5.svg'; -import Avatar6 from '@assets/images/avatars/user/default-avatar_6.svg'; -import Avatar7 from '@assets/images/avatars/user/default-avatar_7.svg'; -import Avatar8 from '@assets/images/avatars/user/default-avatar_8.svg'; -import Avatar9 from '@assets/images/avatars/user/default-avatar_9.svg'; -import Avatar10 from '@assets/images/avatars/user/default-avatar_10.svg'; -import Avatar11 from '@assets/images/avatars/user/default-avatar_11.svg'; -import Avatar12 from '@assets/images/avatars/user/default-avatar_12.svg'; -import Avatar13 from '@assets/images/avatars/user/default-avatar_13.svg'; -import Avatar14 from '@assets/images/avatars/user/default-avatar_14.svg'; -import Avatar15 from '@assets/images/avatars/user/default-avatar_15.svg'; -import Avatar16 from '@assets/images/avatars/user/default-avatar_16.svg'; -import Avatar17 from '@assets/images/avatars/user/default-avatar_17.svg'; -import Avatar18 from '@assets/images/avatars/user/default-avatar_18.svg'; -import Avatar19 from '@assets/images/avatars/user/default-avatar_19.svg'; -import Avatar20 from '@assets/images/avatars/user/default-avatar_20.svg'; -import Avatar21 from '@assets/images/avatars/user/default-avatar_21.svg'; -import Avatar22 from '@assets/images/avatars/user/default-avatar_22.svg'; -import Avatar23 from '@assets/images/avatars/user/default-avatar_23.svg'; -import Avatar24 from '@assets/images/avatars/user/default-avatar_24.svg'; - -type AvatarComponent = FC; -type AvatarArray = readonly AvatarComponent[]; - -const avatars: AvatarArray = [ - Avatar1, - Avatar2, - Avatar3, - Avatar4, - Avatar5, - Avatar6, - Avatar7, - Avatar8, - Avatar9, - Avatar10, - Avatar11, - Avatar12, - Avatar13, - Avatar14, - Avatar15, - Avatar16, - Avatar17, - Avatar18, - Avatar19, - Avatar20, - Avatar21, - Avatar22, - Avatar23, - Avatar24, -] as const; - -const AVATAR_LENGTH: number = avatars.length; -const DEFAULT_AVATAR: AvatarComponent = Avatar1; - -// Prime numbers for better distribution -const MULTIPLIER = AVATAR_LENGTH + 7; // First prime after length -const OFFSET = AVATAR_LENGTH - 11; // First prime before length - -/** - * Generate a deterministic avatar based on multiple letters from the name. - * Uses a rolling hash of the first 5 letters (or available letters if name is shorter) - * for better distribution while maintaining deterministic results. - * - * @example - * // These will always return the same avatar for the same name - * const avatar1 = getAvatarForContact("Jonathan") // Uses 'Jonat' for hash - * const avatar2 = getAvatarForContact("Jane") // Uses 'Jane' for hash - * const avatar3 = getAvatarForContact("J") // Uses 'J' for hash - * - * @param name - Contact name or null/undefined - * @returns Avatar component - */ -const getAvatarForContact = (name?: string | null): AvatarComponent => { - if (!name?.length) { - return DEFAULT_AVATAR; - } - - // Take up to first 8 characters, or all if name is shorter - const chars = name.slice(0, 8); - - // Create a rolling hash from the characters - let hash = 0; - for (let i = 0; i < chars.length; i++) { - const charCode = chars.charCodeAt(i); - // Use position-based multiplier for better distribution - hash = (hash * MULTIPLIER + charCode * (i + 1) + OFFSET) % AVATAR_LENGTH; - } - - return avatars.at(Math.abs(hash)) ?? DEFAULT_AVATAR; -}; - -export type {AvatarComponent}; -export {getAvatarForContact}; diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 6147ee3e8d47..07e34d9692b1 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -1,14 +1,10 @@ import lodashIsEqual from 'lodash/isEqual'; import lodashPick from 'lodash/pick'; import lodashReject from 'lodash/reject'; -import React, {memo, useCallback, useEffect, useMemo, useState} from 'react'; +import React, {memo, useCallback, useEffect, useMemo} from 'react'; import type {GestureResponderEvent} from 'react-native'; -import {InteractionManager, Linking, View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; -import {RESULTS} from 'react-native-permissions'; -import type {PermissionStatus} from 'react-native-permissions'; import Button from '@components/Button'; -import ContactPermissionModal from '@components/ContactPermissionModal'; import EmptySelectionListContent from '@components/EmptySelectionListContent'; import FormHelpMessage from '@components/FormHelpMessage'; import * as Expensicons from '@components/Icon/Expensicons'; @@ -18,7 +14,6 @@ import {useOptionsList} from '@components/OptionListContextProvider'; import ReferralProgramCTA from '@components/ReferralProgramCTA'; import SelectionList from '@components/SelectionList'; import InviteMemberListItem from '@components/SelectionList/InviteMemberListItem'; -import Text from '@components/Text'; import useDebouncedState from '@hooks/useDebouncedState'; import useDismissedReferralBanners from '@hooks/useDismissedReferralBanners'; import useLocalize from '@hooks/useLocalize'; @@ -26,16 +21,11 @@ import useNetwork from '@hooks/useNetwork'; import usePolicy from '@hooks/usePolicy'; import useScreenWrapperTranstionStatus from '@hooks/useScreenWrapperTransitionStatus'; import useThemeStyles from '@hooks/useThemeStyles'; -import contactImport from '@libs/ContactImport'; -import type {ContactImportResult} from '@libs/ContactImport/types'; -import {getContactPermission} from '@libs/ContactPermission'; -import getContacts from '@libs/ContactUtils'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import saveLastRoute from '@libs/saveLastRoute'; import * as SubscriptionUtils from '@libs/SubscriptionUtils'; import * as Policy from '@userActions/Policy/Policy'; import * as Report from '@userActions/Report'; @@ -43,7 +33,6 @@ import type {IOUAction, IOUType} from '@src/CONST'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {PersonalDetails} from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; type MoneyRequestParticipantsSelectorProps = { @@ -80,9 +69,6 @@ function MoneyRequestParticipantsSelector({ }: MoneyRequestParticipantsSelectorProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); - const [softPermissionModalVisible, setSoftPermissionModalVisible] = useState(false); - const [contactPermissionState, setContactPermissionState] = useState(RESULTS.UNAVAILABLE); - const showImportContacts = !(contactPermissionState === RESULTS.GRANTED || contactPermissionState === RESULTS.LIMITED); const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); const referralContentType = iouType === CONST.IOU.TYPE.PAY ? CONST.REFERRAL_PROGRAM.CONTENT_TYPES.PAY_SOMEONE : CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE; const {isOffline} = useNetwork(); @@ -97,8 +83,6 @@ function MoneyRequestParticipantsSelector({ const {options, areOptionsInitialized} = useOptionsList({ shouldInitialize: didScreenTransitionEnd, }); - const [contacts, setContacts] = useState>>([]); - const [textInputAutoFocus, setTextInputAutoFocus] = useState(softPermissionModalVisible); const cleanSearchTerm = useMemo(() => debouncedSearchTerm.trim().toLowerCase(), [debouncedSearchTerm]); const offlineMessage: string = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; @@ -124,7 +108,7 @@ function MoneyRequestParticipantsSelector({ const optionList = OptionsListUtils.getValidOptions( { reports: options.reports, - personalDetails: options.personalDetails.concat(contacts), + personalDetails: options.personalDetails, }, { betas, @@ -148,7 +132,7 @@ function MoneyRequestParticipantsSelector({ ...optionList, ...orderedOptions, }; - }, [action, contacts, areOptionsInitialized, betas, didScreenTransitionEnd, iouType, isCategorizeOrShareAction, options.personalDetails, options.reports, participants]); + }, [action, areOptionsInitialized, betas, didScreenTransitionEnd, iouType, isCategorizeOrShareAction, options.personalDetails, options.reports, participants]); const chatOptions = useMemo(() => { if (!areOptionsInitialized) { @@ -172,16 +156,6 @@ function MoneyRequestParticipantsSelector({ return newOptions; }, [areOptionsInitialized, defaultOptions, debouncedSearchTerm, participants, isPaidGroupPolicy, isCategorizeOrShareAction, action]); - const inputHelperText = useMemo( - () => - OptionsListUtils.getHeaderMessage( - (chatOptions.personalDetails ?? []).length + (chatOptions.recentReports ?? []).length !== 0, - !!chatOptions?.userToInvite, - debouncedSearchTerm.trim(), - participants.some((participant) => OptionsListUtils.getPersonalDetailSearchTerms(participant).join(' ').toLowerCase().includes(cleanSearchTerm)), - ), - [chatOptions.personalDetails, chatOptions.recentReports, chatOptions?.userToInvite, cleanSearchTerm, debouncedSearchTerm, participants], - ); /** * Returns the sections needed for the OptionsSelector * @returns {Array} @@ -229,10 +203,12 @@ function MoneyRequestParticipantsSelector({ }); } - let headerMessage = ''; - if (!showImportContacts) { - headerMessage = inputHelperText; - } + const headerMessage = OptionsListUtils.getHeaderMessage( + (chatOptions.personalDetails ?? []).length + (chatOptions.recentReports ?? []).length !== 0, + !!chatOptions?.userToInvite, + debouncedSearchTerm.trim(), + participants.some((participant) => OptionsListUtils.getPersonalDetailSearchTerms(participant).join(' ').toLowerCase().includes(cleanSearchTerm)), + ); return [newSections, headerMessage]; }, [ @@ -245,38 +221,19 @@ function MoneyRequestParticipantsSelector({ chatOptions.userToInvite, personalDetails, translate, - showImportContacts, - inputHelperText, + cleanSearchTerm, ]); - const handleContactImport = useCallback(() => { - contactImport().then(({contactList, permissionStatus}: ContactImportResult) => { - setContactPermissionState(permissionStatus); - const usersFromContact = getContacts(contactList); - setContacts(usersFromContact); - }); - }, []); - - useEffect(() => { - setSoftPermissionModalVisible(true); - getContactPermission().then((status) => { - setContactPermissionState(status); - if (status !== RESULTS.BLOCKED && status !== RESULTS.UNAVAILABLE) { - setSoftPermissionModalVisible(true); - } - }); - }, []); - /** * Adds a single participant to the expense * * @param {Object} option */ const addSingleParticipant = useCallback( - (option: Participant & OptionsListUtils.Option) => { + (option: Participant) => { const newParticipants: Participant[] = [ { - ...lodashPick(option, 'accountID', 'login', 'isPolicyExpenseChat', 'reportID', 'searchText', 'policyID', 'text', 'phoneNumber'), + ...lodashPick(option, 'accountID', 'login', 'isPolicyExpenseChat', 'reportID', 'searchText', 'policyID'), selected: true, iouType, }, @@ -386,57 +343,21 @@ function MoneyRequestParticipantsSelector({ const shouldShowReferralBanner = !isDismissed && iouType !== CONST.IOU.TYPE.INVOICE && !shouldShowListEmptyContent; - const goToSettings = useCallback(() => { - Linking.openSettings(); - // In the case of ios, the App reloads when we update contact permission from settings - // we are saving last route so we can navigate to it after app reload - saveLastRoute(); - }, []); - const headerContent = useMemo(() => { - const importContacts = - showImportContacts && inputHelperText ? ( - - - {`${translate('common.noResultsFound')}. `} - - {translate('contact.importContactsTitle')} - {' '} - {translate('contact.importContactsExplanation')} - - - ) : null; + if (!shouldDisplayTrackExpenseButton) { + return; + } // We only display the track expense button if the user is coming from the combined submit/track flow. - const expenseButton = shouldDisplayTrackExpenseButton ? ( + return ( - ) : null; - - return ( - <> - {importContacts} - {expenseButton} - ); - }, [showImportContacts, inputHelperText, shouldDisplayTrackExpenseButton, translate, onTrackExpensePress, styles, goToSettings]); - - const handleSoftPermissionDeny = useCallback(() => { - setSoftPermissionModalVisible(false); - }, []); - - const handleSoftPermissionGrant = useCallback(() => { - setSoftPermissionModalVisible(false); - InteractionManager.runAfterInteractions(handleContactImport); - setTextInputAutoFocus(true); - }, [handleContactImport]); + }, [shouldDisplayTrackExpenseButton, translate, onTrackExpensePress]); const footerContent = useMemo(() => { if (isDismissed && !shouldShowSplitBillErrorMessage && !participants.length) { @@ -511,58 +432,27 @@ function MoneyRequestParticipantsSelector({ [isIOUSplit, addParticipantToSelection, addSingleParticipant], ); - const listFooterComponent = useMemo(() => { - if (!showImportContacts) { - return null; - } - return ( - - ); - }, [goToSettings, showImportContacts, styles.mb3, translate]); - - const EmptySelectionListContentWithPermission = useMemo(() => { - return ; - }, [iouType]); - return ( - <> - {softPermissionModalVisible && ( - - )} - - + } + headerMessage={header} + showLoadingPlaceholder={showLoadingPlaceholder} + canSelectMultiple={isIOUSplit && isAllowedToSplit} + isLoadingNewOptions={!!isSearchingForReports} + shouldShowListEmptyContent={shouldShowListEmptyContent} + /> ); } diff --git a/tsconfig.json b/tsconfig.json index f1d7d0282c55..869627446f09 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,30 +21,9 @@ "@pages/*": ["./src/pages/*"], "@styles/*": ["./src/styles/*"], "@src/*": ["./src/*"], - "@userActions/*": ["./src/libs/actions/*"], - "contacts-nitro-module": ["./modules/ContactsNitroModule"], - "contacts-nitro-module/*": ["./modules/ContactsNitroModule/*"] + "@userActions/*": ["./src/libs/actions/*"] } }, - "include": [ - "src", - "desktop", - "web", - "website", - "docs", - "assets", - "config", - "tests", - "jest", - "__mocks__", - ".github/**/*", - ".storybook/**/*", - "scripts", - "modules/index.ts", - "**/*.nitro/*.ts", - "**/*.nitro/*.tsx", - "modules/ContactsNitroModule/lib/**/*", - "modules/ContactsNitroModule/lib/*.d.ts" - ], + "include": ["src", "desktop", "web", "website", "docs", "assets", "config", "tests", "jest", "__mocks__", ".github/**/*", ".storybook/**/*", "scripts"], "exclude": ["**/node_modules/*", "**/dist/*", ".github/actions/**/index.js", "**/docs/*"] } From 4a8a55554a4f8cf49b9d3c0ecebc95a6f8e17bb9 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 20 Dec 2024 23:24:21 +0700 Subject: [PATCH 14/19] fix: onboarding modal is not shown when redirecting from OD --- src/libs/actions/Welcome/OnboardingFlow.ts | 14 +++++++++----- src/pages/home/ReportScreen.tsx | 6 ------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/libs/actions/Welcome/OnboardingFlow.ts b/src/libs/actions/Welcome/OnboardingFlow.ts index 9aa0f07dc59c..e8c8c3d1d42f 100644 --- a/src/libs/actions/Welcome/OnboardingFlow.ts +++ b/src/libs/actions/Welcome/OnboardingFlow.ts @@ -1,5 +1,6 @@ import {findFocusedRoute, getStateFromPath} from '@react-navigation/native'; import type {NavigationState, PartialState} from '@react-navigation/native'; +import {InteractionManager} from 'react-native'; import Onyx from 'react-native-onyx'; import linkingConfig from '@libs/Navigation/linkingConfig'; import getAdaptedStateFromPath from '@libs/Navigation/linkingConfig/getAdaptedStateFromPath'; @@ -44,11 +45,14 @@ function startOnboardingFlow(isPrivateDomain?: boolean) { if (focusedRoute?.name === currentRoute?.name) { return; } - navigationRef.resetRoot({ - ...navigationRef.getRootState(), - ...adaptedState, - stale: true, - } as PartialState); + // This should delay opening the onboarding modal so it does not interfere with the ongoing ReportScreen params changes + InteractionManager.runAfterInteractions(() => { + navigationRef.resetRoot({ + ...navigationRef.getRootState(), + ...adaptedState, + stale: true, + } as PartialState); + }); } function getOnboardingInitialPath(isPrivateDomain?: boolean): string { diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index e9771189bed2..d66a17bbe9b8 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -112,7 +112,6 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro const {isOffline} = useNetwork(); const {shouldUseNarrowLayout, isInNarrowPaneModal} = useResponsiveLayout(); const {activeWorkspaceID} = useActiveWorkspace(); - const lastAccessedReportIDRef = useRef(false); const [modal] = useOnyx(ONYXKEYS.MODAL); const [isComposerFullSize] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${reportIDFromRoute}`, {initialValue: false}); @@ -152,10 +151,6 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro return; } - if (lastAccessedReportIDRef.current) { - return; - } - const lastAccessedReportID = ReportUtils.findLastAccessedReport(!canUseDefaultRooms, !!route.params.openOnAdminRoom, activeWorkspaceID)?.reportID; // It's possible that reports aren't fully loaded yet @@ -165,7 +160,6 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro } Log.info(`[ReportScreen] no reportID found in params, setting it to lastAccessedReportID: ${lastAccessedReportID}`); - lastAccessedReportIDRef.current = true; navigation.setParams({reportID: lastAccessedReportID}); }, [activeWorkspaceID, canUseDefaultRooms, navigation, route, finishedLoadingApp]); From fdddac404c8b99b55e0ce2e09d4c37f37a683991 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 20 Dec 2024 23:44:52 +0700 Subject: [PATCH 15/19] update implementation --- src/hooks/useOnboardingFlow.ts | 10 +++++++--- src/libs/actions/Welcome/OnboardingFlow.ts | 14 +++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts index 81796dae851d..048c7b72508f 100644 --- a/src/hooks/useOnboardingFlow.ts +++ b/src/hooks/useOnboardingFlow.ts @@ -1,5 +1,5 @@ import {useEffect} from 'react'; -import {NativeModules} from 'react-native'; +import {InteractionManager, NativeModules} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import Navigation from '@libs/Navigation/Navigation'; import {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector} from '@libs/onboardingSelectors'; @@ -62,13 +62,17 @@ function useOnboardingFlowRouter() { // But if the hybrid app onboarding is completed, but NewDot onboarding is not completed, we start NewDot onboarding flow // This is a special case when user created an account from NewDot without finishing the onboarding flow and then logged in from OldDot if (isHybridAppOnboardingCompleted === true && isOnboardingCompleted === false) { - OnboardingFlow.startOnboardingFlow(isPrivateDomain); + InteractionManager.runAfterInteractions(() => { + OnboardingFlow.startOnboardingFlow(isPrivateDomain); + }); } } // If the user is not transitioning from OldDot to NewDot, we should start NewDot onboarding flow if it's not completed yet if (!NativeModules.HybridAppModule && isOnboardingCompleted === false) { - OnboardingFlow.startOnboardingFlow(isPrivateDomain); + InteractionManager.runAfterInteractions(() => { + OnboardingFlow.startOnboardingFlow(isPrivateDomain); + }); } }, [ isOnboardingCompleted, diff --git a/src/libs/actions/Welcome/OnboardingFlow.ts b/src/libs/actions/Welcome/OnboardingFlow.ts index e8c8c3d1d42f..9aa0f07dc59c 100644 --- a/src/libs/actions/Welcome/OnboardingFlow.ts +++ b/src/libs/actions/Welcome/OnboardingFlow.ts @@ -1,6 +1,5 @@ import {findFocusedRoute, getStateFromPath} from '@react-navigation/native'; import type {NavigationState, PartialState} from '@react-navigation/native'; -import {InteractionManager} from 'react-native'; import Onyx from 'react-native-onyx'; import linkingConfig from '@libs/Navigation/linkingConfig'; import getAdaptedStateFromPath from '@libs/Navigation/linkingConfig/getAdaptedStateFromPath'; @@ -45,14 +44,11 @@ function startOnboardingFlow(isPrivateDomain?: boolean) { if (focusedRoute?.name === currentRoute?.name) { return; } - // This should delay opening the onboarding modal so it does not interfere with the ongoing ReportScreen params changes - InteractionManager.runAfterInteractions(() => { - navigationRef.resetRoot({ - ...navigationRef.getRootState(), - ...adaptedState, - stale: true, - } as PartialState); - }); + navigationRef.resetRoot({ + ...navigationRef.getRootState(), + ...adaptedState, + stale: true, + } as PartialState); } function getOnboardingInitialPath(isPrivateDomain?: boolean): string { From 3a590f2c74043cdd0f7a50d22989f51187eb20ff Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 20 Dec 2024 23:46:36 +0700 Subject: [PATCH 16/19] add a comment --- src/hooks/useOnboardingFlow.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts index 048c7b72508f..b6753ce5b408 100644 --- a/src/hooks/useOnboardingFlow.ts +++ b/src/hooks/useOnboardingFlow.ts @@ -62,6 +62,7 @@ function useOnboardingFlowRouter() { // But if the hybrid app onboarding is completed, but NewDot onboarding is not completed, we start NewDot onboarding flow // This is a special case when user created an account from NewDot without finishing the onboarding flow and then logged in from OldDot if (isHybridAppOnboardingCompleted === true && isOnboardingCompleted === false) { + // This should delay opening the onboarding modal so it does not interfere with the ongoing ReportScreen params changes InteractionManager.runAfterInteractions(() => { OnboardingFlow.startOnboardingFlow(isPrivateDomain); }); @@ -70,6 +71,7 @@ function useOnboardingFlowRouter() { // If the user is not transitioning from OldDot to NewDot, we should start NewDot onboarding flow if it's not completed yet if (!NativeModules.HybridAppModule && isOnboardingCompleted === false) { + // This should delay opening the onboarding modal so it does not interfere with the ongoing ReportScreen params changes InteractionManager.runAfterInteractions(() => { OnboardingFlow.startOnboardingFlow(isPrivateDomain); }); From 830b02d0165c06c6a6b8761c5fa3235f122d8976 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 20 Dec 2024 23:49:31 +0700 Subject: [PATCH 17/19] wrap whole useEffect callback --- src/hooks/useOnboardingFlow.ts | 65 ++++++++++++++++------------------ 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts index b6753ce5b408..d322a4d52703 100644 --- a/src/hooks/useOnboardingFlow.ts +++ b/src/hooks/useOnboardingFlow.ts @@ -32,50 +32,47 @@ function useOnboardingFlowRouter() { const [isSingleNewDotEntry, isSingleNewDotEntryMetadata] = useOnyx(ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY); const [allBetas, allBetasMetadata] = useOnyx(ONYXKEYS.BETAS); useEffect(() => { - if (isLoadingOnyxValue(isOnboardingCompletedMetadata, tryNewDotdMetadata, dismissedProductTrainingMetadata, allBetasMetadata)) { - return; - } - - if (NativeModules.HybridAppModule && isLoadingOnyxValue(isSingleNewDotEntryMetadata)) { - return; - } - - if (hasBeenAddedToNudgeMigration && !dismissedProductTraining?.migratedUserWelcomeModal && Permissions.shouldShowProductTrainingElements(allBetas)) { - const defaultCannedQuery = SearchQueryUtils.buildCannedSearchQuery(); - const query = defaultCannedQuery; - Navigation.navigate(ROUTES.SEARCH_CENTRAL_PANE.getRoute({query})); - Navigation.navigate(ROUTES.MIGRATED_USER_WELCOME_MODAL); - return; - } + // This should delay opening the onboarding modal so it does not interfere with the ongoing ReportScreen params changes + InteractionManager.runAfterInteractions(() => { + if (isLoadingOnyxValue(isOnboardingCompletedMetadata, tryNewDotdMetadata, dismissedProductTrainingMetadata, allBetasMetadata)) { + return; + } - if (NativeModules.HybridAppModule) { - // For single entries, such as using the Travel feature from OldDot, we don't want to show onboarding - if (isSingleNewDotEntry) { + if (NativeModules.HybridAppModule && isLoadingOnyxValue(isSingleNewDotEntryMetadata)) { return; } - // When user is transitioning from OldDot to NewDot, we usually show the explanation modal - if (isHybridAppOnboardingCompleted === false) { - Navigation.navigate(ROUTES.EXPLANATION_MODAL_ROOT); + if (hasBeenAddedToNudgeMigration && !dismissedProductTraining?.migratedUserWelcomeModal && Permissions.shouldShowProductTrainingElements(allBetas)) { + const defaultCannedQuery = SearchQueryUtils.buildCannedSearchQuery(); + const query = defaultCannedQuery; + Navigation.navigate(ROUTES.SEARCH_CENTRAL_PANE.getRoute({query})); + Navigation.navigate(ROUTES.MIGRATED_USER_WELCOME_MODAL); + return; } - // But if the hybrid app onboarding is completed, but NewDot onboarding is not completed, we start NewDot onboarding flow - // This is a special case when user created an account from NewDot without finishing the onboarding flow and then logged in from OldDot - if (isHybridAppOnboardingCompleted === true && isOnboardingCompleted === false) { - // This should delay opening the onboarding modal so it does not interfere with the ongoing ReportScreen params changes - InteractionManager.runAfterInteractions(() => { + if (NativeModules.HybridAppModule) { + // For single entries, such as using the Travel feature from OldDot, we don't want to show onboarding + if (isSingleNewDotEntry) { + return; + } + + // When user is transitioning from OldDot to NewDot, we usually show the explanation modal + if (isHybridAppOnboardingCompleted === false) { + Navigation.navigate(ROUTES.EXPLANATION_MODAL_ROOT); + } + + // But if the hybrid app onboarding is completed, but NewDot onboarding is not completed, we start NewDot onboarding flow + // This is a special case when user created an account from NewDot without finishing the onboarding flow and then logged in from OldDot + if (isHybridAppOnboardingCompleted === true && isOnboardingCompleted === false) { OnboardingFlow.startOnboardingFlow(isPrivateDomain); - }); + } } - } - // If the user is not transitioning from OldDot to NewDot, we should start NewDot onboarding flow if it's not completed yet - if (!NativeModules.HybridAppModule && isOnboardingCompleted === false) { - // This should delay opening the onboarding modal so it does not interfere with the ongoing ReportScreen params changes - InteractionManager.runAfterInteractions(() => { + // If the user is not transitioning from OldDot to NewDot, we should start NewDot onboarding flow if it's not completed yet + if (!NativeModules.HybridAppModule && isOnboardingCompleted === false) { OnboardingFlow.startOnboardingFlow(isPrivateDomain); - }); - } + } + }); }, [ isOnboardingCompleted, isHybridAppOnboardingCompleted, From 30d7b4847423cba40bef5ff782e78c31a33dc9e1 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Fri, 20 Dec 2024 17:21:30 +0000 Subject: [PATCH 18/19] Update version to 9.0.77-6 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 20e86ae52073..4c917b995331 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009007705 - versionName "9.0.77-5" + versionCode 1009007706 + versionName "9.0.77-6" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 4b9157afbcae..1e81fdedcaee 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -40,7 +40,7 @@ CFBundleVersion - 9.0.77.5 + 9.0.77.6 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 3e6cc8920b19..2291b6e19e37 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.77.5 + 9.0.77.6 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index d3bc23571433..f94a9a34f558 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.77 CFBundleVersion - 9.0.77.5 + 9.0.77.6 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 0ded98fa58eb..51773c06935e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.77-5", + "version": "9.0.77-6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.77-5", + "version": "9.0.77-6", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 0896f83e10d0..c3f6d8e730d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.77-5", + "version": "9.0.77-6", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From e09ff02135925bf7834c2954a6076271a9dffe88 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Fri, 20 Dec 2024 17:22:03 +0000 Subject: [PATCH 19/19] Update Mobile-Expensify to 9.0.77-6 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 1d9a218bff07..f370c5f31cdf 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 1d9a218bff0706bbe75f50045c6d39eba1435f97 +Subproject commit f370c5f31cdfd750b0d42d75a471a9b8d30935ad