diff --git a/android/app/src/main/java/com/expensify/chat/AppStateTrackerModule.kt b/android/app/src/main/java/com/expensify/chat/AppStateTrackerModule.kt index 2f96578a4af3..5546916c38f9 100644 --- a/android/app/src/main/java/com/expensify/chat/AppStateTrackerModule.kt +++ b/android/app/src/main/java/com/expensify/chat/AppStateTrackerModule.kt @@ -4,6 +4,7 @@ import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod +import com.facebook.react.bridge.UiThreadUtil import com.expensify.chat.MainActivity @@ -25,4 +26,14 @@ class AppStateTrackerModule(reactContext: ReactApplicationContext) : ReactContex promise.resolve(false) } } + + /** + * Tells Android that NewDot finished its first screen, which records time to full display for this launch. + */ + @ReactMethod + fun reportFullyDrawn() { + UiThreadUtil.runOnUiThread { + reactApplicationContext.getCurrentActivity()?.reportFullyDrawn() + } + } } diff --git a/src/Expensify.tsx b/src/Expensify.tsx index ef75ca168830..f0c6470b93f5 100644 --- a/src/Expensify.tsx +++ b/src/Expensify.tsx @@ -38,6 +38,7 @@ import PushNotification from './libs/Notification/PushNotification'; import {endSpan, getSpan, startSpan} from './libs/telemetry/activeSpans'; import {startBootsplashMonitor} from './libs/telemetry/bootsplashTelemetry'; import {scheduleInitialDatabaseSizeMeasurement} from './libs/telemetry/databaseSizeTracker'; +import reportFullyDrawn from './libs/telemetry/reportFullyDrawn'; import {cleanupTelemetryTrackers, initializeTelemetryTrackers} from './libs/telemetry/TelemetrySynchronizer'; import Visibility from './libs/Visibility'; import ONYXKEYS from './ONYXKEYS'; @@ -209,6 +210,7 @@ function Expensify() { setSplashScreenState(CONST.BOOT_SPLASH_STATE.HIDDEN); endSpan(CONST.TELEMETRY.SPAN_OD_ND_TRANSITION); endSpan(CONST.TELEMETRY.SPAN_APP_STARTUP); + reportFullyDrawn(); endSpan(CONST.TELEMETRY.SPAN_BOOTSPLASH.ROOT); endSpan(CONST.TELEMETRY.SPAN_BOOTSPLASH.SPLASH_HIDER); scheduleInitialDatabaseSizeMeasurement(); diff --git a/src/libs/telemetry/reportFullyDrawn/index.android.ts b/src/libs/telemetry/reportFullyDrawn/index.android.ts new file mode 100644 index 000000000000..85090dfeb4c8 --- /dev/null +++ b/src/libs/telemetry/reportFullyDrawn/index.android.ts @@ -0,0 +1,9 @@ +import {NativeModules} from 'react-native'; + +import type ReportFullyDrawn from './types'; + +const reportFullyDrawn: ReportFullyDrawn = () => { + NativeModules.AppStateTracker.reportFullyDrawn?.(); +}; + +export default reportFullyDrawn; diff --git a/src/libs/telemetry/reportFullyDrawn/index.ts b/src/libs/telemetry/reportFullyDrawn/index.ts new file mode 100644 index 000000000000..55a3d77e0598 --- /dev/null +++ b/src/libs/telemetry/reportFullyDrawn/index.ts @@ -0,0 +1,6 @@ +import type ReportFullyDrawn from './types'; + +// Time to full display is an Android startup metric, so the other platforms have nothing to report. +const reportFullyDrawn: ReportFullyDrawn = () => {}; + +export default reportFullyDrawn; diff --git a/src/libs/telemetry/reportFullyDrawn/types.ts b/src/libs/telemetry/reportFullyDrawn/types.ts new file mode 100644 index 000000000000..9b0390ba3a55 --- /dev/null +++ b/src/libs/telemetry/reportFullyDrawn/types.ts @@ -0,0 +1,3 @@ +type ReportFullyDrawn = () => void; + +export default ReportFullyDrawn; diff --git a/src/types/modules/react-native.d.ts b/src/types/modules/react-native.d.ts index e43d30a8631e..50a6535f707d 100644 --- a/src/types/modules/react-native.d.ts +++ b/src/types/modules/react-native.d.ts @@ -9,6 +9,8 @@ import type {TargetedEvent} from 'react-native'; type AppStateTrackerModule = { getWasAppRelaunchedFromIcon: () => Promise; + // Missing on binaries built before this method was added. + reportFullyDrawn?: () => void; }; type RNTextInputResetModule = {