import * as MediaLibrary from "expo-media-library"; import React, { useEffect, useState } from "react"; import { ActivityIndicator, Alert, Modal, StyleSheet, Text, View, } from "react-native"; import { ProgressBar } from "react-native-paper"; import Toast from "react-native-toast-message"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { logImEXEvent } from "../../firebase/firebase.analytics"; import { selectCurrentCameraJobId, selectDeleteAfterUpload, } from "../../redux/app/app.selectors"; import * as Sentry from "@sentry/react-native"; import { formatBytes } from "../../util/document-upload.utility"; import { handleLocalUpload } from "../../util/local-document-upload.utility"; const mapStateToProps = createStructuredSelector({ selectedCameraJobId: selectCurrentCameraJobId, deleteAfterUpload: selectDeleteAfterUpload, }); export default connect(mapStateToProps, null)(UploadProgress); export function UploadProgress({ selectedCameraJobId, deleteAfterUpload, uploads, setUploads, forceRerender, }) { const [progress, setProgress] = useState({ loading: false, uploadInProgress: false, speed: 0, }); useEffect(() => { //Set the state of uploads to do. if (uploads) { beginUploads(uploads); setUploads(null); } }, [uploads]); async function handleOnSuccess({ duration, data }) { //If it's not in production, show a toast with the time. Toast.show({ type: "success", text1: ` Upload completed in ${duration}.`, // // text2: duration, }); if (deleteAfterUpload) { try { await MediaLibrary.deleteAssetsAsync(data); const album = await MediaLibrary.createAlbumAsync( "ImEX Mobile Deleted", data.pop(), false ); //Move the rest. if (data.length > 0) { const moveResult = await MediaLibrary.addAssetsToAlbumAsync( data, album, false ); } const deleteResult = await MediaLibrary.deleteAlbumsAsync(album); } catch (error) { console.log("Unable to delete picture.", error); Sentry.captureException(error); } } logImEXEvent("imexmobile_successful_upload"); forceRerender(); setProgress({ ...progress, speed: 0, percent: 1, uploadInProgress: false }); } function handleOnProgress({ percent, loaded }) { setProgress((progress) => ({ ...progress, speed: loaded - progress.loaded, loaded: loaded, percent, })); } function handleOnError({ assetid, error }) { logImEXEvent("imexmobile_upload_documents_error"); Toast.show({ type: "error", text1: "Unable to upload documents.", text2: error, autoHide: false, }); setProgress({ speed: 0, percent: 1, uploadInProgress: false, }); } const beginUploads = async (data) => { //Validate to make sure the totals for the file sizes do not exceed the total on the job. setProgress({ percent: 0, loaded: 0, uploadInProgress: true, start: new Date(), average: 0, }); await handleLocalUpload({ files: data, onError: ({ assetid, error }) => handleOnError({ assetid, error }), onProgress: ({ percent, loaded }) => handleOnProgress({ percent, loaded }), onSuccess: ({ duration }) => handleOnSuccess({ duration, data }), context: { jobid: selectedCameraJobId !== "temp" ? selectedCameraJobId : "temporary", }, }); }; return ( { Alert.alert("Cancel?", "Do you want to abort the upload?", [ { text: "Yes", onPress: () => { setUploads(null); setProgress(null); }, }, { text: "No" }, ]); }} > {`${formatBytes( progress.speed )}/sec`} {`Avg. ${formatBytes( progress.loaded / ((new Date() - progress.start) / 1000) )}/sec`} {`Total Uploaded ${formatBytes(progress.loaded)}`} {`Duration ${( (new Date() - progress.start) / 1000 ).toFixed(1)} sec`} ); } const styles = StyleSheet.create({ modalContainer: { display: "flex", flex: 1, justifyContent: "center", }, modal: { // flex: 1, display: "flex", marginLeft: 20, marginRight: 20, backgroundColor: "white", borderRadius: 20, padding: 18, shadowColor: "#000", shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.25, shadowRadius: 4, elevation: 5, }, });