2022-10-05 18:03:52 +02:00
|
|
|
import React from 'react';
|
2023-08-31 13:29:17 +02:00
|
|
|
import { Alert, Button, Linking, Text, View } from 'react-native';
|
2022-10-05 18:03:52 +02:00
|
|
|
// Redux
|
|
|
|
|
import { connect } from 'react-redux';
|
2022-12-28 17:53:43 +01:00
|
|
|
import { initContact } from '../Store/Actions/contacts';
|
2023-08-22 10:32:40 +02:00
|
|
|
import { initDirectories } from '../Store/Actions/directories';
|
2023-01-04 15:28:10 +01:00
|
|
|
import { initDocuments } from '../Store/Actions/documents';
|
2023-01-04 11:38:44 +01:00
|
|
|
// Sentry
|
2023-08-22 10:32:40 +02:00
|
|
|
import * as Sentry from '@sentry/react-native';
|
2023-09-05 09:27:14 +02:00
|
|
|
|
2022-10-05 18:03:52 +02:00
|
|
|
// Style
|
|
|
|
|
import styles from '../../Resources/Styles/SyncStyle';
|
|
|
|
|
// Translations
|
2023-08-22 10:32:40 +02:00
|
|
|
import i18n from '../../I18n';
|
|
|
|
|
// Controller
|
2022-10-05 18:03:52 +02:00
|
|
|
import SyncController from '../Controllers/SyncController';
|
|
|
|
|
// Progress
|
|
|
|
|
import * as Progress from 'react-native-progress';
|
2023-08-22 10:32:40 +02:00
|
|
|
// Database
|
|
|
|
|
import {
|
|
|
|
|
Contact,
|
|
|
|
|
Directory,
|
|
|
|
|
Document,
|
2023-09-04 09:59:48 +02:00
|
|
|
Form,
|
2023-08-22 10:32:40 +02:00
|
|
|
SendBrochure,
|
|
|
|
|
User,
|
|
|
|
|
} from '../../Database';
|
2022-10-06 16:25:15 +02:00
|
|
|
// FileSytem
|
|
|
|
|
import * as FileSystem from 'expo-file-system';
|
2022-10-05 18:03:52 +02:00
|
|
|
|
|
|
|
|
function mapStateToProps(state) {
|
2023-08-22 10:32:40 +02:00
|
|
|
return {
|
|
|
|
|
syncVersion: state.app.syncVersion,
|
|
|
|
|
currentUser: state.app.currentUser,
|
|
|
|
|
locale: state.locale.locale,
|
|
|
|
|
mainColor: state.app.mainColor,
|
|
|
|
|
directories: state.directories,
|
|
|
|
|
};
|
2022-10-05 18:03:52 +02:00
|
|
|
}
|
|
|
|
|
|
2022-12-28 16:32:30 +01:00
|
|
|
const mapDispatchToProps = dispatch => {
|
2023-08-22 10:32:40 +02:00
|
|
|
return {
|
|
|
|
|
init: () => dispatch({ type: 'INIT' }),
|
|
|
|
|
initUsers: () => dispatch({ type: 'INIT_USERS' }),
|
2023-09-04 09:59:48 +02:00
|
|
|
initFormularies: () => dispatch({ type: 'INIT_FORMS' }),
|
2023-08-22 10:32:40 +02:00
|
|
|
initDirectories: (lang, user) => dispatch(initDirectories(lang, user)),
|
|
|
|
|
initDocuments: (lang, directories) =>
|
|
|
|
|
dispatch(initDocuments(lang, directories)),
|
|
|
|
|
initContact: currentUser => dispatch(initContact(currentUser)),
|
|
|
|
|
initBtns: () => dispatch({ type: 'INIT_HOME_BTNS' }),
|
|
|
|
|
updateVersion: version =>
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'UPDATE_VERSION',
|
|
|
|
|
data: version,
|
|
|
|
|
}),
|
|
|
|
|
updateShowIsActive: value =>
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'UPDATE_SHOW_IS_ACTIVE',
|
|
|
|
|
data: value,
|
|
|
|
|
}),
|
|
|
|
|
};
|
2022-12-28 16:32:30 +01:00
|
|
|
};
|
|
|
|
|
|
2022-10-05 18:03:52 +02:00
|
|
|
class SyncScreen extends React.Component {
|
2023-08-22 10:32:40 +02:00
|
|
|
state = {
|
|
|
|
|
progress: 0,
|
|
|
|
|
txtStep: '',
|
|
|
|
|
downloadProgress: 0,
|
|
|
|
|
downloadingFile: false,
|
|
|
|
|
processing: false,
|
|
|
|
|
newApp: false,
|
|
|
|
|
forced: false,
|
|
|
|
|
};
|
2022-10-05 18:03:52 +02:00
|
|
|
|
2023-08-22 10:32:40 +02:00
|
|
|
componentDidMount() {
|
|
|
|
|
const { forceSync } = this.props.route.params;
|
|
|
|
|
if (forceSync === true) {
|
|
|
|
|
this.setState({ forced: true });
|
|
|
|
|
this.sync();
|
2022-10-07 18:27:54 +02:00
|
|
|
}
|
2023-08-22 10:32:40 +02:00
|
|
|
}
|
2022-10-07 18:27:54 +02:00
|
|
|
|
2023-08-22 10:32:40 +02:00
|
|
|
render() {
|
|
|
|
|
const fileProgress = this.fileProgress();
|
|
|
|
|
return (
|
|
|
|
|
<View style={styles.container}>
|
|
|
|
|
<Progress.Circle
|
|
|
|
|
size={250}
|
|
|
|
|
progress={this.state.progress}
|
|
|
|
|
showsText={true}
|
|
|
|
|
color={this.props.mainColor}
|
|
|
|
|
/>
|
|
|
|
|
<View style={styles.btnWrapper}>
|
|
|
|
|
<Button
|
|
|
|
|
disabled={this.state.processing}
|
|
|
|
|
color={this.props.mainColor}
|
|
|
|
|
title={i18n.t('sync_s.start_sync')}
|
|
|
|
|
onPress={() => this.sync()}
|
|
|
|
|
/>
|
|
|
|
|
</View>
|
|
|
|
|
<View style={styles.btnWrapper}>
|
|
|
|
|
<Text>
|
|
|
|
|
{this.state.txtStep} {fileProgress}
|
|
|
|
|
</Text>
|
|
|
|
|
</View>
|
|
|
|
|
</View>
|
|
|
|
|
);
|
|
|
|
|
}
|
2022-10-05 18:03:52 +02:00
|
|
|
|
2023-08-22 10:32:40 +02:00
|
|
|
async sync() {
|
|
|
|
|
let errorStatus = false;
|
2023-09-04 09:59:48 +02:00
|
|
|
|
|
|
|
|
console.debug('Sync');
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Promise<import('@react-native-community/netinfo').NetInfoState>} promise
|
|
|
|
|
* @param {(error:any) => void|null} onError
|
|
|
|
|
*/
|
|
|
|
|
const getCall = (promise, onError = null) => {
|
|
|
|
|
if (onError === null) {
|
|
|
|
|
/** @param {import('axios').AxiosError} error */
|
|
|
|
|
onError = error => {
|
|
|
|
|
let message = 'Erreur de la communication serveur';
|
|
|
|
|
if (error?.response?.status === 422) {
|
|
|
|
|
message =
|
|
|
|
|
this.parseValidationErrors(error.response?.data?.errors ?? {}) ||
|
|
|
|
|
message;
|
|
|
|
|
console.warn(error.response?.data?.errors ?? {});
|
|
|
|
|
} else if (error?.response?.status === 419) {
|
|
|
|
|
// * CSRF TOKEN MISMATCH (On ne pourrais plus faire d'appels AJAX sans recharger la page)
|
|
|
|
|
message = 'Votre session a expiré, la page va être rechargée';
|
|
|
|
|
} else if (error?.response?.status === 403) {
|
|
|
|
|
// * Access denied
|
|
|
|
|
message = "Vous n'êtes pas autorisé a effectuer cette action";
|
|
|
|
|
} else {
|
|
|
|
|
console.error(error);
|
|
|
|
|
}
|
|
|
|
|
console.warn(message);
|
|
|
|
|
|
|
|
|
|
Sentry.captureException(error);
|
|
|
|
|
Alert.alert(
|
|
|
|
|
i18n.t('error.error'),
|
|
|
|
|
i18n.t('error.error_has_occurred'),
|
|
|
|
|
);
|
|
|
|
|
errorStatus = true;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return promise.catch(onError);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const isConnected = await SyncController.checkConnection().catch(
|
|
|
|
|
error => false,
|
|
|
|
|
);
|
2023-08-22 10:32:40 +02:00
|
|
|
if (!isConnected) {
|
|
|
|
|
Alert.alert(
|
|
|
|
|
i18n.t('global.warning'),
|
|
|
|
|
i18n.t('error.must_be_connected_internet_sync'),
|
|
|
|
|
);
|
|
|
|
|
return;
|
2022-10-05 18:03:52 +02:00
|
|
|
}
|
2023-08-22 10:32:40 +02:00
|
|
|
this.setState({ processing: true });
|
2023-09-04 09:59:48 +02:00
|
|
|
|
|
|
|
|
// * --- getVersion
|
|
|
|
|
const resVersion = await getCall(
|
|
|
|
|
SyncController.getVersion().then(res => {
|
2023-08-22 10:32:40 +02:00
|
|
|
return res.data;
|
2023-09-04 09:59:48 +02:00
|
|
|
}),
|
|
|
|
|
);
|
2023-08-22 10:32:40 +02:00
|
|
|
if (errorStatus) {
|
|
|
|
|
return false;
|
2022-10-05 18:03:52 +02:00
|
|
|
}
|
2023-08-22 10:32:40 +02:00
|
|
|
this.props.updateVersion(resVersion.version);
|
|
|
|
|
this.props.updateShowIsActive(resVersion.ShowIsActive);
|
|
|
|
|
this.setState({ newApp: resVersion.newApp });
|
2023-09-04 09:59:48 +02:00
|
|
|
|
|
|
|
|
// * --- getUsers
|
|
|
|
|
this.setState({
|
|
|
|
|
progress: 0.1,
|
|
|
|
|
txtStep: i18n.t('sync_s.updating_users') + '...',
|
|
|
|
|
});
|
|
|
|
|
const resUsers = await getCall(
|
|
|
|
|
SyncController.getUsers().then(res => {
|
2023-08-22 10:32:40 +02:00
|
|
|
User.clear();
|
|
|
|
|
return res.data;
|
2023-09-04 09:59:48 +02:00
|
|
|
}),
|
|
|
|
|
);
|
2023-08-22 10:32:40 +02:00
|
|
|
if (errorStatus) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
resUsers.forEach(user => {
|
|
|
|
|
User.add(user);
|
|
|
|
|
});
|
2023-09-04 09:59:48 +02:00
|
|
|
|
|
|
|
|
// * --- Contacts Sync
|
|
|
|
|
/*
|
|
|
|
|
* This is done only for actual app user
|
|
|
|
|
- 1 Upsert all contacts
|
|
|
|
|
- 2 Delete contacts where to_delete is true
|
|
|
|
|
- 3 Get all contacts
|
|
|
|
|
*/
|
2023-08-22 10:32:40 +02:00
|
|
|
this.setState({
|
2023-09-04 09:59:48 +02:00
|
|
|
progress: 0.2,
|
2023-08-22 10:32:40 +02:00
|
|
|
txtStep: i18n.t('sync_s.updating_contacts') + '...',
|
|
|
|
|
});
|
2023-09-04 09:59:48 +02:00
|
|
|
|
|
|
|
|
// * --- Contacts Sync -- STEP 1
|
|
|
|
|
await getCall(SyncController.upsertContacts(this.props.currentUser.id));
|
2023-08-22 10:32:40 +02:00
|
|
|
if (errorStatus) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-09-04 09:59:48 +02:00
|
|
|
|
|
|
|
|
// * --- Contacts Sync -- STEP 2
|
|
|
|
|
this.setState({
|
|
|
|
|
progress: 0.23,
|
2023-08-22 10:32:40 +02:00
|
|
|
});
|
2023-09-04 09:59:48 +02:00
|
|
|
await getCall(SyncController.deleteContacts(this.props.currentUser.id));
|
|
|
|
|
if (errorStatus) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// * --- Contacts Sync -- STEP 3
|
2023-08-22 10:32:40 +02:00
|
|
|
this.setState({
|
2023-09-04 09:59:48 +02:00
|
|
|
progress: 0.26,
|
|
|
|
|
});
|
|
|
|
|
const resContacts = await getCall(
|
|
|
|
|
SyncController.getContacts(this.props.currentUser.id).then(res => {
|
|
|
|
|
// * Clear Contacts, in order to fetch them all after.
|
|
|
|
|
Contact.clear(this.props.currentUser.id);
|
|
|
|
|
return res.data;
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
if (errorStatus) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
/** @type {(contact: import('./../Models/Contact').ContactData ) => void} */
|
|
|
|
|
const contactMapper = contact => {
|
|
|
|
|
// * Stringify complex Fields
|
|
|
|
|
contact.data = JSON.stringify(contact.data);
|
|
|
|
|
contact.visits = JSON.stringify(contact.visits);
|
|
|
|
|
contact.timestamp = new Date(contact.timestamp);
|
|
|
|
|
Contact.set(contact);
|
|
|
|
|
};
|
|
|
|
|
resContacts.forEach(contactMapper);
|
|
|
|
|
|
|
|
|
|
// * --- sendBrochures
|
|
|
|
|
this.setState({
|
|
|
|
|
progress: 0.3,
|
2023-08-22 10:32:40 +02:00
|
|
|
txtStep: i18n.t('sync_s.sending_flyers') + '...',
|
|
|
|
|
});
|
2023-09-04 09:59:48 +02:00
|
|
|
const brochures = SendBrochure.getAll();
|
2023-08-22 10:32:40 +02:00
|
|
|
for (const brochure of brochures) {
|
2023-09-04 09:59:48 +02:00
|
|
|
await getCall(
|
|
|
|
|
SyncController.sendBrochure(brochure).then(res => {
|
2023-08-22 10:32:40 +02:00
|
|
|
SendBrochure.delete(brochure.id);
|
2023-09-04 09:59:48 +02:00
|
|
|
}),
|
|
|
|
|
);
|
2022-10-06 16:25:15 +02:00
|
|
|
}
|
2023-08-22 10:32:40 +02:00
|
|
|
if (errorStatus) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-09-04 09:59:48 +02:00
|
|
|
|
|
|
|
|
// * --- getDirectories
|
2023-08-22 10:32:40 +02:00
|
|
|
this.setState({
|
2023-09-04 09:59:48 +02:00
|
|
|
progress: 0.4,
|
2023-08-22 10:32:40 +02:00
|
|
|
txtStep: i18n.t('sync_s.updating_folders') + '...',
|
|
|
|
|
});
|
2023-09-04 09:59:48 +02:00
|
|
|
const resDirectories = await getCall(
|
|
|
|
|
SyncController.getDirectories().then(res => {
|
2023-08-22 10:32:40 +02:00
|
|
|
Directory.clear();
|
|
|
|
|
return res.data;
|
2023-09-04 09:59:48 +02:00
|
|
|
}),
|
|
|
|
|
);
|
2023-08-22 10:32:40 +02:00
|
|
|
if (errorStatus) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
resDirectories.forEach(dir => {
|
|
|
|
|
Directory.add(dir);
|
|
|
|
|
});
|
2023-09-04 09:59:48 +02:00
|
|
|
|
|
|
|
|
// * --- getFormularies
|
2023-08-22 10:32:40 +02:00
|
|
|
this.setState({
|
2023-09-04 09:59:48 +02:00
|
|
|
progress: 0.5,
|
|
|
|
|
txtStep: i18n.t('sync_s.updating_forms') + '...',
|
|
|
|
|
});
|
|
|
|
|
const resFormularies = await getCall(
|
|
|
|
|
SyncController.getFormularies().then(res => {
|
|
|
|
|
Form.clear();
|
|
|
|
|
return res.data;
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
if (errorStatus) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
resFormularies.forEach(form => Form.add(form));
|
|
|
|
|
|
|
|
|
|
// * --- getDocuments
|
|
|
|
|
this.setState({
|
|
|
|
|
progress: 0.6,
|
2023-08-22 10:32:40 +02:00
|
|
|
txtStep: i18n.t('sync_s.updating_docs') + '...',
|
|
|
|
|
});
|
2023-09-04 09:59:48 +02:00
|
|
|
const resDocuments = await getCall(
|
|
|
|
|
SyncController.getDocuments().then(res => {
|
2023-08-22 10:32:40 +02:00
|
|
|
return res.data;
|
2023-09-04 09:59:48 +02:00
|
|
|
}),
|
|
|
|
|
);
|
2023-08-22 10:32:40 +02:00
|
|
|
if (errorStatus) {
|
|
|
|
|
return false;
|
2022-10-06 16:25:15 +02:00
|
|
|
}
|
2023-08-22 10:32:40 +02:00
|
|
|
const toDelete = Document.clear(resDocuments);
|
|
|
|
|
resDocuments.forEach(document => {
|
|
|
|
|
Document.update(document);
|
|
|
|
|
});
|
|
|
|
|
this.downloadDocuments(Document.getAll(), toDelete);
|
2023-09-04 09:59:48 +02:00
|
|
|
|
|
|
|
|
// * --- End
|
2023-08-22 10:32:40 +02:00
|
|
|
}
|
2022-10-06 16:25:15 +02:00
|
|
|
|
2023-08-22 10:32:40 +02:00
|
|
|
fileProgress() {
|
|
|
|
|
if (this.state.downloadingFile === true) {
|
|
|
|
|
return this.state.downloadProgress + ' %';
|
2022-10-06 16:25:15 +02:00
|
|
|
}
|
2023-08-22 10:32:40 +02:00
|
|
|
}
|
2022-10-06 16:25:15 +02:00
|
|
|
|
2023-08-22 10:32:40 +02:00
|
|
|
downloadDocuments(docs, toDelete) {
|
|
|
|
|
const version = this.props.syncVersion;
|
|
|
|
|
this.getToDL(docs, 0).then(toDownload => {
|
|
|
|
|
if (toDownload.length > 0) {
|
2023-09-04 09:59:48 +02:00
|
|
|
this.setState({ progress: 0.6 });
|
|
|
|
|
const docProgress = 0.4 / toDownload.length;
|
2023-08-22 10:32:40 +02:00
|
|
|
this.download(toDownload, docProgress, 0).then(status => {
|
|
|
|
|
if (status === true) {
|
2023-09-04 09:59:48 +02:00
|
|
|
this.deleteFile(toDelete, 0).then(delStatus => {
|
2023-08-22 10:32:40 +02:00
|
|
|
this.finishSync(version);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
this.setState({
|
|
|
|
|
txtStep: i18n.t('error.error_has_occurred') + '.',
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-10-06 16:25:15 +02:00
|
|
|
});
|
2023-08-22 10:32:40 +02:00
|
|
|
} else {
|
|
|
|
|
this.deleteFile(toDelete, 0).then(status => {
|
|
|
|
|
this.setState({ progress: 1 });
|
|
|
|
|
this.finishSync(version);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-10-06 16:25:15 +02:00
|
|
|
|
2023-08-22 10:32:40 +02:00
|
|
|
async getToDL(docs, i, toDL = []) {
|
|
|
|
|
if (docs.length < 1) {
|
|
|
|
|
return toDL;
|
2022-10-06 16:25:15 +02:00
|
|
|
}
|
2023-08-22 10:32:40 +02:00
|
|
|
const item = docs[i];
|
|
|
|
|
const { exists, modificationTime } = await FileSystem.getInfoAsync(
|
|
|
|
|
FileSystem.documentDirectory + item.uuid + '.' + item.type,
|
|
|
|
|
);
|
|
|
|
|
if (exists === false) {
|
|
|
|
|
toDL.push(item);
|
|
|
|
|
} else {
|
|
|
|
|
if (modificationTime.toString() !== item.updated_at) {
|
|
|
|
|
toDL.push(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (i < docs.length - 1) {
|
|
|
|
|
return this.getToDL(docs, i + 1, toDL);
|
|
|
|
|
}
|
|
|
|
|
return toDL;
|
|
|
|
|
}
|
2022-10-06 16:25:15 +02:00
|
|
|
|
2023-08-22 10:32:40 +02:00
|
|
|
async deleteFile(docs, i) {
|
|
|
|
|
if (docs.length > 0) {
|
|
|
|
|
const file = docs[i];
|
|
|
|
|
await FileSystem.deleteAsync(
|
|
|
|
|
FileSystem.documentDirectory + file.uuid + '.' + file.type,
|
|
|
|
|
{ idempotent: true },
|
|
|
|
|
);
|
|
|
|
|
if (i < docs.length - 1) {
|
|
|
|
|
return this.deleteFile(docs, i + 1);
|
|
|
|
|
}
|
2022-10-06 16:25:15 +02:00
|
|
|
}
|
2023-08-22 10:32:40 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
callback(downloadProgress) {
|
|
|
|
|
let progress =
|
|
|
|
|
(downloadProgress.totalBytesWritten /
|
|
|
|
|
downloadProgress.totalBytesExpectedToWrite) *
|
|
|
|
|
100;
|
|
|
|
|
progress = Math.round(progress);
|
|
|
|
|
progress = progress.toString();
|
|
|
|
|
this.setState({
|
|
|
|
|
downloadProgress: progress,
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-10-06 16:25:15 +02:00
|
|
|
|
2023-08-22 10:32:40 +02:00
|
|
|
downloadResumable(url, uuid, type) {
|
|
|
|
|
return FileSystem.createDownloadResumable(
|
|
|
|
|
url,
|
|
|
|
|
FileSystem.documentDirectory + uuid + '.' + type,
|
|
|
|
|
{},
|
|
|
|
|
this.callback.bind(this),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async download(documents, progress, i) {
|
|
|
|
|
if (this.state.downloadingFile === false) {
|
|
|
|
|
this.setState({ downloadingFile: true });
|
|
|
|
|
}
|
2025-09-01 18:57:23 +02:00
|
|
|
const tenantUrl = SyncController.getUrlBo();
|
|
|
|
|
const rootUrl = tenantUrl.substring(0, tenantUrl.lastIndexOf('/'));
|
|
|
|
|
const tenantId = tenantUrl.match(/[^\/]+$/)[0];
|
|
|
|
|
const endpoint = rootUrl + '/storage/docs/' + tenantId + "/";
|
2023-08-22 10:32:40 +02:00
|
|
|
const doc = documents[i];
|
|
|
|
|
this.setState({
|
|
|
|
|
txtStep:
|
|
|
|
|
i18n.t('sync_s.download') +
|
|
|
|
|
' : ' +
|
|
|
|
|
doc.title +
|
|
|
|
|
' (' +
|
|
|
|
|
doc.type.toUpperCase() +
|
|
|
|
|
') ...',
|
|
|
|
|
});
|
|
|
|
|
try {
|
2023-09-05 09:27:14 +02:00
|
|
|
const uri = `${endpoint}${doc.uuid}.${doc.type}`;
|
2023-08-22 10:32:40 +02:00
|
|
|
await this.downloadResumable(
|
|
|
|
|
endpoint + doc.uuid + '.' + doc.type,
|
|
|
|
|
doc.uuid,
|
|
|
|
|
doc.type,
|
|
|
|
|
).downloadAsync();
|
|
|
|
|
const { modificationTime } = await FileSystem.getInfoAsync(
|
|
|
|
|
FileSystem.documentDirectory + doc.uuid + '.' + doc.type,
|
|
|
|
|
);
|
|
|
|
|
SyncController.updateLastModificationDoc(doc.id, modificationTime);
|
2023-09-05 09:27:14 +02:00
|
|
|
console.debug('Finished downloading to ', uri);
|
2023-08-22 10:32:40 +02:00
|
|
|
this.setState({ progress: this.state.progress + progress });
|
|
|
|
|
if (i < documents.length - 1) {
|
|
|
|
|
return this.download(documents, progress, i + 1);
|
|
|
|
|
}
|
|
|
|
|
this.setState({ downloadingFile: false });
|
|
|
|
|
return true;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
return false;
|
2022-10-06 16:25:15 +02:00
|
|
|
}
|
2023-08-22 10:32:40 +02:00
|
|
|
}
|
2022-10-06 16:25:15 +02:00
|
|
|
|
2023-08-22 10:32:40 +02:00
|
|
|
finishSync(version) {
|
|
|
|
|
this.props.init();
|
|
|
|
|
this.props.initUsers();
|
|
|
|
|
this.props.initContact(this.props.currentUser);
|
|
|
|
|
this.props.initDirectories(this.props.locale, this.props.currentUser);
|
|
|
|
|
this.props.initDocuments(this.props.locale, this.props.directories.global);
|
|
|
|
|
this.props.initBtns();
|
|
|
|
|
if (this.state.forced) {
|
|
|
|
|
SyncController.setInstalled();
|
|
|
|
|
}
|
|
|
|
|
SyncController.updateVersion(version);
|
|
|
|
|
this.setState({
|
|
|
|
|
txtStep: i18n.t('sync_s.update_completed') + '.',
|
|
|
|
|
processing: false,
|
|
|
|
|
});
|
|
|
|
|
if (this.state.newApp === true) {
|
|
|
|
|
const appUUID = SyncController.getAppStoreUUID();
|
|
|
|
|
const url = 'https://store.ldc.fr' + '/app/' + appUUID;
|
|
|
|
|
Alert.alert(
|
|
|
|
|
'LDC Store',
|
|
|
|
|
i18n.t('sync_s.new_app_version'),
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
text: i18n.t('global.cancel'),
|
2023-09-05 09:27:14 +02:00
|
|
|
onPress: () => console.debug('Cancel Pressed'),
|
2023-08-22 10:32:40 +02:00
|
|
|
style: 'cancel',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
text: i18n.t('sync_s.open_store'),
|
|
|
|
|
onPress: () =>
|
|
|
|
|
Linking.openURL(url).catch(err =>
|
|
|
|
|
console.error('An error occurred', err),
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
{ cancelable: false },
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-09-04 09:59:48 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parse error messages for a specific input.
|
|
|
|
|
*
|
|
|
|
|
* @param {Record<string, Array<string>>} allErrors
|
|
|
|
|
* @return {string | null}
|
|
|
|
|
*/
|
|
|
|
|
parseValidationErrors(allErrors = {}) {
|
|
|
|
|
const errorList = Object.values(allErrors);
|
|
|
|
|
if (!errorList.length) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
return errorList
|
|
|
|
|
.reduce((oldInputErrors, inputErrors) =>
|
|
|
|
|
oldInputErrors ? oldInputErrors.concat(inputErrors) : inputErrors,
|
|
|
|
|
)
|
|
|
|
|
.reduce(
|
|
|
|
|
(oldInputString, inputString) =>
|
|
|
|
|
(oldInputString ? `${oldInputString}, ` : '') + inputString,
|
|
|
|
|
);
|
|
|
|
|
}
|
2022-10-05 18:03:52 +02:00
|
|
|
}
|
|
|
|
|
|
2023-08-22 10:32:40 +02:00
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(SyncScreen);
|