diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..e9ee3cb --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +legacy-peer-deps=true \ No newline at end of file diff --git a/App.js b/App.js index 3341959..ee1019e 100644 --- a/App.js +++ b/App.js @@ -1,9 +1,9 @@ import { ApolloProvider } from "@apollo/client"; import React from "react"; -import { DefaultTheme, Provider as PaperProvider } from "react-native-paper"; +import { MD2LightTheme as DefaultTheme, Provider as PaperProvider } from "react-native-paper"; import { Provider } from "react-redux"; import { PersistGate } from "redux-persist/integration/react"; -import * as Sentry from "sentry-expo"; +import * as Sentry from '@sentry/react-native'; import ScreenMainComponent from "./components/screen-main/screen-main.component"; import { logImEXEvent } from "./firebase/firebase.analytics"; import { client } from "./graphql/client"; @@ -17,17 +17,16 @@ import { SafeAreaProvider } from "react-native-safe-area-context"; Sentry.init({ dsn: "https://4866820768550ca396e849fa325e84d6@o492140.ingest.sentry.io/4505637419614208", enableInExpoDevelopment: true, - tracesSampleRate: 0.2, - integrations: [ - new Sentry.Native.ReactNativeTracing({ - tracingOrigins: ["localhost", "romeonline.io", "cloudinary.com", /^\//], - // ... other options - }), - ], + // tracesSampleRate: 0.2, + // integrations: [ + // new Sentry.Native.ReactNativeTracing({ + // tracingOrigins: ["localhost", "imex.online", "cloudinary.com", /^\//], + // // ... other options + // }), + // ], debug: true, // Sentry will try to print out useful debugging information if something goes wrong with sending an event. Set this to `false` in production. }); -Sentry.Native.nativeCrash(); const theme = { ...DefaultTheme, @@ -38,7 +37,7 @@ const theme = { }, }; -export default class App extends React.Component { +class App extends React.Component { async componentDidMount() { logImEXEvent("imexmobile_app_start"); } @@ -60,3 +59,4 @@ export default class App extends React.Component { ); } } +export default Sentry.wrap(App); \ No newline at end of file diff --git a/app.json b/app.json index ac06b51..5ab92fd 100644 --- a/app.json +++ b/app.json @@ -11,6 +11,7 @@ }, "orientation": "default", "icon": "./assets/RomeIcon.png", + "platforms": ["ios", "android"], "ios": { "supportsTablet": true, "bundleIdentifier": "com.rome.mobile", @@ -43,6 +44,7 @@ "url": "https://u.expo.dev/df105e21-a07f-4425-af10-2200a7704a48" }, "assetBundlePatterns": ["**/*"], + "assetBundlePatterns": ["**/*"], "web": { "favicon": "./assets/RomeIcon.png", "config": { @@ -58,11 +60,15 @@ } }, "description": "", - "hooks": { - "postPublish": [] - }, "plugins": [ - "sentry-expo", + [ + "@sentry/react-native/expo", + { + "url": "https://sentry.io/", + "organization": "imex", + "project": "imexmobile" + } + ], [ "expo-media-library", { diff --git a/components/camera-select-job/camera-select-job.component.jsx b/components/camera-select-job/camera-select-job.component.jsx index d19058f..0e9c6bd 100644 --- a/components/camera-select-job/camera-select-job.component.jsx +++ b/components/camera-select-job/camera-select-job.component.jsx @@ -109,7 +109,7 @@ export function CameraSelectJob({ }} > diff --git a/components/local-upload-progress/local-upload-progress.component.jsx b/components/local-upload-progress/local-upload-progress.component.jsx index 4729cd6..ab237f0 100644 --- a/components/local-upload-progress/local-upload-progress.component.jsx +++ b/components/local-upload-progress/local-upload-progress.component.jsx @@ -1,5 +1,5 @@ -import * as MediaLibrary from "expo-media-library"; -import React, { useEffect, useState } from "react"; +import * as MediaLibrary from 'expo-media-library'; +import React, { useEffect, useState } from 'react'; import { ActivityIndicator, @@ -8,20 +8,20 @@ import { 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"; +} 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-expo"; +} 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"; +import { formatBytes } from '../../util/document-upload.utility'; +import { handleLocalUpload } from '../../util/local-document-upload.utility'; const mapStateToProps = createStructuredSelector({ selectedCameraJobId: selectCurrentCameraJobId, @@ -54,7 +54,7 @@ export function UploadProgress({ async function handleOnSuccess({ duration, data }) { //If it's not in production, show a toast with the time. Toast.show({ - type: "success", + type: 'success', text1: ` Upload completed in ${duration}.`, // // text2: duration, @@ -62,13 +62,28 @@ export function UploadProgress({ 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); + console.log('Unable to delete picture.', error); Sentry.Native.captureException(error); } } - logImEXEvent("imexmobile_successful_upload"); + logImEXEvent('imexmobile_successful_upload'); forceRerender(); setProgress({ ...progress, speed: 0, percent: 1, uploadInProgress: false }); } @@ -83,10 +98,10 @@ export function UploadProgress({ } function handleOnError({ assetid, error }) { - logImEXEvent("imexmobile_upload_documents_error"); + logImEXEvent('imexmobile_upload_documents_error'); Toast.show({ - type: "error", - text1: "Unable to upload documents.", + type: 'error', + text1: 'Unable to upload documents.', text2: error, autoHide: false, }); @@ -115,7 +130,7 @@ export function UploadProgress({ onSuccess: ({ duration }) => handleOnSuccess({ duration, data }), context: { jobid: - selectedCameraJobId !== "temp" ? selectedCameraJobId : "temporary", + selectedCameraJobId !== 'temp' ? selectedCameraJobId : 'temporary', }, }); }; @@ -123,41 +138,41 @@ export function UploadProgress({ return ( { - Alert.alert("Cancel?", "Do you want to abort the upload?", [ + Alert.alert('Cancel?', 'Do you want to abort the upload?', [ { - text: "Yes", + text: 'Yes', onPress: () => { setUploads(null); setProgress(null); }, }, - { text: "No" }, + { text: 'No' }, ]); }} > - + - {`${formatBytes( + {`${formatBytes( progress.speed )}/sec`} {`Avg. ${formatBytes( progress.loaded / ((new Date() - progress.start) / 1000) )}/sec`} {`Total Uploaded ${formatBytes(progress.loaded)}`} - {`Duration ${( + {`Duration ${( (new Date() - progress.start) / 1000 ).toFixed(1)} sec`} @@ -168,19 +183,19 @@ export function UploadProgress({ } const styles = StyleSheet.create({ modalContainer: { - display: "flex", + display: 'flex', flex: 1, - justifyContent: "center", + justifyContent: 'center', }, modal: { // flex: 1, - display: "flex", + display: 'flex', marginLeft: 20, marginRight: 20, - backgroundColor: "white", + backgroundColor: 'white', borderRadius: 20, padding: 18, - shadowColor: "#000", + shadowColor: '#000', shadowOffset: { width: 0, height: 2, diff --git a/components/screen-main/screen-main.component.jsx b/components/screen-main/screen-main.component.jsx index 83ab488..4288812 100644 --- a/components/screen-main/screen-main.component.jsx +++ b/components/screen-main/screen-main.component.jsx @@ -92,7 +92,7 @@ const JobsTabNavigator = connect( navigation.navigate("MediaBrowserTab"); }} > - + ), })} @@ -191,11 +191,11 @@ const BottomTabsNavigator = () => ( tabBarIcon: ({ color, size }) => { let iconName; if (route.name === "JobTab") { - iconName = "ios-list"; + iconName = "list"; } else if (route.name === "MoreTab") { - iconName = "ios-settings"; + iconName = "settings"; } else if (route.name === "MediaBrowserTab") { - iconName = "ios-camera"; + iconName = "camera"; } else if (route.name === "TimeTicketBrowserTab") { iconName = "ios-stopwatch-outline"; } else { diff --git a/components/screen-media-browser/screen-media-browser.component.jsx b/components/screen-media-browser/screen-media-browser.component.jsx index 6810a35..daf1206 100644 --- a/components/screen-media-browser/screen-media-browser.component.jsx +++ b/components/screen-media-browser/screen-media-browser.component.jsx @@ -1,26 +1,40 @@ -import { Ionicons } from "@expo/vector-icons"; -import { AssetsSelector } from "expo-images-picker"; -import React, { useCallback, useMemo, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { StyleSheet, Text, View } from "react-native"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { logImEXEvent } from "../../firebase/firebase.analytics"; -import { selectCurrentCameraJobId } from "../../redux/app/app.selectors"; -import CameraSelectJob from "../camera-select-job/camera-select-job.component"; -import JobSpaceAvailable from "../job-space-available/job-space-available.component"; -import UploadDeleteSwitch from "../upload-delete-switch/upload-delete-switch.component"; -import UploadProgress from "../upload-progress/upload-progress.component"; -import { MediaType } from "expo-media-library"; -import { selectBodyshop } from "../../redux/user/user.selectors"; -import LocalUploadProgress from "../local-upload-progress/local-upload-progress.component"; +import { Ionicons } from '@expo/vector-icons'; +import { AssetsSelector } from 'expo-images-picker'; +import { MediaType } from 'expo-media-library'; +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { StyleSheet, Text, View } from 'react-native'; +import { connect } from 'react-redux'; +import { createStructuredSelector } from 'reselect'; +import { logImEXEvent } from '../../firebase/firebase.analytics'; +import { toggleDeleteAfterUpload } from '../../redux/app/app.actions'; +import { + selectCurrentCameraJobId, + selectDeleteAfterUpload, +} from '../../redux/app/app.selectors'; +import { selectBodyshop } from '../../redux/user/user.selectors'; +import CameraSelectJob from '../camera-select-job/camera-select-job.component'; +import JobSpaceAvailable from '../job-space-available/job-space-available.component'; +import LocalUploadProgress from '../local-upload-progress/local-upload-progress.component'; +import UploadDeleteSwitch from '../upload-delete-switch/upload-delete-switch.component'; +import UploadProgress from '../upload-progress/upload-progress.component'; const mapStateToProps = createStructuredSelector({ selectedCameraJobId: selectCurrentCameraJobId, bodyshop: selectBodyshop, + deleteAfterUpload: selectDeleteAfterUpload, }); -export function ImageBrowserScreen({ bodyshop, selectedCameraJobId }) { +const mapDispatchToProps = (dispatch) => ({ + toggleDeleteAfterUpload: () => dispatch(toggleDeleteAfterUpload()), +}); + +export function ImageBrowserScreen({ + bodyshop, + selectedCameraJobId, + //toggleDeleteAfterUpload, + // deleteAfterUpload, +}) { const { t } = useTranslation(); const [uploads, setUploads] = useState(null); const [tick, setTick] = useState(0); @@ -29,18 +43,18 @@ export function ImageBrowserScreen({ bodyshop, selectedCameraJobId }) { }, []); const onDone = (data) => { - logImEXEvent("imexmobile_upload_documents", { count: data.length }); + logImEXEvent('imexmobile_upload_documents', { count: data.length }); if (data.length !== 0) setUploads(data); }; const widgetErrors = useMemo( () => ({ - errorTextColor: "black", + errorTextColor: 'black', errorMessages: { - hasErrorWithPermissions: "Please Allow media gallery permissions.", - hasErrorWithLoading: "There was an error while loading images.", - hasErrorWithResizing: "There was an error while loading images.", - hasNoAssets: "No images found.", + hasErrorWithPermissions: 'Please Allow media gallery permissions.', + hasErrorWithLoading: 'There was an error while loading images.', + hasErrorWithResizing: 'There was an error while loading images.', + hasNoAssets: 'No images found.', }, }), [] @@ -64,28 +78,28 @@ export function ImageBrowserScreen({ bodyshop, selectedCameraJobId }) { width: 50, compress: 0.7, base64: false, - saveTo: "jpeg", + saveTo: 'jpeg', }), [] ); const _textStyle = { - color: "white", + color: 'white', }; const _buttonStyle = { - backgroundColor: "orange", + backgroundColor: 'orange', borderRadius: 5, }; const widgetNavigator = useMemo( () => ({ Texts: { - finish: t("mediabrowser.actions.upload"), - back: t("mediabrowser.actions.refresh"), - selected: "selected", + finish: t('mediabrowser.actions.upload'), + back: t('mediabrowser.actions.refresh'), + selected: 'selected', }, - midTextColor: "black", + midTextColor: 'black', minSelection: 1, buttonTextStyle: styles.textStyle, buttonStyle: styles.buttonStyle, @@ -100,20 +114,20 @@ export function ImageBrowserScreen({ bodyshop, selectedCameraJobId }) { const widgetStyles = useMemo( () => ({ margin: 2, - bgColor: "white", - spinnerColor: "blue", + bgColor: 'white', + spinnerColor: 'blue', widgetWidth: 99, videoIcon: { Component: Ionicons, - iconName: "ios-videocam", - color: "white", + iconName: 'videocam', + color: 'white', size: 20, }, selectedIcon: { Component: Ionicons, - iconName: "ios-checkmark-circle-outline", - color: "white", - bg: "rgba(35,35,35, 0.75)", + iconName: 'checkmark-circle-outline', + color: 'white', + bg: 'rgba(35,35,35, 0.75)', size: 32, }, }), @@ -125,7 +139,7 @@ export function ImageBrowserScreen({ bodyshop, selectedCameraJobId }) { {bodyshop.uselocalmediaserver ? ( - {t("mediabrowser.labels.localserver", { + {t('mediabrowser.labels.localserver', { url: bodyshop.localmediaserverhttp, })} @@ -133,15 +147,25 @@ export function ImageBrowserScreen({ bodyshop, selectedCameraJobId }) { )} + { + // + } {!selectedCameraJobId && ( - {t("mediabrowser.labels.selectjobassetselector")} + {t('mediabrowser.labels.selectjobassetselector')} )} {selectedCameraJobId && ( @@ -176,7 +200,7 @@ const styles = StyleSheet.create({ flex: 1, }, container: { - display: "flex", + display: 'flex', // position: "relative", }, buttonStyle: { @@ -184,11 +208,11 @@ const styles = StyleSheet.create({ }, // eslint-disable-next-line react-native/no-color-literals textStyle: { - color: "dodgerblue", + color: 'dodgerblue', }, }); -export default connect(mapStateToProps, null)(ImageBrowserScreen); +export default connect(mapStateToProps, mapDispatchToProps)(ImageBrowserScreen); // options={{ // assetsType: ["photo", "video"], diff --git a/components/screen-settings/screen-settings.component.jsx b/components/screen-settings/screen-settings.component.jsx index 07bafd6..6ce2b15 100644 --- a/components/screen-settings/screen-settings.component.jsx +++ b/components/screen-settings/screen-settings.component.jsx @@ -25,7 +25,7 @@ export default function ScreenSettingsComponent() { })} - Release Channel {Updates.releaseChannel} + Release Channel {Updates.channel} {/*