From beb1145f98af49d3e0ce2c1c4c0f9a420319a9c7 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Fri, 31 Oct 2025 09:38:51 -0700 Subject: [PATCH] Upload improvements for imgproxy. --- app/jobs/[jobId]/_layout.tsx | 4 ++-- components/error/error-display.jsx | 2 +- components/job-documents/image-loader.jsx | 9 ++++++++- components/job-lines/job-lines.jsx | 13 +++++++++---- components/job-notes/job-notes.jsx | 2 +- components/job-tombstone/job-tombstone.jsx | 8 ++++---- components/jobs-list/job-list-item.jsx | 2 +- components/settings/settings.jsx | 8 ++++---- components/upload-progress/upload-progress.jsx | 2 +- redux/photos/photos.reducer.js | 10 ++++++++-- redux/photos/photos.sagas.js | 7 ++++--- 11 files changed, 43 insertions(+), 24 deletions(-) diff --git a/app/jobs/[jobId]/_layout.tsx b/app/jobs/[jobId]/_layout.tsx index ad92fa3..201cddb 100644 --- a/app/jobs/[jobId]/_layout.tsx +++ b/app/jobs/[jobId]/_layout.tsx @@ -13,9 +13,9 @@ function JobTabLayout() { tabBarActiveTintColor: theme.colors.primary, tabBarPosition: "top", headerShown: false, - animation: "shift", + animation: "fade", tabBarStyle: { - // marginTop: -50 + marginTop: -48, }, }} > diff --git a/components/error/error-display.jsx b/components/error/error-display.jsx index 10563a6..18a92c1 100644 --- a/components/error/error-display.jsx +++ b/components/error/error-display.jsx @@ -5,7 +5,7 @@ import { Button, Card, Text } from "react-native-paper"; export default function ErrorDisplay({ errorMessage, error, onDismiss }) { const { t } = useTranslation(); return ( - + diff --git a/components/job-documents/image-loader.jsx b/components/job-documents/image-loader.jsx index fa36f11..03eac04 100644 --- a/components/job-documents/image-loader.jsx +++ b/components/job-documents/image-loader.jsx @@ -33,7 +33,14 @@ const ImageLoader = ({ style, source, ...props }) => { if (loading) return ( <> - + {memorizedImage} ); diff --git a/components/job-lines/job-lines.jsx b/components/job-lines/job-lines.jsx index 6e4dc0c..2b2b82f 100644 --- a/components/job-lines/job-lines.jsx +++ b/components/job-lines/job-lines.jsx @@ -4,7 +4,7 @@ import { useGlobalSearchParams } from "expo-router"; import React from "react"; import { useTranslation } from "react-i18next"; import { ScrollView, useWindowDimensions } from "react-native"; -import { ActivityIndicator, DataTable } from "react-native-paper"; +import { ActivityIndicator, DataTable, useTheme } from "react-native-paper"; import ErrorDisplay from "../error/error-display"; export default function JobLines() { @@ -18,7 +18,7 @@ export default function JobLines() { }); const { width, height } = useWindowDimensions(); const isLandscape = width > height; - + const theme = useTheme(); const { t } = useTranslation(); const onRefresh = async () => { return refetch(); @@ -58,8 +58,13 @@ export default function JobLines() { - {job.joblines.map((item) => ( - + {job.joblines.map((item, index) => ( + {item.line_desc} diff --git a/components/job-notes/job-notes.jsx b/components/job-notes/job-notes.jsx index f952230..3de61bc 100644 --- a/components/job-notes/job-notes.jsx +++ b/components/job-notes/job-notes.jsx @@ -119,7 +119,7 @@ export default function JobNotes() { const NoteListItem = memo(function NoteListItem({ item }) { return ( - + {item.text} diff --git a/components/job-tombstone/job-tombstone.jsx b/components/job-tombstone/job-tombstone.jsx index dd06b84..d2906dc 100644 --- a/components/job-tombstone/job-tombstone.jsx +++ b/components/job-tombstone/job-tombstone.jsx @@ -95,7 +95,7 @@ function JobTombstone({ bodyshop }) { } > - + - + - + - + - + @@ -110,7 +110,7 @@ function Tab({ bodyshop, currentUser, signOutStart }) { - + @@ -121,7 +121,7 @@ function Tab({ bodyshop, currentUser, signOutStart }) { - + @@ -157,7 +157,7 @@ function Tab({ bodyshop, currentUser, signOutStart }) { - + {`${t("settings.labels.signedinshop")} ${ diff --git a/components/upload-progress/upload-progress.jsx b/components/upload-progress/upload-progress.jsx index 0b19beb..d5fc269 100644 --- a/components/upload-progress/upload-progress.jsx +++ b/components/upload-progress/upload-progress.jsx @@ -46,7 +46,7 @@ export function UploadProgress({ const total = Object.keys(photoUploadProgress).length; if (total === 0) return 0; const completed = Object.values(photoUploadProgress).filter( - (p) => p.progress === 100 + (p) => p.progress === 1 ).length; return completed / total; }, [photoUploadProgress]); diff --git a/redux/photos/photos.reducer.js b/redux/photos/photos.reducer.js index 52b91e3..a5e5c80 100644 --- a/redux/photos/photos.reducer.js +++ b/redux/photos/photos.reducer.js @@ -39,7 +39,7 @@ const photosReducer = (state = INITIAL_STATE, action) => { return { ...state, - progress: { ...state.progress, [action.payload.assetId]: { ...state.progress[action.payload.assetId], progress: 100, status: 'completed', endTime: new Date() } }, + progress: { ...state.progress, [action.payload.assetId]: { ...state.progress[action.payload.assetId], progress: 1, status: 'completed', endTime: new Date() } }, cancelTasks: remainingTasks }; case PhotosActionTypes.MEDIA_UPLOAD_PROGRESS_UPDATE_BULK: @@ -53,7 +53,7 @@ const photosReducer = (state = INITIAL_STATE, action) => { uploadInProgress: false, uploadError: null, photos: [], - progress: {}, + // progress: {}, cancelTasks: {} }; case PhotosActionTypes.CLEAR_UPLOAD_ERROR: @@ -83,6 +83,12 @@ const photosReducer = (state = INITIAL_STATE, action) => { ...state, cancelTriggered: true, }; + case PhotosActionTypes.DELETE_MEDIA_SUCCESS: { + return { + ...state, + progress: {}, //Clear it here so we only delete photos that were successful. + } + } default: return state; } diff --git a/redux/photos/photos.sagas.js b/redux/photos/photos.sagas.js index 1f45643..5a3a304 100644 --- a/redux/photos/photos.sagas.js +++ b/redux/photos/photos.sagas.js @@ -243,6 +243,7 @@ function* uploadToLocalMediaServer(photos, bodyshop, jobid) { } catch (error) { console.log("Uncaught error", error); } + } function* uploadToImageProxy(photo, photoBlob, extension, key, bodyshop, jobid) { @@ -297,7 +298,6 @@ function* uploadToImageProxy(photo, photoBlob, extension, key, bodyshop, jobid) const sent = progressData.totalBytesSent; const total = progressData.totalBytesExpectedToSend; const progress = sent / total; - console.log(progress, sent) store.dispatch(mediaUploadProgressOne({ ...photo, progress, loaded: sent })); // onUpload(Number(progress.toFixed(2)) * 100); }, @@ -347,7 +347,7 @@ function* uploadToImageProxy(photo, photoBlob, extension, key, bodyshop, jobid) ], }, })); - console.log("Upload and record creation successful for", photo.uri); + } else { console.log("Error uploading to Cloud", uploadResult); throw new Error(`Cloud upload failed: ${uploadResult}`); @@ -393,8 +393,9 @@ function* mediaUploadCompletedAction({ payload: photos }) { } try { + const progress = yield select((state) => state.photos.progress); // Handle the completion of media uploads - const filesToDelete = [...photos] + const filesToDelete = Object.keys(progress).filter((key) => progress[key].status === 'completed').map((key) => progress[key]); if (Platform.OS === "android") { //Create a new asset with the first file to delete.