Update sentry lines and comment new image picker.

This commit is contained in:
Patrick Fic
2025-05-30 13:55:18 -07:00
parent 895091468a
commit 00002ed0f5
11 changed files with 146 additions and 62 deletions

3
App.js
View File

@@ -1,3 +1,4 @@
import 'expo-dev-client';
import { ApolloProvider } from "@apollo/client"; import { ApolloProvider } from "@apollo/client";
import * as Sentry from "@sentry/react-native"; import * as Sentry from "@sentry/react-native";
import "expo-asset"; import "expo-asset";
@@ -26,7 +27,7 @@ Sentry.init({
enableInExpoDevelopment: true, enableInExpoDevelopment: true,
// tracesSampleRate: 0.2, // tracesSampleRate: 0.2,
// integrations: [ // integrations: [
// new Sentry.Native.ReactNativeTracing({ // new Sentry.ReactNativeTracing({
// tracingOrigins: ["localhost", "imex.online", "cloudinary.com", /^\//], // tracingOrigins: ["localhost", "imex.online", "cloudinary.com", /^\//],
// // ... other options // // ... other options
// }), // }),

View File

@@ -82,6 +82,12 @@
"isAccessMediaLocationEnabled": "true" "isAccessMediaLocationEnabled": "true"
} }
], ],
[
"expo-image-picker",
{
"photosPermission": "Allow $(PRODUCT_NAME) to access your photos and upload them to the system."
}
],
"expo-localization", "expo-localization",
"expo-font" "expo-font"
] ]

View File

@@ -101,7 +101,7 @@ async function getPhotos({ bodyshop, jobid, setImages }) {
setImages(normalizedImages); setImages(normalizedImages);
} catch (error) { } catch (error) {
Sentry.Native.captureException(error); Sentry.captureException(error);
Toast.show({ Toast.show({
type: "error", type: "error",
text1: `Error fetching photos.`, text1: `Error fetching photos.`,

View File

@@ -18,6 +18,9 @@ import JobSpaceAvailable from "../job-space-available/job-space-available.compon
import UploadProgressLocal from "../upload-progress-local/upload-progress-local.component"; import UploadProgressLocal from "../upload-progress-local/upload-progress-local.component";
import UploadDeleteSwitch from "../upload-delete-switch/upload-delete-switch.component"; import UploadDeleteSwitch from "../upload-delete-switch/upload-delete-switch.component";
import UploadProgress from "../upload-progress/upload-progress.component"; import UploadProgress from "../upload-progress/upload-progress.component";
// import * as ImagePicker from "expo-image-picker";
// import { Button } from "react-native-paper";
// import * as MediaLibrary from "expo-media-library";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
selectedCameraJobId: selectCurrentCameraJobId, selectedCameraJobId: selectCurrentCameraJobId,
@@ -38,12 +41,29 @@ export function ImageBrowserScreen({
const { t } = useTranslation(); const { t } = useTranslation();
const [uploads, setUploads] = useState(null); const [uploads, setUploads] = useState(null);
const [tick, setTick] = useState(0); const [tick, setTick] = useState(0);
// const [medialLibraryPermissionStatus, requestmediaLibraryPermission] =
// ImagePicker.useMediaLibraryPermissions();
const forceRerender = useCallback(() => { const forceRerender = useCallback(() => {
setTick((tick) => tick + 1); setTick((tick) => tick + 1);
}, []); }, []);
const onDone = (data) => { const onDone = (data) => {
logImEXEvent("imexmobile_upload_documents", { count: data.length }); logImEXEvent("imexmobile_upload_documents", { count: data.length });
// const uploads = await Promise.all(
// data.map(async (item) => {
// let id = item.id || item.fileName;
// if (!item.id && item.uri) {
// id = await getAssetIdFromUri(item.uri, item.fileName);
// }
// return {
// ...item,
// localUri: item.uri,
// id,
// };
// })
// );
// console.log("onDone", uploads);
if (data.length !== 0) setUploads(data); if (data.length !== 0) setUploads(data);
}; };
@@ -73,25 +93,6 @@ export function ImageBrowserScreen({
[] []
); );
const widgetResize = useMemo(
() => ({
width: 50,
compress: 0.7,
base64: false,
saveTo: "jpeg",
}),
[]
);
const _textStyle = {
color: "white",
};
const _buttonStyle = {
backgroundColor: "orange",
borderRadius: 5,
};
const widgetNavigator = useMemo( const widgetNavigator = useMemo(
() => ({ () => ({
Texts: { Texts: {
@@ -134,6 +135,33 @@ export function ImageBrowserScreen({
[] []
); );
// const handleSelectPhotos = async () => {
// let result = await ImagePicker.launchImageLibraryAsync({
// mediaTypes: ["images", "videos"],
// allowsMultipleSelection: true,
// // aspect: [4, 3],
// });
// console.log("*** ~ handleSelectPhotos ~ result:", result);
// if (!result.canceled) {
// const uploads = await Promise.all(
// result.assets.map(async (item) => {
// let id = item.id || item.fileName;
// if (!item.id && item.uri) {
// id = await getAssetIdFromUri(item.uri);
// }
// return {
// ...item,
// localUri: item.uri,
// id,
// };
// })
// );
// console.log("Uploads from handleSelectPhotos", uploads);
// setUploads(uploads);
// }
// };
return ( return (
<View style={[styles.flex, styles.container]}> <View style={[styles.flex, styles.container]}>
<CameraSelectJob /> <CameraSelectJob />
@@ -147,16 +175,6 @@ export function ImageBrowserScreen({
<JobSpaceAvailable jobid={selectedCameraJobId} key={`${tick}-space`} /> <JobSpaceAvailable jobid={selectedCameraJobId} key={`${tick}-space`} />
)} )}
<UploadDeleteSwitch /> <UploadDeleteSwitch />
{
// <Button
// onPress={() => {
// //Mutate the state
// toggleDeleteAfterUpload();
// }}
// >
// <Text>{`From screen. ${deleteAfterUpload}`}</Text>
// </Button>
}
{!selectedCameraJobId && ( {!selectedCameraJobId && (
<View <View
style={{ style={{
@@ -270,3 +288,32 @@ export default connect(mapStateToProps, mapDispatchToProps)(ImageBrowserScreen);
// }, // },
// }, // },
// }} // }}
// // Utility to get asset ID from URI if missing
// async function getAssetIdFromUri(uri, filename = null, maxPages = 10) {
// let after = null;
// let found = null;
// let pageCount = 0;
// while (!found && pageCount < maxPages) {
// const page = await MediaLibrary.getAssetsAsync({
// first: 100,
// mediaType: [MediaLibrary.MediaType.photo, MediaLibrary.MediaType.video],
// after,
// });
// // Try to match by URI
// found = page.assets.find((asset) => asset.uri === uri);
// // Fallback: try to match by filename if not found and filename is available
// if (!found && filename) {
// found = page.assets.find((asset) => asset.filename === filename);
// }
// after = page.endCursor;
// pageCount++;
// if (!after) break;
// }
// return found ? found.id : null;
// }

View File

@@ -79,7 +79,7 @@ export function UploadProgress({
const deleteResult = await MediaLibrary.deleteAlbumsAsync(album); const deleteResult = await MediaLibrary.deleteAlbumsAsync(album);
} catch (error) { } catch (error) {
console.log("Unable to delete picture.", error); console.log("Unable to delete picture.", error);
Sentry.Native.captureException(error); Sentry.captureException(error);
} }
} }

View File

@@ -132,10 +132,14 @@ export function UploadProgress({
const data = []; const data = [];
const totalOfUploads = await selectedFiles.reduce(async (acc, val) => { const totalOfUploads = await selectedFiles.reduce(async (acc, val) => {
//Get the size of the file based on URI. //Get the size of the file based on URI.
const info = await FileSystem.getInfoAsync(val.uri, { size: true }); if (acc.fileSize) {
data.push({ ...info, ...val }); //Add in the size. return acc + acc.fileSize;
val.albumId && MediaLibrary.migrateAlbumIfNeededAsync(val.albumId); } else {
return (await acc) + info.size; const info = await FileSystem.getInfoAsync(val.uri, { size: true });
data.push({ ...info, ...val }); //Add in the size.
val.albumId && MediaLibrary.migrateAlbumIfNeededAsync(val.albumId);
return (await acc) + info.size;
}
}, 0); }, 0);
if (selectedCameraJobId !== "temp") { if (selectedCameraJobId !== "temp") {
@@ -231,7 +235,7 @@ export function UploadProgress({
} }
} catch (error) { } catch (error) {
console.log("Unable to delete picture.", error); console.log("Unable to delete picture.", error);
Sentry.Native.captureException(error); Sentry.captureException(error);
} }
} }
filesToDelete = []; filesToDelete = [];

13
package-lock.json generated
View File

@@ -34,6 +34,7 @@
"expo-file-system": "~18.0.10", "expo-file-system": "~18.0.10",
"expo-font": "~13.0.3", "expo-font": "~13.0.3",
"expo-image-manipulator": "~13.0.6", "expo-image-manipulator": "~13.0.6",
"expo-image-picker": "~16.0.6",
"expo-images-picker": "^2.5.1", "expo-images-picker": "^2.5.1",
"expo-localization": "~16.0.1", "expo-localization": "~16.0.1",
"expo-media-library": "~17.0.6", "expo-media-library": "~17.0.6",
@@ -9506,6 +9507,18 @@
"expo": "*" "expo": "*"
} }
}, },
"node_modules/expo-image-picker": {
"version": "16.0.6",
"resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-16.0.6.tgz",
"integrity": "sha512-HN4xZirFjsFDIsWFb12AZh19fRzuvZjj2ll17cGr19VNRP06S/VPQU3Tdccn5vwUzQhOBlLu704CnNm278boiQ==",
"license": "MIT",
"dependencies": {
"expo-image-loader": "~5.0.0"
},
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-images-picker": { "node_modules/expo-images-picker": {
"version": "2.5.1", "version": "2.5.1",
"resolved": "https://registry.npmjs.org/expo-images-picker/-/expo-images-picker-2.5.1.tgz", "resolved": "https://registry.npmjs.org/expo-images-picker/-/expo-images-picker-2.5.1.tgz",

View File

@@ -89,7 +89,8 @@
"redux-logger": "^3.0.6", "redux-logger": "^3.0.6",
"redux-persist": "^6.0.0", "redux-persist": "^6.0.0",
"redux-saga": "^1.3.0", "redux-saga": "^1.3.0",
"reselect": "^5.1.1" "reselect": "^5.1.1",
"expo-image-picker": "~16.0.6"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.26.8", "@babel/core": "^7.26.8",

View File

@@ -108,7 +108,7 @@ export function* onSignInSuccess() {
export function* signInSuccessSaga({ payload }) { export function* signInSuccessSaga({ payload }) {
try { try {
// Analytics.setUserId(payload.email);//JF:commenting out the firebase analytics portion // Analytics.setUserId(payload.email);//JF:commenting out the firebase analytics portion
//Sentry.Native.setUser({ email: payload.email }); //Sentry.setUser({ email: payload.email });
const shop = yield client.query({ query: QUERY_BODYSHOP }); const shop = yield client.query({ query: QUERY_BODYSHOP });
logImEXEvent("imexmobile_sign_in_success", payload); logImEXEvent("imexmobile_sign_in_success", payload);
@@ -123,7 +123,7 @@ export function* signInSuccessSaga({ payload }) {
// ); // );
} catch (error) { } catch (error) {
console.log("UH-OH. Couldn't get shop details.", error); console.log("UH-OH. Couldn't get shop details.", error);
Sentry.Native.captureException(error); Sentry.captureException(error);
} }
} }

View File

@@ -17,29 +17,30 @@ cleanAxios.interceptors.request.eject(axiosAuthInterceptorId);
export const handleUpload = async (ev, context) => { export const handleUpload = async (ev, context) => {
const { mediaId, onError, onSuccess, onProgress } = ev; const { mediaId, onError, onSuccess, onProgress } = ev;
const { bodyshop, jobId } = context; const { bodyshop, jobId } = context;
try {
const imageData = await MediaLibrary.getAssetInfoAsync(mediaId); const imageData = await MediaLibrary.getAssetInfoAsync(mediaId);
const newFile = await ( const newFile = await (
await fetch(imageData.localUri || imageData.uri) await fetch(imageData.localUri || imageData.uri)
).blob(); ).blob();
let extension = imageData.localUri.split(".").pop(); let extension = imageData.localUri.split(".").pop();
//Default to Cloudinary in case of split treatment errors. //Default to Cloudinary in case of split treatment errors.
let destination = let destination =
splitClient?.getTreatment("Imgproxy") === "on" ? "imgproxy" : "cloudinary"; splitClient?.getTreatment("Imgproxy") === "on" ? "imgproxy" : "cloudinary";
let key = let key =
destination === "imgproxy" destination === "imgproxy"
? `${bodyshop.id}/${jobId}/${replaceAccents( ? `${bodyshop.id}/${jobId}/${replaceAccents(
imageData.filename || imageData.uri.split("/").pop() imageData.filename || imageData.uri.split("/").pop()
).replace(/[^A-Z0-9]+/gi, "_")}-${new Date().getTime()}.${extension}` ).replace(/[^A-Z0-9]+/gi, "_")}-${new Date().getTime()}.${extension}`
: `${bodyshop.id}/${jobId}/${( : `${bodyshop.id}/${jobId}/${(
imageData.filename || imageData.uri.split("/").pop() imageData.filename || imageData.uri.split("/").pop()
).replace(/\.[^/.]+$/, "")}-${new Date().getTime()}`; ).replace(/\.[^/.]+$/, "")}-${new Date().getTime()}`;
const res = const res =
destination === "imgproxy" destination === "imgproxy"
? await uploadToImgproxy( ? await uploadToImgproxy(
key, key,
mediaId, mediaId,
imageData, imageData,
@@ -51,7 +52,7 @@ export const handleUpload = async (ev, context) => {
onProgress, onProgress,
context context
) )
: await uploadToCloudinary( : await uploadToCloudinary(
key, key,
mediaId, mediaId,
imageData, imageData,
@@ -63,7 +64,18 @@ export const handleUpload = async (ev, context) => {
onProgress, onProgress,
context context
); );
return res; return res;
} catch (error) {
console.log("Error creating upload promise", error.message, error.stack);
if (onError) onError(error.message);
Sentry.captureException(error);
return {
success: false,
error: error.message,
stack: error.stack,
mediaId,
};
}
}; };
export const handleUploadImgproxy = async (ev, context) => { export const handleUploadImgproxy = async (ev, context) => {
@@ -196,7 +208,7 @@ export const uploadToImgproxy = async (
stack: error.stack, stack: error.stack,
mediaId, mediaId,
}; };
Sentry.Native.captureException(error); Sentry.captureException(error);
} }
const documentInsert = await client.mutate({ const documentInsert = await client.mutate({
@@ -270,7 +282,7 @@ export const uploadToCloudinary = async (
}); });
} catch (error) { } catch (error) {
console.log("ERROR GETTING SIGNED URL", error); console.log("ERROR GETTING SIGNED URL", error);
Sentry.Native.captureException(error); Sentry.captureException(error);
return { success: false, error: error }; return { success: false, error: error };
} }
@@ -319,7 +331,7 @@ export const uploadToCloudinary = async (
); );
} catch (error) { } catch (error) {
console.log("CLOUDINARY error", error.response, cloudinaryUploadResponse); console.log("CLOUDINARY error", error.response, cloudinaryUploadResponse);
Sentry.Native.captureException(error); Sentry.captureException(error);
if (onError) onError(error.message); if (onError) onError(error.message);
return { success: false, error: error }; return { success: false, error: error };

View File

@@ -96,14 +96,14 @@ export const handleLocalUpload = async ({
}); });
} }
} catch (error) { } catch (error) {
Sentry.Native.captureException(error); Sentry.captureException(error);
console.log("Error uploading documents:", error.message); console.log("Error uploading documents:", error.message);
onError && onError({ error: error.message }); onError && onError({ error: error.message });
} }
} catch (error) { } catch (error) {
console.log("Uncaught error", error); console.log("Uncaught error", error);
Sentry.Native.captureException(error); Sentry.captureException(error);
onError && onError({ error: error.message }); onError && onError({ error: error.message });
} }