Compare commits

...
Sign in to create a new pull request.

6 commits

20 changed files with 1936 additions and 1019 deletions

View file

@ -1,5 +1,30 @@
# CHANGELOG # CHANGELOG
## 4.0.0
### Évolution - 4.0.0
- Delete store.ldc.fr dependance
- Remove useless MySpace feature
## 3.2.1
### Évolution - 3.2.1
- Update select and select multiple fields to get list in alphabetical order
## 3.1.1
### Évolution - 3.1.1
- Update Install and Download docs call to handle tenant changes
## 3.0.1
### Bug - 3.0.1
- Fix sendBrochure call, put data into data axios object instead of params
## 3.0.0 ## 3.0.0
### Bug - 3.0.0 ### Bug - 3.0.0

View file

@ -1,4 +1,18 @@
# ComApp # ComApp
# Run with Windows + WSL
- Install Android studio and create a Virtual Device
- Launch emulator
- In WSL :
```bash
adb reverse tcp:8081 tcp:8081
npx react-native start // TO start metro
npx react-native run-android --deviceId emulator-5554 // TO build and run to this Emulator
```
You can set internet proxy in emulator params
## Dependencies ## Dependencies
- i18n-js - i18n-js
- @react-native-community/netinfo - @react-native-community/netinfo

View file

@ -139,7 +139,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1 versionCode 1
versionName "3.0.0" versionName "4.0.0"
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
if (isNewArchitectureEnabled()) { if (isNewArchitectureEnabled()) {

837
ComApp/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -58,9 +58,11 @@
"eslint": "^7.32.0", "eslint": "^7.32.0",
"jest": "^26.6.3", "jest": "^26.6.3",
"metro-react-native-babel-preset": "^0.72.3", "metro-react-native-babel-preset": "^0.72.3",
"patch-package": "^8.0.0",
"react-test-renderer": "18.1.0" "react-test-renderer": "18.1.0"
}, },
"jest": { "jest": {
"preset": "react-native" "preset": "react-native"
} },
"postinstall": "patch-package"
} }

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,13 @@
diff --git a/node_modules/react-native/ReactAndroid/build.gradle b/node_modules/react-native/ReactAndroid/build.gradle
index 3be8b26..3f7bba8 100644
--- a/node_modules/react-native/ReactAndroid/build.gradle
+++ b/node_modules/react-native/ReactAndroid/build.gradle
@@ -61,7 +61,7 @@ task createNativeDepsDirectories {
}
task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) {
- src("https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz")
+ src("https://archives.boost.io/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz")
onlyIfNewer(true)
overwrite(false)
dest(new File(downloadsDir, "boost_${BOOST_VERSION}.tar.gz"))

View file

@ -36,7 +36,6 @@ import DirectoriesScreen from './App/Views/DirectoriesScreen';
import HomeScreen from './App/Views/HomeScreen'; import HomeScreen from './App/Views/HomeScreen';
import InstallScreen from './App/Views/InstallScreen'; import InstallScreen from './App/Views/InstallScreen';
import LoginScreen from './App/Views/LoginScreen'; import LoginScreen from './App/Views/LoginScreen';
import MySpaceScreen from './App/Views/MySpaceScreen';
import OnlyVideosScreen from './App/Views/OnlyVideosScreen'; import OnlyVideosScreen from './App/Views/OnlyVideosScreen';
import PDFScreen from './App/Views/PDFScreen'; import PDFScreen from './App/Views/PDFScreen';
import SearchScreen from './App/Views/SearchScreen'; import SearchScreen from './App/Views/SearchScreen';
@ -246,15 +245,6 @@ class App extends React.Component {
<Icon name={'search'} size={20} color={'white'} /> <Icon name={'search'} size={20} color={'white'} />
</TouchableOpacity> </TouchableOpacity>
</View> </View>
{store.getState().app.ShowIsActive === '1' && (
<TouchableOpacity
onPress={() =>
navigation.navigation.navigate('MySpaceScreen')
}
style={{ marginRight: 25 }}>
<Icon name="user-circle" size={25} />
</TouchableOpacity>
)}
<TouchableOpacity <TouchableOpacity
onPress={() => onPress={() =>
navigation.navigation.navigate('ContactScreen', { navigation.navigation.navigate('ContactScreen', {
@ -378,31 +368,6 @@ class App extends React.Component {
this.LogoTitle(navigation, i18n.t('app.results_search')), this.LogoTitle(navigation, i18n.t('app.results_search')),
})} })}
/> />
<Stack.Screen
name="MySpaceScreen"
component={MySpaceScreen}
options={(navigation, route) => ({
headerTitle: () =>
this.LogoTitle(navigation, i18n.t('app.my_space')),
headerRight: () => (
<View
style={{ flexDirection: 'row', alignItems: 'center' }}>
<TouchableOpacity
onPress={() => {
const folder = store
.getState()
.directories.treeview.filter(tmp => tmp.id === 1);
navigation.navigation.navigate('DirectoriesScreen', {
folder: folder,
});
}}
style={{ marginRight: 15 }}>
<Icon name="briefcase" size={20} />
</TouchableOpacity>
</View>
),
})}
/>
</Stack.Navigator> </Stack.Navigator>
<FlashMessage position="top" /> <FlashMessage position="top" />
</DrawerLayoutAndroid> </DrawerLayoutAndroid>

View file

@ -3,8 +3,6 @@
import axios from 'axios'; import axios from 'axios';
// Network Infos // Network Infos
import NetInfo from '@react-native-community/netinfo'; import NetInfo from '@react-native-community/netinfo';
// Application infos
import * as Application from 'expo-application';
// Database // Database
import { Contact, Document, SendBrochure, Setting } from '../../Database'; import { Contact, Document, SendBrochure, Setting } from '../../Database';
import { ContactData } from '../Models/Contact'; import { ContactData } from '../Models/Contact';
@ -20,32 +18,10 @@ class SyncController {
return test.value; return test.value;
} }
getAppStoreUUID() {
const test = Setting.get('AppStoreUUID');
if (test === null) {
return 'noset';
}
return test.value;
}
async checkConnection() { async checkConnection() {
return NetInfo.fetch(); return NetInfo.fetch();
} }
async getVersion() {
return axios({
method: 'GET',
// * version
url: this.getUrlBo() + '/api/version',
responseType: 'json',
params: {
token: api_token,
app_uuid: this.getAppStoreUUID(),
app_version: Application.nativeApplicationVersion,
},
});
}
async getUsers() { async getUsers() {
return axios({ return axios({
method: 'GET', method: 'GET',
@ -132,8 +108,10 @@ class SyncController {
responseType: 'json', responseType: 'json',
params: { params: {
token: api_token, token: api_token,
emails: brochure,
}, },
data: {
emails: brochure,
}
}); });
} }
@ -177,24 +155,6 @@ class SyncController {
Document.update({ id: id, updated_at: date.toString() }, true); Document.update({ id: id, updated_at: date.toString() }, true);
} }
updateVersion(version) {
const localVersion = Setting.get('version');
if (localVersion === null) {
Setting.add({ key: 'version', value: version });
} else {
Setting.update({ id: localVersion.id, key: 'version', value: version });
}
}
updateShowIsActive(value) {
const local = Setting.get('ShowIsActive');
if (local === null) {
Setting.add({ key: 'ShowIsActive', value: value });
} else {
Setting.update({ id: local.id, key: 'ShowIsActive', value: value });
}
}
/** /**
* @param {number} app_user_id * @param {number} app_user_id
* @returns * @returns
@ -227,36 +187,6 @@ class SyncController {
return false; return false;
} }
needSync(callback) {
NetInfo.fetch().then(state => {
if (state.isConnected) {
axios({
method: 'get',
url: this.getUrlBo() + '/version',
responseType: 'json',
params: {
token: api_token,
},
})
.then(response => {
const localVersion = Setting.get('version');
if (
localVersion === null ||
localVersion.value !== response.data.version
) {
return callback();
}
return false;
})
.catch(function (error) {
console.error(error);
});
}
return false;
});
return false;
}
setInstalled(remove = false) { setInstalled(remove = false) {
if (remove) { if (remove) {
Setting.delete('installed'); Setting.delete('installed');

View file

@ -7,10 +7,8 @@ const initialState = {
locale: 'fr', locale: 'fr',
currentUser: {}, currentUser: {},
logged: false, logged: false,
syncVersion: 0,
forceSync: false, forceSync: false,
currentOpenedDoc: {}, currentOpenedDoc: {},
ShowIsActive: 0,
HomeBtns: {}, HomeBtns: {},
mainColor: '#D4021D', mainColor: '#D4021D',
}; };
@ -19,14 +17,12 @@ const reducer = (state = initialState, action) => {
let saved; let saved;
switch (action.type) { switch (action.type) {
case 'INIT': case 'INIT':
let ShowIsActive = Setting.get('ShowIsActive');
let MainColor = Setting.get('MainColor'); let MainColor = Setting.get('MainColor');
saved = Setting.get('isSetup'); saved = Setting.get('isSetup');
return { return {
...state, ...state,
isSetup: isSetup:
saved === undefined ? false : saved?.value === 'true' ? true : false, saved === undefined ? false : saved?.value === 'true' ? true : false,
ShowIsActive: ShowIsActive ? ShowIsActive?.value : false,
mainColor: mainColor:
MainColor === undefined MainColor === undefined
? initialState.mainColor ? initialState.mainColor
@ -101,17 +97,6 @@ const reducer = (state = initialState, action) => {
...state, ...state,
currentOpenedDoc: action.data, currentOpenedDoc: action.data,
}; };
case 'UPDATE_VERSION':
return {
...state,
syncVersion: action.data,
};
case 'UPDATE_SHOW_IS_ACTIVE':
SyncController.updateShowIsActive(action.data);
return {
...state,
ShowIsActive: action.data,
};
case 'SEND_BROCHURE': case 'SEND_BROCHURE':
SendBrochure.add(action.data); SendBrochure.add(action.data);
return state; return state;

View file

@ -184,7 +184,7 @@ class ContactDetailsScreen extends React.Component {
contact.email.length >= 255 || contact.email.length >= 255 ||
!Helpers.isEmailValid(contact.email) !Helpers.isEmailValid(contact.email)
) { ) {
console.debug('invalid prop email'); console.debug('invalid prop email', contact.email);
error = error.concat(i18n.t('error.invalid_email_address') + '.\n'); error = error.concat(i18n.t('error.invalid_email_address') + '.\n');
} }
const lockedFields = ['firstname', 'lastname', 'phone']; const lockedFields = ['firstname', 'lastname', 'phone'];
@ -1292,12 +1292,12 @@ class ContactDetailsScreen extends React.Component {
'contact_details_s.input_select_multiple_search', 'contact_details_s.input_select_multiple_search',
)} )}
confirmText={i18n.t('global.close')} confirmText={i18n.t('global.close')}
items={details.map(function (detail, detailIndex) { items={details
return { .map((detail, detailIndex) => ({
id: detailIndex, id: detailIndex,
name: detail, name: detail,
}; }))
})} .sort((a, b) => a.name.localeCompare(b.name))}
IconRenderer={this.getIcon} IconRenderer={this.getIcon}
uniqueKey="id" uniqueKey="id"
selectText={`${placeHolder} ${requiredStr}`} selectText={`${placeHolder} ${requiredStr}`}
@ -1535,8 +1535,10 @@ class ContactDetailsScreen extends React.Component {
label={i18n.t('contact_details_s.input_select_please_choose')} label={i18n.t('contact_details_s.input_select_please_choose')}
value={''} value={''}
/> />
{details.map((detail, detailIndex) => ( {details.map((detail, index) => ({ label: detail, value: index }))
<Picker.Item key={detailIndex} label={detail} value={detailIndex} /> .sort((a, b) => a.label.localeCompare(b.label))
.map((item, index) => (
<Picker.Item key={index} label={item.label} value={item.value} />
))} ))}
</Picker> </Picker>
</View>, </View>,

View file

@ -21,8 +21,6 @@ import styles from '../../Resources/Styles/HomeStyle';
import i18n from '../../I18n'; import i18n from '../../I18n';
// FileSytem // FileSytem
import * as FileSystem from 'expo-file-system'; import * as FileSystem from 'expo-file-system';
// NetInfo
import NetInfo from '@react-native-community/netinfo';
// Controller // Controller
import SyncController from '../Controllers/SyncController'; import SyncController from '../Controllers/SyncController';
@ -63,19 +61,6 @@ class HomeScreen extends React.Component {
SplashScreen.hideAsync(); SplashScreen.hideAsync();
} }
unsubscribe() {
NetInfo.addEventListener(state => {
if (state.isConnected === true) {
let seconds =
Math.abs(new Date(this.state.lastSyncCall) - Date.now()) / 1000;
if (seconds > 30) {
this.setState({ lastSyncCall: Date.now() });
SyncController.needSync(this.openSync.bind(this));
}
}
});
}
openSync() { openSync() {
this.props.navigation.navigate('SyncScreen', { forceSync: true }); this.props.navigation.navigate('SyncScreen', { forceSync: true });
} }

View file

@ -136,10 +136,10 @@ class InstallScreen extends React.Component {
let toDL = []; let toDL = [];
if (response.data) { if (response.data) {
if (response.data.status === 'OK') { if (response.data.status === 'OK') {
const rootUrl = url.substring(0, url.lastIndexOf('/'));
_.forEach(response.data.datas, function (value, key) { _.forEach(response.data.datas, function (value, key) {
switch (key) { switch (key) {
case 'MainColor': case 'MainColor':
case 'AppStoreUUID':
Setting.upsert({ key: key, value: value }); Setting.upsert({ key: key, value: value });
break; break;
case 'SquaredLogo': case 'SquaredLogo':
@ -147,7 +147,7 @@ class InstallScreen extends React.Component {
case 'BackgroundImage': case 'BackgroundImage':
case 'HomeButtonImage': case 'HomeButtonImage':
toDL.push({ toDL.push({
source: url + '/' + value, source: rootUrl + '/' + value,
dest: FileSystem.documentDirectory + key + '.png', dest: FileSystem.documentDirectory + key + '.png',
}); });
break; break;

View file

@ -235,7 +235,6 @@ class LoginScreen extends React.Component {
_.forEach(response.data.datas, function (value, key) { _.forEach(response.data.datas, function (value, key) {
switch (key) { switch (key) {
case 'MainColor': case 'MainColor':
case 'AppStoreUUID':
Setting.upsert({ key: key, value: value }); Setting.upsert({ key: key, value: value });
break; break;
case 'SquaredLogo': case 'SquaredLogo':

View file

@ -1,24 +0,0 @@
import React from 'react';
import { Text, View } from 'react-native';
// Redux
import { connect } from 'react-redux';
// Style
import styles from '../../Resources/Styles/MySpaceStyle';
function mapStateToProps(state) {
return {
documents: state.app.documents,
};
}
class MySpaceScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Mon Espace</Text>
</View>
);
}
}
export default connect(mapStateToProps)(MySpaceScreen);

View file

@ -30,7 +30,6 @@ import * as FileSystem from 'expo-file-system';
function mapStateToProps(state) { function mapStateToProps(state) {
return { return {
syncVersion: state.app.syncVersion,
currentUser: state.app.currentUser, currentUser: state.app.currentUser,
locale: state.locale.locale, locale: state.locale.locale,
mainColor: state.app.mainColor, mainColor: state.app.mainColor,
@ -47,17 +46,7 @@ const mapDispatchToProps = dispatch => {
initDocuments: (lang, directories) => initDocuments: (lang, directories) =>
dispatch(initDocuments(lang, directories)), dispatch(initDocuments(lang, directories)),
initContact: currentUser => dispatch(initContact(currentUser)), initContact: currentUser => dispatch(initContact(currentUser)),
initBtns: () => dispatch({ type: 'INIT_HOME_BTNS' }), initBtns: () => dispatch({ type: 'INIT_HOME_BTNS' })
updateVersion: version =>
dispatch({
type: 'UPDATE_VERSION',
data: version,
}),
updateShowIsActive: value =>
dispatch({
type: 'UPDATE_SHOW_IS_ACTIVE',
data: value,
}),
}; };
}; };
@ -68,7 +57,6 @@ class SyncScreen extends React.Component {
downloadProgress: 0, downloadProgress: 0,
downloadingFile: false, downloadingFile: false,
processing: false, processing: false,
newApp: false,
forced: false, forced: false,
}; };
@ -159,20 +147,6 @@ class SyncScreen extends React.Component {
return; return;
} }
this.setState({ processing: true }); this.setState({ processing: true });
// * --- getVersion
const resVersion = await getCall(
SyncController.getVersion().then(res => {
return res.data;
}),
);
if (errorStatus) {
return false;
}
this.props.updateVersion(resVersion.version);
this.props.updateShowIsActive(resVersion.ShowIsActive);
this.setState({ newApp: resVersion.newApp });
// * --- getUsers // * --- getUsers
this.setState({ this.setState({
progress: 0.1, progress: 0.1,
@ -322,7 +296,6 @@ class SyncScreen extends React.Component {
} }
downloadDocuments(docs, toDelete) { downloadDocuments(docs, toDelete) {
const version = this.props.syncVersion;
this.getToDL(docs, 0).then(toDownload => { this.getToDL(docs, 0).then(toDownload => {
if (toDownload.length > 0) { if (toDownload.length > 0) {
this.setState({ progress: 0.6 }); this.setState({ progress: 0.6 });
@ -330,7 +303,7 @@ class SyncScreen extends React.Component {
this.download(toDownload, docProgress, 0).then(status => { this.download(toDownload, docProgress, 0).then(status => {
if (status === true) { if (status === true) {
this.deleteFile(toDelete, 0).then(delStatus => { this.deleteFile(toDelete, 0).then(delStatus => {
this.finishSync(version); this.finishSync();
}); });
} else { } else {
this.setState({ this.setState({
@ -341,7 +314,7 @@ class SyncScreen extends React.Component {
} else { } else {
this.deleteFile(toDelete, 0).then(status => { this.deleteFile(toDelete, 0).then(status => {
this.setState({ progress: 1 }); this.setState({ progress: 1 });
this.finishSync(version); this.finishSync();
}); });
} }
}); });
@ -407,7 +380,10 @@ class SyncScreen extends React.Component {
if (this.state.downloadingFile === false) { if (this.state.downloadingFile === false) {
this.setState({ downloadingFile: true }); this.setState({ downloadingFile: true });
} }
const endpoint = SyncController.getUrlBo() + '/storage/docs/'; const tenantUrl = SyncController.getUrlBo();
const rootUrl = tenantUrl.substring(0, tenantUrl.lastIndexOf('/'));
const tenantId = tenantUrl.match(/[^\/]+$/)[0];
const endpoint = rootUrl + '/storage/docs/' + tenantId + "/";
const doc = documents[i]; const doc = documents[i];
this.setState({ this.setState({
txtStep: txtStep:
@ -442,7 +418,7 @@ class SyncScreen extends React.Component {
} }
} }
finishSync(version) { finishSync() {
this.props.init(); this.props.init();
this.props.initUsers(); this.props.initUsers();
this.props.initContact(this.props.currentUser); this.props.initContact(this.props.currentUser);
@ -452,34 +428,10 @@ class SyncScreen extends React.Component {
if (this.state.forced) { if (this.state.forced) {
SyncController.setInstalled(); SyncController.setInstalled();
} }
SyncController.updateVersion(version);
this.setState({ this.setState({
txtStep: i18n.t('sync_s.update_completed') + '.', txtStep: i18n.t('sync_s.update_completed') + '.',
processing: false, 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'),
onPress: () => console.debug('Cancel Pressed'),
style: 'cancel',
},
{
text: i18n.t('sync_s.open_store'),
onPress: () =>
Linking.openURL(url).catch(err =>
console.error('An error occurred', err),
),
},
],
{ cancelable: false },
);
}
} }
/** /**

View file

@ -48,8 +48,7 @@
"folders": "Ordner", "folders": "Ordner",
"video": "Video", "video": "Video",
"contact_details": "Kontaktdaten", "contact_details": "Kontaktdaten",
"results_search": "Suchergebnisse", "results_search": "Suchergebnisse"
"my_space": "Mein Raum"
}, },
"login_s": { "login_s": {
"username": "Benutzername", "username": "Benutzername",

View file

@ -48,8 +48,7 @@
"folders": "Folders", "folders": "Folders",
"video": "Video", "video": "Video",
"contact_details": "Contact information", "contact_details": "Contact information",
"results_search": "Search results", "results_search": "Search results"
"my_space": "Personal Dashboard"
}, },
"login_s": { "login_s": {
"username": "Username", "username": "Username",

View file

@ -47,8 +47,7 @@
"folders": "Dossiers", "folders": "Dossiers",
"video": "Vidéo", "video": "Vidéo",
"contact_details": "Détails du contact", "contact_details": "Détails du contact",
"results_search": "Résultat(s) de votre recherche", "results_search": "Résultat(s) de votre recherche"
"my_space": "Mon espace"
}, },
"login_s": { "login_s": {
"username": "Identifiant", "username": "Identifiant",

File diff suppressed because it is too large Load diff