11import type JSZip from 'jszip' ;
22import type { RefObject } from 'react' ;
3- import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
3+ import React , { useEffect , useState } from 'react' ;
44import { Alert } from 'react-native' ;
5- import RNFetchBlob from 'react-native-blob-util' ;
65import DeviceInfo from 'react-native-device-info' ;
7- import { startProfiling , stopProfiling } from 'react-native-release-profiler' ;
86import Button from '@components/Button' ;
97import Switch from '@components/Switch' ;
108import TestToolRow from '@components/TestToolRow' ;
119import Text from '@components/Text' ;
1210import useLocalize from '@hooks/useLocalize' ;
1311import useOnyx from '@hooks/useOnyx' ;
1412import useThemeStyles from '@hooks/useThemeStyles' ;
15- import { disableLoggingAndFlushLogs , setShouldStoreLogs } from '@libs/actions/Console' ;
16- import toggleProfileTool from '@libs/actions/ProfilingTool' ;
17- import { setShouldRecordTroubleshootData } from '@libs/actions/Troubleshoot' ;
13+ import { cleanupAfterDisable , disableRecording , enableRecording , stopProfilingAndGetData } from '@libs/actions/Troubleshoot' ;
14+ import type { ProfilingData } from '@libs/actions/Troubleshoot' ;
1815import { parseStringifiedMessages } from '@libs/Console' ;
1916import getPlatform from '@libs/getPlatform' ;
20- import Log from '@libs/Log' ;
21- import { Memoize } from '@libs/memoize' ;
22- import Performance from '@libs/Performance' ;
23- import { shouldShowProfileTool as shouldShowProfileToolUtil } from '@userActions/TestTool' ;
2417import CONFIG from '@src/CONFIG' ;
25- import CONST from '@src/CONST' ;
2618import ONYXKEYS from '@src/ONYXKEYS' ;
2719import type { Log as OnyxLog } from '@src/types/onyx' ;
2820import pkg from '../../../package.json' ;
29- import RNFS from './RNFS' ;
21+ import handleStopRecording from './handleStopRecording' ;
22+ import type StopRecordingParams from './handleStopRecording.types' ;
3023import Share from './Share' ;
3124
3225type File = {
@@ -88,52 +81,26 @@ function BaseRecordTroubleshootDataToolMenu({
8881 const styles = useThemeStyles ( ) ;
8982 const [ shouldRecordTroubleshootData ] = useOnyx ( ONYXKEYS . SHOULD_RECORD_TROUBLESHOOT_DATA , { canBeMissing : true } ) ;
9083 const [ capturedLogs ] = useOnyx ( ONYXKEYS . LOGS , { canBeMissing : true } ) ;
91- const [ isProfilingInProgress ] = useOnyx ( ONYXKEYS . APP_PROFILING_IN_PROGRESS , { canBeMissing : true } ) ;
9284 const [ shareUrls , setShareUrls ] = useState < string [ ] > ( ) ;
9385 const [ isDisabled , setIsDisabled ] = useState < boolean > ( false ) ;
9486 const [ profileTracePath , setProfileTracePath ] = useState < string > ( ) ;
9587
96- const shouldShowProfileTool = useMemo ( ( ) => shouldShowProfileToolUtil ( ) , [ ] ) ;
97-
98- const onToggleProfiling = useCallback ( ( ) => {
99- const shouldProfiling = ! isProfilingInProgress ;
100- if ( shouldProfiling ) {
101- setShareUrls ( undefined ) ;
102- Memoize . startMonitoring ( ) ;
103- Performance . enableMonitoring ( ) ;
104- startProfiling ( ) ;
105- } else {
106- Performance . disableMonitoring ( ) ;
107- }
108- toggleProfileTool ( shouldProfiling ) ;
109- return ( ) => {
110- Performance . disableMonitoring ( ) ;
111- } ;
112- } , [ isProfilingInProgress ] ) ;
113-
114- const getAppInfo = useCallback ( ( ) => {
115- return Promise . all ( [ DeviceInfo . getTotalMemory ( ) , DeviceInfo . getUsedMemory ( ) ] ) . then ( ( [ totalMemory , usedMemory ] ) => {
116- return JSON . stringify ( {
117- appVersion : pkg . version ,
118- environment : CONFIG . ENVIRONMENT ,
119- platform : getPlatform ( ) ,
120- totalMemory : formatBytes ( totalMemory , 2 ) ,
121- usedMemory : formatBytes ( usedMemory , 2 ) ,
122- memoizeStats : Memoize . stopMonitoring ( ) ,
123- performance : shouldShowProfileTool ? Performance . getPerformanceMeasures ( ) : undefined ,
124- } ) ;
88+ const getAppInfo = async ( profilingData : ProfilingData ) => {
89+ const [ totalMemory , usedMemory ] = await Promise . all ( [ DeviceInfo . getTotalMemory ( ) , DeviceInfo . getUsedMemory ( ) ] ) ;
90+ return JSON . stringify ( {
91+ appVersion : pkg . version ,
92+ environment : CONFIG . ENVIRONMENT ,
93+ platform : getPlatform ( ) ,
94+ totalMemory : formatBytes ( totalMemory , 2 ) ,
95+ usedMemory : formatBytes ( usedMemory , 2 ) ,
96+ memoizeStats : profilingData . memoizeStats ,
97+ performance : profilingData . performanceMeasures ,
12598 } ) ;
126- } , [ shouldShowProfileTool ] ) ;
127-
128- const onStopProfiling = useMemo ( ( ) => ( shouldShowProfileTool ? stopProfiling : ( ) => Promise . resolve ( ) ) , [ shouldShowProfileTool ] ) ;
99+ } ;
129100
130- const onToggle = ( ) => {
131- if ( shouldShowProfileTool ) {
132- onToggleProfiling ( ) ;
133- }
101+ const onToggle = async ( ) => {
134102 if ( ! shouldRecordTroubleshootData ) {
135- setShouldStoreLogs ( true ) ;
136- setShouldRecordTroubleshootData ( true ) ;
103+ enableRecording ( ) ;
137104
138105 if ( onEnableLogging ) {
139106 onEnableLogging ( ) ;
@@ -146,8 +113,7 @@ function BaseRecordTroubleshootDataToolMenu({
146113
147114 if ( ! capturedLogs ) {
148115 Alert . alert ( translate ( 'initialSettingsPage.troubleshoot.noLogsToShare' ) ) ;
149- disableLoggingAndFlushLogs ( ) ;
150- setShouldRecordTroubleshootData ( false ) ;
116+ disableRecording ( ) ;
151117 return ;
152118 }
153119
@@ -156,103 +122,30 @@ function BaseRecordTroubleshootDataToolMenu({
156122
157123 const infoFileName = `App_Info_${ pkg . version } .json` ;
158124
159- if ( getPlatform ( ) === CONST . PLATFORM . WEB ) {
160- onStopProfiling ( true , newFileName ) . then ( ( ) => {
161- getAppInfo ( ) . then ( ( appInfo ) => {
162- zipRef . current ?. file ( infoFileName , appInfo ) ;
163-
164- onDisableLogging ( logsWithParsedMessages ) . then ( ( ) => {
165- disableLoggingAndFlushLogs ( ) ;
166- setShouldRecordTroubleshootData ( false ) ;
167- setIsDisabled ( false ) ;
168- onDownloadZip ?.( ) ;
169- } ) ;
170- } ) ;
171- } ) ;
172- } else if ( getPlatform ( ) === CONST . PLATFORM . IOS ) {
173- onStopProfiling ( true , newFileName ) . then ( ( path ) => {
174- if ( ! path ) {
175- return ;
176- }
177-
178- const newFilePath = `${ pathToBeUsed } /${ newFileName } ` ;
179-
180- RNFS . exists ( newFilePath )
181- . then ( ( fileExists ) => {
182- if ( ! fileExists ) {
183- return ;
184- }
185-
186- return RNFS . unlink ( newFilePath ) . then ( ( ) => {
187- Log . hmmm ( '[ProfilingToolMenu] existing file deleted successfully' ) ;
188- } ) ;
189- } )
190- . catch ( ( error ) => {
191- const typedError = error as Error ;
192- Log . hmmm ( '[ProfilingToolMenu] error checking/deleting existing file: ' , typedError . message ) ;
193- } )
194- . then ( ( ) => {
195- RNFS . copyFile ( path , newFilePath )
196- . then ( ( ) => {
197- getAppInfo ( ) . then ( ( appInfo ) => {
198- zipRef . current ?. file ( infoFileName , appInfo ) ;
199-
200- onDisableLogging ( logsWithParsedMessages ) . then ( ( ) => {
201- disableLoggingAndFlushLogs ( ) ;
202- setShouldRecordTroubleshootData ( false ) ;
203- setIsDisabled ( false ) ;
204- onDownloadZip ?.( ) ;
205- } ) ;
206- } ) ;
207- Log . hmmm ( '[ProfilingToolMenu] file copied successfully' ) ;
208-
209- setProfileTracePath ( newFilePath ) ;
210- } )
211- . catch ( ( err ) => {
212- console . error ( '[ProfilingToolMenu] error copying file: ' , err ) ;
213- } ) ;
214- } )
215- . catch ( ( error : Record < string , unknown > ) => {
216- console . error ( '[ProfilingToolMenu] error copying file: ' , error ) ;
217- Log . hmmm ( '[ProfilingToolMenu] error copying file: ' , error ) ;
218- } ) ;
219- } ) ;
220- } else if ( getPlatform ( ) === CONST . PLATFORM . ANDROID ) {
221- onStopProfiling ( true , newFileName ) . then ( ( path ) => {
222- if ( ! path ) {
223- return ;
224- }
225-
226- RNFetchBlob . fs
227- // Check if it is an internal path of `DownloadManager` then append content://media to create a valid url
228- . stat ( ! path . startsWith ( 'content://media/' ) && path . match ( / \/ d o w n l o a d s \/ \d + $ / ) ? `content://media/${ path } ` : path )
229- . then ( ( { path : realPath } ) => setProfileTracePath ( realPath ) )
230- . catch ( ( ) => setProfileTracePath ( path ) ) ;
231-
232- getAppInfo ( ) . then ( ( appInfo ) => {
233- zipRef . current ?. file ( infoFileName , appInfo ) ;
234-
235- onDisableLogging ( logsWithParsedMessages ) . then ( ( ) => {
236- disableLoggingAndFlushLogs ( ) ;
237- setShouldRecordTroubleshootData ( false ) ;
238- setIsDisabled ( false ) ;
239- } ) ;
240- } ) ;
241- } ) ;
242- } else {
243- // Desktop
244- onStopProfiling ( true , newFileName ) . then ( ( ) => {
245- getAppInfo ( ) . then ( ( appInfo ) => {
246- zipRef . current ?. file ( infoFileName , appInfo ) ;
247-
248- onDisableLogging ( logsWithParsedMessages ) . then ( ( ) => {
249- disableLoggingAndFlushLogs ( ) ;
250- setShouldRecordTroubleshootData ( false ) ;
251- setIsDisabled ( false ) ;
252- } ) ;
253- } ) ;
254- } ) ;
125+ try {
126+ const profilingData = await stopProfilingAndGetData ( newFileName ) ;
127+ const appInfo = await getAppInfo ( profilingData ) ;
128+
129+ const params : StopRecordingParams = {
130+ profilingData,
131+ infoFileName,
132+ profileFileName : newFileName ,
133+ appInfo,
134+ logsWithParsedMessages,
135+ onDisableLogging,
136+ cleanupAfterDisable,
137+ zipRef,
138+ pathToBeUsed,
139+ onDownloadZip,
140+ setProfileTracePath,
141+ } ;
142+
143+ await handleStopRecording ( params ) ;
144+ } catch ( error ) {
145+ console . error ( '[ProfilingToolMenu] error handling stop recording' , error ) ;
255146 }
147+
148+ setIsDisabled ( false ) ;
256149 } ;
257150
258151 useEffect ( ( ) => {
@@ -275,7 +168,9 @@ function BaseRecordTroubleshootDataToolMenu({
275168 < Switch
276169 accessibilityLabel = { translate ( 'initialSettingsPage.troubleshoot.recordTroubleshootData' ) }
277170 isOn = { ! ! shouldRecordTroubleshootData }
278- onToggle = { onToggle }
171+ onToggle = { ( ) => {
172+ onToggle ( ) . catch ( ( error ) => console . error ( '[ProfilingToolMenu] toggle failed' , error ) ) ;
173+ } }
279174 disabled = { isDisabled }
280175 />
281176 </ TestToolRow >
0 commit comments