import React, { useEffect, useState } from "react"; import { Box, Text, useApp } from "ink"; import Spinner from "ink-spinner"; import { Header, UploadProgress, ConnectionStatus, ConfirmAnimatedUpload, } from "./index.ts"; import { useUpload } from "../hooks/useUpload.ts"; import type { UploadOptions } from "../cli/types.ts"; export interface AppProps { options: UploadOptions; verbose: boolean; /** Set when the upload contains a GIF/video and requires user confirmation */ confirmMediaType?: "gif" | "video" | null; } export const App: React.FC = ({ options, verbose, confirmMediaType, }) => { const [confirmed, setConfirmed] = useState(!confirmMediaType); if (!confirmed && confirmMediaType) { return ( setConfirmed(true)} /> ); } return ; }; const UploadFlow: React.FC<{ options: UploadOptions; verbose: boolean }> = ({ options, verbose, }) => { const { exit } = useApp(); const { status, message, progress, currentFileIndex, totalFiles, uploadSteps, connectionSteps, } = useUpload(options, verbose); // Exit the app when done useEffect(() => { if (status === "success" || status === "error") { // Give time for the final render, then exit const timer = setTimeout(() => { exit(); // Force exit since noble keeps handles open process.exit(status === "error" ? 1 : 0); }, 100); return () => clearTimeout(timer); } }, [status, exit]); return (
{options.isBulk && totalFiles > 1 && ( Bulk Upload: {currentFileIndex}/{totalFiles} files )} {status === "connecting" && ( {" "} {message} )} {status === "uploading" && ( )} {status === "success" && ( <> Device is ready to use! )} {status === "error" && ( <> Please check your device and try again. )} ); };