import { useTheme } from "@/hooks"; import { cancelUploads, clearUploadError } from "@/redux/photos/photos.actions"; import { formatBytes } from "@/util/uploadUtils"; import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { ScrollView, StyleSheet, View } from "react-native"; import { Button, Divider, Modal, Portal, ProgressBar, Text, } from "react-native-paper"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectPhotos, selectUploadError, selectUploadProgress, } from "../../redux/photos/photos.selectors"; const mapStateToProps = createStructuredSelector({ photos: selectPhotos, photoUploadProgress: selectUploadProgress, uploadError: selectUploadError, }); const mapDispatchToProps = (dispatch) => ({ clearError: () => dispatch(clearUploadError()), cancelUploads: () => dispatch(cancelUploads()), }); export default connect(mapStateToProps, mapDispatchToProps)(UploadProgress); export function UploadProgress({ photos, photoUploadProgress, uploadError, clearError, cancelUploads, }) { const { t } = useTranslation(); const theme = useTheme(); const completion = useMemo(() => { const total = Object.keys(photoUploadProgress).length; if (total === 0) return 0; const completed = Object.values(photoUploadProgress).filter( (p) => p.progress === 100 ).length; return completed / total; }, [photoUploadProgress]); const handleCancelUploads = () => { cancelUploads(); }; return ( 0} style={styles.modalOuter} // add contentContainerStyle={[ styles.modalContainer, { backgroundColor: theme.colors.elevation.level1 }, ]} > {t("general.labels.upload")} {`${t("general.labels.uploadprogress")} ${Math.round( completion * 100 )}%`} {Object.keys(photoUploadProgress).map((key) => ( {photoUploadProgress[key].fileName} {`${formatBytes( photoUploadProgress[key].loaded / (((photoUploadProgress[key].endTime || new Date()) - photoUploadProgress[key].startTime) / 1000) )}/sec`} ))} ); } const styles = StyleSheet.create({ modalOuter: { flex: 1, // ensure outer container can grow, paddingHorizontal: 24, paddingVertical: 72, }, modalContainer: { width: "100%", height: "50%", // force full area (important for iOS) padding: 24, justifyContent: "center", borderRadius: 24, }, modalFill: { flex: 1, }, speedRow: { flexDirection: "row", alignItems: "center", }, title: { alignSelf: "center", alignItems: "center", marginBottom: 12, paddingLeft: 12, paddingRight: 12, }, progressItem: { display: "flex", flexDirection: "row", alignItems: "center", marginBottom: 12, marginLeft: 12, marginRight: 12, }, progressText: { flex: 1, flexShrink: 1, }, progressBarContainer: { flex: 3, marginLeft: 12, marginRight: 12, }, });