Base functionality with SDK44.

This commit is contained in:
Patrick Fic
2022-05-10 18:28:14 -07:00
parent a6d98f734e
commit 717b75a1b8
13 changed files with 4382 additions and 3632 deletions

2
App.js
View File

@@ -12,6 +12,7 @@ import "intl";
import "intl/locale-data/jsonp/en"; import "intl/locale-data/jsonp/en";
import "./translations/i18n"; import "./translations/i18n";
import "expo-asset"; import "expo-asset";
import Toast from "react-native-toast-message";
Sentry.init({ Sentry.init({
dsn: "https://8d6c3de1940a4e4f8b81cf4d2150bdea@o492140.ingest.sentry.io/5558869", dsn: "https://8d6c3de1940a4e4f8b81cf4d2150bdea@o492140.ingest.sentry.io/5558869",
@@ -42,6 +43,7 @@ export default class App extends React.Component {
<ApolloProvider client={client}> <ApolloProvider client={client}>
<PaperProvider theme={theme}> <PaperProvider theme={theme}>
<ScreenMainComponent /> <ScreenMainComponent />
<Toast />
</PaperProvider> </PaperProvider>
</ApolloProvider> </ApolloProvider>
</PersistGate> </PersistGate>

View File

@@ -23,6 +23,7 @@ export function JobListComponent({ bodyshop }) {
statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"], statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"],
}, },
skip: !bodyshop, skip: !bodyshop,
notifyOnNetworkStatusChange: true,
}); });
const onRefresh = async () => { const onRefresh = async () => {
@@ -32,7 +33,6 @@ export function JobListComponent({ bodyshop }) {
if (loading) return <LoadingDisplay />; if (loading) return <LoadingDisplay />;
if (error) return <ErrorDisplay errorMessage={error.message} />; if (error) return <ErrorDisplay errorMessage={error.message} />;
if (data && data.jobs && data.jobs.length === 0) if (data && data.jobs && data.jobs.length === 0)
return ( return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}> <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>

View File

@@ -26,6 +26,7 @@ import {
} from "../../redux/user/user.selectors"; } from "../../redux/user/user.selectors";
import { formatBytes } from "../../util/document-upload.utility"; import { formatBytes } from "../../util/document-upload.utility";
import { handleLocalUpload } from "../../util/local-document-upload.utility"; import { handleLocalUpload } from "../../util/local-document-upload.utility";
import Toast from "react-native-toast-message";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser, currentUser: selectCurrentUser,
@@ -103,8 +104,13 @@ export function UploadProgress({
}, },
})); }));
} }
function handleOnError(id) { function handleOnError(id, error) {
logImEXEvent("imexmobile_upload_documents_error"); logImEXEvent("imexmobile_upload_documents_error");
Toast.show({
type: "error",
text1: "Unable to upload documents.",
text2: (error && error.message) || JSON.stringify(error),
});
setProgress((progress) => ({ setProgress((progress) => ({
...progress, ...progress,
action: t("mediabrowser.labels.converting"), action: t("mediabrowser.labels.converting"),
@@ -191,7 +197,7 @@ export function UploadProgress({
ev: { ev: {
filename, filename,
mediaId: p.id, mediaId: p.id,
onError: () => handleOnError(p.id), onError: (error) => handleOnError(p.id, error),
onProgress: ({ percent, loaded }) => onProgress: ({ percent, loaded }) =>
handleOnProgress(p.id, percent, loaded), handleOnProgress(p.id, percent, loaded),
onSuccess: () => handleOnSuccess(p.id, p), onSuccess: () => handleOnSuccess(p.id, p),

View File

@@ -10,8 +10,18 @@ import JobLines from "../job-lines/job-lines.component";
import JobNotes from "../job-notes/job-notes.component"; import JobNotes from "../job-notes/job-notes.component";
import JobTombstone from "../job-tombstone/job-tombstone.component"; import JobTombstone from "../job-tombstone/job-tombstone.component";
import LoadingDisplay from "../loading-display/loading-display.component"; import LoadingDisplay from "../loading-display/loading-display.component";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(mapStateToProps, mapDispatchToProps)(ScreenJobDetail);
export default function ScreenJobDetail({ route }) { export function ScreenJobDetail({ bodyshop, route }) {
const { const {
params: { jobId }, params: { jobId },
} = route; } = route;
@@ -45,12 +55,16 @@ export default function ScreenJobDetail({ route }) {
loading: loading, loading: loading,
refetch: refetch, refetch: refetch,
}), }),
documents: () => ...(bodyshop.uselocalmediaserver
JobDocuments({ ? {}
job: data.jobs_by_pk, : {
loading: loading, documents: () =>
refetch: refetch, JobDocuments({
}), job: data.jobs_by_pk,
loading: loading,
refetch: refetch,
}),
}),
notes: () => notes: () =>
JobNotes({ JobNotes({
job: data.jobs_by_pk, job: data.jobs_by_pk,
@@ -63,7 +77,9 @@ export default function ScreenJobDetail({ route }) {
const [routes] = React.useState([ const [routes] = React.useState([
{ key: "job", title: t("jobdetail.labels.job") }, { key: "job", title: t("jobdetail.labels.job") },
{ key: "lines", title: t("jobdetail.labels.lines") }, { key: "lines", title: t("jobdetail.labels.lines") },
{ key: "documents", title: t("jobdetail.labels.documents") }, ...(bodyshop.uselocalmediaserver
? []
: [{ key: "documents", title: t("jobdetail.labels.documents") }]),
{ key: "notes", title: t("jobdetail.labels.notes") }, { key: "notes", title: t("jobdetail.labels.notes") },
]); ]);

View File

@@ -2,11 +2,17 @@ import firebase from "firebase/app";
import "firebase/auth"; import "firebase/auth";
import env from "../env"; import env from "../env";
if (!firebase.apps.length) { import { initializeApp } from "firebase/app";
firebase.initializeApp(env.firebase); import { getAuth, initializeAuth } from "firebase/auth";
} import { getReactNativePersistence } from "firebase/auth/react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
const defaultApp = initializeApp(env.firebase);
initializeAuth(defaultApp, {
persistence: getReactNativePersistence(AsyncStorage),
});
export const auth = getAuth();
export const auth = firebase.auth();
//export const analytics = firebase.analytics(); //export const analytics = firebase.analytics();
export default firebase; export default firebase;
@@ -19,14 +25,3 @@ export const getCurrentUser = () => {
}, reject); }, reject);
}); });
}; };
export const updateCurrentUser = (userDetails) => {
return new Promise((resolve, reject) => {
const unsubscribe = auth.onAuthStateChanged((userAuth) => {
userAuth.updateProfile(userDetails).then((r) => {
unsubscribe();
resolve(userAuth);
});
}, reject);
});
};

View File

@@ -127,6 +127,7 @@ export const client = new ApolloClient({
//link: from([apolloLogger, errorLink, authLink, link]), //link: from([apolloLogger, errorLink, authLink, link]),
link: from([authLink, link]), link: from([authLink, link]),
cache, cache,
notifyOnNetworkStatusChange: true,
// connectToDevTools: process.env.NODE_ENV !== "production", // connectToDevTools: process.env.NODE_ENV !== "production",
defaultOptions: { defaultOptions: {

View File

@@ -1,15 +0,0 @@
> Why do I have a folder named ".expo" in my project?
The ".expo" folder is created when an Expo project is started using "expo start" command.
> What do the files contain?
- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
- "packager-info.json": contains port numbers and process PIDs that are used to serve the application to the mobile device/simulator.
- "settings.json": contains the server configuration that is used to serve the application manifest.
> Should I commit the ".expo" folder?
No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
Upon project creation, the ".expo" folder is already added to your ".gitignore" file.

View File

@@ -1,8 +0,0 @@
{
"hostType": "lan",
"lanType": "ip",
"dev": true,
"minify": false,
"urlRandomness": null,
"https": false
}

6
metro.config.js Normal file
View File

@@ -0,0 +1,6 @@
const { getDefaultConfig } = require("metro-config");
const { resolver: defaultResolver } = getDefaultConfig.getDefaultValues();
exports.resolver = {
...defaultResolver,
sourceExts: [...defaultResolver.sourceExts, "cjs", "jsx"],
};

View File

@@ -14,9 +14,9 @@
"build:android:test": "expo build:android --release-channel test" "build:android:test": "expo build:android --release-channel test"
}, },
"dependencies": { "dependencies": {
"@apollo/client": "^3.3.19", "@apollo/client": "^3.7.0-alpha.3",
"@expo/vector-icons": "^12.0.0", "@expo/vector-icons": "^13.0.0",
"@react-native-async-storage/async-storage": "~1.15.0", "@react-native-async-storage/async-storage": "~1.17.3",
"@react-native-community/art": "^1.2.0", "@react-native-community/art": "^1.2.0",
"@react-native-community/masked-view": "^0.1.11", "@react-native-community/masked-view": "^0.1.11",
"@react-navigation/bottom-tabs": "^6.2.0", "@react-navigation/bottom-tabs": "^6.2.0",
@@ -26,23 +26,23 @@
"axios": "^0.21.0", "axios": "^0.21.0",
"cloudinary-core": "^2.12.3", "cloudinary-core": "^2.12.3",
"dinero.js": "^1.9.1", "dinero.js": "^1.9.1",
"expo": "^44.0.6", "expo": "^45.0.0",
"expo-app-loading": "~1.3.0", "expo-app-loading": "~2.0.0",
"expo-av": "~10.2.1", "expo-av": "~11.2.3",
"expo-camera": "~12.1.2", "expo-camera": "~12.2.0",
"expo-device": "~4.1.1", "expo-device": "~4.2.0",
"expo-file-system": "~13.1.4", "expo-file-system": "~14.0.0",
"expo-firebase-analytics": "~6.0.1", "expo-firebase-analytics": "~7.0.0",
"expo-font": "~10.0.5", "expo-font": "~10.1.0",
"expo-image-manipulator": "~10.2.0", "expo-image-manipulator": "~10.3.1",
"expo-images-picker": "^2.2.5", "expo-images-picker": "^2.2.5",
"expo-localization": "~12.0.1", "expo-localization": "~13.0.0",
"expo-media-library": "~14.0.1", "expo-media-library": "~14.1.0",
"expo-permissions": "~13.1.1", "expo-permissions": "~13.2.0",
"expo-status-bar": "~1.2.0", "expo-status-bar": "~1.3.0",
"expo-updates": "~0.11.7", "expo-updates": "~0.13.1",
"expo-video-thumbnails": "~6.1.0", "expo-video-thumbnails": "~6.3.0",
"firebase": "8.2.3", "firebase": "^9.8.1",
"formik": "^2.2.9", "formik": "^2.2.9",
"graphql": "^15.4.0", "graphql": "^15.4.0",
"i18next": "^21.6.13", "i18next": "^21.6.13",
@@ -51,20 +51,21 @@
"luxon": "^2.3.1", "luxon": "^2.3.1",
"moment": "^2.29.1", "moment": "^2.29.1",
"normalize-url": "^7.0.3", "normalize-url": "^7.0.3",
"react": "17.0.1", "react": "17.0.2",
"react-dom": "17.0.1", "react-dom": "17.0.2",
"react-i18next": "^11.15.5", "react-i18next": "^11.15.5",
"react-native": "0.64.3", "react-native": "0.68.1",
"react-native-gesture-handler": "~2.1.0", "react-native-gesture-handler": "~2.2.1",
"react-native-image-gallery": "^2.1.5", "react-native-image-gallery": "^2.1.5",
"react-native-indicators": "^0.17.0", "react-native-indicators": "^0.17.0",
"react-native-pager-view": "5.4.9", "react-native-pager-view": "5.4.15",
"react-native-paper": "^4.11.2", "react-native-paper": "^4.11.2",
"react-native-progress": "^5.0.0", "react-native-progress": "^5.0.0",
"react-native-reanimated": "~2.3.1", "react-native-reanimated": "~2.8.0",
"react-native-safe-area-context": "3.3.2", "react-native-safe-area-context": "4.2.4",
"react-native-screens": "~3.10.1", "react-native-screens": "~3.11.1",
"react-native-tab-view": "3.1.1", "react-native-tab-view": "3.1.1",
"react-native-toast-message": "^2.1.5",
"react-native-web": "0.17.7", "react-native-web": "0.17.7",
"react-redux": "^7.2.6", "react-redux": "^7.2.6",
"redux": "^4.1.2", "redux": "^4.1.2",
@@ -72,12 +73,12 @@
"redux-persist": "^6.0.0", "redux-persist": "^6.0.0",
"redux-saga": "^1.1.3", "redux-saga": "^1.1.3",
"reselect": "^4.1.5", "reselect": "^4.1.5",
"sentry-expo": "^4.1.0", "sentry-expo": "^4.0.0",
"subscriptions-transport-ws": "^0.9.18" "subscriptions-transport-ws": "^0.9.18"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.9", "@babel/core": "^7.12.9",
"babel-preset-expo": "9.0.1", "babel-preset-expo": "~9.1.0",
"eslint": "^7.27.0", "eslint": "^7.27.0",
"eslint-plugin-react": "^7.24.0", "eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-native": "^3.11.0" "eslint-plugin-react-native": "^3.11.0"

View File

@@ -22,6 +22,7 @@ import {
validatePasswordResetSuccess, validatePasswordResetSuccess,
} from "./user.actions"; } from "./user.actions";
import UserActionTypes from "./user.types"; import UserActionTypes from "./user.types";
import { signInWithEmailAndPassword, signOut } from "firebase/auth";
export function* onEmailSignInStart() { export function* onEmailSignInStart() {
yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail); yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail);
@@ -29,7 +30,7 @@ export function* onEmailSignInStart() {
export function* signInWithEmail({ payload: { email, password } }) { export function* signInWithEmail({ payload: { email, password } }) {
try { try {
logImEXEvent("imexmobile_sign_in_attempt", { user: email }); logImEXEvent("imexmobile_sign_in_attempt", { user: email });
const { user } = yield auth.signInWithEmailAndPassword(email, password); const { user } = yield signInWithEmailAndPassword(auth, email, password);
yield put( yield put(
signInSuccess({ signInSuccess({
uid: user.uid, uid: user.uid,
@@ -78,7 +79,7 @@ export function* signOutStart() {
try { try {
logImEXEvent("imexmobile_sign_out"); logImEXEvent("imexmobile_sign_out");
yield auth.signOut(); yield signOut(auth);
yield put(signOutSuccess()); yield put(signOutSuccess());
} catch (error) { } catch (error) {
yield put(signOutFailure(error.message)); yield put(signOutFailure(error.message));

View File

@@ -83,6 +83,7 @@ export const handleLocalUpload = async ({ ev, context }) => {
callbackAfterUpload(); callbackAfterUpload();
} }
} catch (error) { } catch (error) {
console.log("Error uploading documents:", error); console.log("Error uploading documents:", onError, error);
onError && onError(error);
} }
}; };

7846
yarn.lock

File diff suppressed because it is too large Load Diff