diff --git a/desktop/flipper-ui-core/src/fb-stubs/openSupportRequestForm.tsx b/desktop/flipper-ui-core/src/fb-stubs/openSupportRequestForm.tsx index c999c263a..ce0d54e16 100644 --- a/desktop/flipper-ui-core/src/fb-stubs/openSupportRequestForm.tsx +++ b/desktop/flipper-ui-core/src/fb-stubs/openSupportRequestForm.tsx @@ -12,11 +12,12 @@ import {State} from '../reducers'; export type SupportRequestDetails = { title?: string; whatAlreadyTried?: string; + everythingEverywhereAllAtOnceExportDownloadURL?: string; }; export default function openSupportRequestForm( _state: State, _details?: SupportRequestDetails, -): void { +): Promise { throw new Error('Not implemented!'); } diff --git a/desktop/flipper-ui-core/src/sandy-chrome/LeftRail.tsx b/desktop/flipper-ui-core/src/sandy-chrome/LeftRail.tsx index bdb86b07c..b672efc9a 100644 --- a/desktop/flipper-ui-core/src/sandy-chrome/LeftRail.tsx +++ b/desktop/flipper-ui-core/src/sandy-chrome/LeftRail.tsx @@ -255,8 +255,6 @@ function ExtrasMenu() { const {showWelcomeAtStartup} = settings; const [welcomeVisible, setWelcomeVisible] = useState(showWelcomeAtStartup); - const fullState = useStore((state) => state); - return ( <> - {config.isFBBuild ? ( - <> - { - getLogger().track('usage', 'support-form-source', { - source: 'sidebar', - group: undefined, - }); - openSupportRequestForm(fullState); - }}> - Feedback - - - ) : null} + {config.isFBBuild ? : null} setShowSettings(true)}> Settings @@ -433,21 +417,51 @@ function DebugLogsButton({ ); } -function ExportEverythingEverywhereAllAtOnceButton() { +function OpenSupportRequestMenuItem() { const store = useStore(); + const [status, setStatus] = useState< ExportEverythingEverywhereAllAtOnceStatus | undefined >(); + + return ( + <> + + { + getLogger().track('usage', 'support-form-source', { + source: 'sidebar', + group: undefined, + }); + await exportEverythingEverywhereAllAtOnce( + store, + (...args) => setStatus(args), + true, + ); + }}> + Feedback + + + ); +} + +function ExportEverythingEverywhereAllAtOnceStatusModal({ + status, + setStatus, +}: { + status: ExportEverythingEverywhereAllAtOnceStatus | undefined; + setStatus: ( + newStatus: ExportEverythingEverywhereAllAtOnceStatus | undefined, + ) => void; +}) { const [statusMessage, setStatusMessage] = useState(); - const exportEverythingEverywhereAllAtOnceTracked = useTrackedCallback( - 'Debug data export', - () => exportEverythingEverywhereAllAtOnce(store, setStatus), - [store, setStatus], - ); - useEffect(() => { - switch (status) { + switch (status?.[0]) { case 'logs': { setStatusMessage(

Exporting Flipper logs...

); return; @@ -492,6 +506,23 @@ function ExportEverythingEverywhereAllAtOnceButton() { setStatusMessage(

Creating an archive...

); return; } + case 'upload': { + setStatusMessage(

Uploading the archive...

); + return; + } + case 'support': { + setStatusMessage(

Creating a support request...

); + return; + } + case 'error': { + setStatusMessage( + <> +

Oops! Something went wrong.

+

{status[1]}

+ , + ); + return; + } case 'done': { setStatusMessage(

Done!

); return; @@ -503,18 +534,39 @@ function ExportEverythingEverywhereAllAtOnceButton() { } }, [status]); + return ( + { + setStatus(undefined); + }} + title="Exporting everything everywhere all at once" + footer={null}> + {statusMessage} + + ); +} + +function ExportEverythingEverywhereAllAtOnceButton() { + const store = useStore(); + const [status, setStatus] = useState< + ExportEverythingEverywhereAllAtOnceStatus | undefined + >(); + + const exportEverythingEverywhereAllAtOnceTracked = useTrackedCallback( + 'Debug data export', + () => + exportEverythingEverywhereAllAtOnce(store, (...args) => setStatus(args)), + [store, setStatus], + ); + return ( <> - { - setStatus(undefined); - }} - title="Exporting everything everywhere all at once" - footer={null}> - {statusMessage} - + } diff --git a/desktop/flipper-ui-core/src/utils/exportData.tsx b/desktop/flipper-ui-core/src/utils/exportData.tsx index 5a21e20df..70514252a 100644 --- a/desktop/flipper-ui-core/src/utils/exportData.tsx +++ b/desktop/flipper-ui-core/src/utils/exportData.tsx @@ -13,6 +13,7 @@ import { DeviceDebugFile, DeviceDebugCommand, timeout, + getStringFromErrorLike, } from 'flipper-common'; import {Store, MiddlewareAPI} from '../reducers'; import {DeviceExport} from 'flipper-frontend-core'; @@ -41,6 +42,8 @@ import {exportLogs} from '../chrome/ConsoleLogs'; import JSZip from 'jszip'; import {safeFilename} from './safeFilename'; import {getExportablePlugins} from '../selectors/connections'; +import {notification} from 'antd'; +import openSupportRequestForm from '../fb-stubs/openSupportRequestForm'; export const IMPORT_FLIPPER_TRACE_EVENT = 'import-flipper-trace'; export const EXPORT_FLIPPER_TRACE_EVENT = 'export-flipper-trace'; @@ -621,15 +624,19 @@ async function startDeviceFlipperFolderExport() { } export type ExportEverythingEverywhereAllAtOnceStatus = - | 'logs' - | 'files' - | 'state' - | 'archive' - | 'done' - | 'cancelled'; + | ['logs'] + | ['files'] + | ['state'] + | ['archive'] + | ['upload'] + | ['support'] + | ['done'] + | ['error', string] + | ['cancelled']; export async function exportEverythingEverywhereAllAtOnce( store: MiddlewareAPI, - onStatusUpdate?: (status: ExportEverythingEverywhereAllAtOnceStatus) => void, + onStatusUpdate?: (...args: ExportEverythingEverywhereAllAtOnceStatus) => void, + openSupportRequest?: boolean, ) { const zip = new JSZip(); @@ -704,10 +711,56 @@ export async function exportEverythingEverywhereAllAtOnce( }, ); - if (exportedFilePath) { - onStatusUpdate?.('done'); + if (openSupportRequest) { + if (exportedFilePath) { + onStatusUpdate?.('upload'); + + let everythingEverywhereAllAtOnceExportDownloadURL: string | undefined; + try { + everythingEverywhereAllAtOnceExportDownloadURL = + await getRenderHostInstance().flipperServer.exec( + 'intern-cloud-upload', + exportedFilePath, + ); + } catch (e) { + console.error( + 'exportEverythingEverywhereAllAtOnce -> failed to upload export to intern', + exportedFilePath, + ); + notification.warn({ + message: 'Failed to upload debug data', + description: `Flipper failed to upload debug export (${exportedFilePath}) automatically. Please, attach it to the support request manually in the comments after it is created.`, + duration: null, + }); + } + + onStatusUpdate?.('support'); + try { + await openSupportRequestForm(store.getState(), { + everythingEverywhereAllAtOnceExportDownloadURL, + }); + onStatusUpdate?.('done'); + } catch (e) { + console.error( + 'exportEverythingEverywhereAllAtOnce -> failed to create a support request', + e, + ); + onStatusUpdate?.('error', getStringFromErrorLike(e)); + } + } else { + notification.warn({ + message: 'Export cancelled', + description: `Exporting Flipper debug data was cancelled. Flipper team will not be able to help you without this data. Please, restart the export.`, + duration: null, + }); + onStatusUpdate?.('cancelled'); + } } else { - onStatusUpdate?.('cancelled'); + if (exportedFilePath) { + onStatusUpdate?.('done'); + } else { + onStatusUpdate?.('cancelled'); + } } }