save tmp clean

This commit is contained in:
Vincent BRIDIER 2022-12-28 16:32:30 +01:00
parent 56e98c5d5c
commit 064baab447
No known key found for this signature in database
GPG key ID: 8571BFA20420D512
17 changed files with 231 additions and 151 deletions

View file

@ -3,6 +3,14 @@ import React from 'react';
// Redux
import { Provider } from 'react-redux';
import { store } from './App/Store/ConfigureStore';
// Deps
import 'react-native-gesture-handler';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { TouchableOpacity, View, Image, Text, TextInput, StyleSheet, Alert } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome5';
import FlashMessage, { showMessage } from 'react-native-flash-message';
import * as SplashScreen from 'expo-splash-screen';
// i18n
import i18n from "./I18n";
// Controllers
@ -10,117 +18,60 @@ import SyncController from './App/Controllers/SyncController';
// Views
import InstallScreen from './App/Views/InstallScreen';
import LoginScreen from './App/Views/LoginScreen';
import OnlyVideosScreen from './App/Views/OnlyVideosScreen';
import ContactScreen from './App/Views/ContactScreen';
import ContactDetailsScreen from './App/Views/ContactDetailsScreen';
// END V2
import SyncScreen from './App/Views/SyncScreen';
import HomeScreen from './App/Views/HomeScreen';
import 'react-native-gesture-handler';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { TouchableOpacity, View, Image, Text, TextInput, StyleSheet, Alert } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome5';
import FlashMessage, { showMessage } from 'react-native-flash-message';
import * as SplashScreen from 'expo-splash-screen';
import DirectoriesScreen from './Views/Directories';
import VideoScreen from './Views/Video';
import PDFScreen from './Views/PDF';
import ContactScreen from './Views/Contact';
import ContactDetailsScreen from './Views/ContactDetails';
import OnlyVideosScreen from './Views/OnlyVideos';
import SearchScreen from "./Views/Search";
import MySpaceScreen from './Views/MySpace';
// V2
//SplashScreen.preventAutoHideAsync(); //Keep
// V2
store.dispatch({ type: 'INIT_APP' });
store.dispatch({ type: 'INIT_LOCALE' });
store.dispatch({ type: 'INIT_USERS' });
// END V2
const Stack = createNativeStackNavigator();
// END V2
class App extends React.Component {
state = {
logged: false,
isSetup: false,
isLogged: false,
searchTxt: '',
sendEmail: '',
ShowIsActive: '0'
sendEmail: ''
};
componentDidMount(): void {
componentDidMount() {
const unsubscribe = store.subscribe(this.handleChange.bind(this));
// if (Sync.isLogged()) {
// store.dispatch({
// type: 'SET_CURRENT_USER',
// data: CommonModel.get('isLogged').value,
// });
// store.dispatch({ type: 'SET_LOGGED', data: true });
// }
if (SyncController.isLogged()) {
store.dispatch({ type: 'SET_CURRENT_USER' });
store.dispatch({ type: 'SET_LOGGED', data: true });
}
this.setState({
isSetup: store.getState().app.isSetup,
isLogged: store.getState().app.logged,
});
}
handleChange() {
const logged = store.getState().app.logged;
if (logged === false) {
CommonModel.delete('isLogged');
}
if (logged !== undefined) {
this.setState({ logged: logged });
}
this.setState({ ShowIsActive: store.getState().app.ShowIsActive });
}
LogoTitle(title) {
return (
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Image
style={{ width: 100, height: 50, resizeMode: 'stretch' }}
source={require('./assets/img/logo.png')}
/>
<Text style={{ marginLeft: 10, fontSize: 18 }}>{title}</Text>
</View>
);
}
SendEmail() {
return (
<View style={{ flexDirection: 'row', alignItems: 'center', marginRight: 10 }}>
<TextInput style={styles.searchInput} placeholder={i18n.t('global.email')} value={this.state.sendEmail} onChangeText={(text) => this.setState({ sendEmail: text })} />
<TouchableOpacity style={styles.btnSearch} onPress={() => {
if (this.state.sendEmail.length > 0) {
if (Helpers.isEmailValid(this.state.sendEmail)) {
const email = {
email: this.state.sendEmail,
subject: i18n.t('app.file_sharing'),
message: '',
documents: JSON.stringify([store.getState().currentOpenedDoc]),
user_id: store.getState().currentUser.id
};
store.dispatch({ type: 'SEND_BROCHURE', data: email });
showMessage({
message: i18n.t('global.message_sent') + '.',
description: i18n.t('global.message_will_be_sent_after_sync') + '.',
type: 'success',
duration: 1500,
});
this.setState({ sendEmail: '' });
} else {
Alert.alert(i18n.t('global.warning') + ' !', i18n.t('error.invalid_email_address') + '.', [
{ text: 'OK' },
],
{ cancelable: false },
);
}
}
}}>
<Icon name={'paper-plane'} size={20} color={'white'} />
</TouchableOpacity>
</View>
);
this.setState({
isSetup: store.getState().app.isSetup,
isLogged: store.getState().app.logged,
}); // to force re-rendering
console.log("state changed")
}
render() {
@ -128,7 +79,7 @@ class App extends React.Component {
<Provider store={store}>
<NavigationContainer>
<Stack.Navigator>
{store.getState().app.isSetup === false &&
{this.state.isSetup === false &&
<Stack.Screen
name="InstallScreen"
component={InstallScreen}
@ -139,7 +90,6 @@ class App extends React.Component {
<TouchableOpacity
onPress={() => {
store.dispatch({ type: 'EDIT_LOCALE' });
this.setState({ state: this.state }); // to force re-rendering
}}
style={{ marginRight: 15 }}>
<Image source={this.renderFlag()} style={{ width: 25, height: 25 }} />
@ -149,7 +99,7 @@ class App extends React.Component {
})}
/>
}
{this.state.logged === false ? (
{this.state.isLogged === false ? (
<Stack.Screen
name="LoginScreen"
component={LoginScreen}
@ -160,7 +110,6 @@ class App extends React.Component {
<TouchableOpacity
onPress={() => {
store.dispatch({ type: 'EDIT_LOCALE' });
this.setState({ state: this.state }); // to force re-rendering
}}
style={{ marginRight: 15 }}>
<Image source={this.renderFlag()} style={{ width: 25, height: 25 }} />
@ -170,7 +119,7 @@ class App extends React.Component {
})}
/>
) : (
<Stack.Screen
<Stack.Screen
name="HomeScreen"
component={HomeScreen}
options={(navigation, route) => ({
@ -198,7 +147,7 @@ class App extends React.Component {
style={{ marginRight: 25 }}>
<Image source={this.renderFlag()} style={{ width: 25, height: 25 }} />
</TouchableOpacity>
{this.state.ShowIsActive === '1' && (
{store.getState().app.ShowIsActive === '1' && (
<TouchableOpacity
onPress={() => navigation.navigation.navigate('MySpaceScreen')}
style={{ marginRight: 25 }}>
@ -224,12 +173,14 @@ class App extends React.Component {
</View>
),
})}
/>
/>
)}
<Stack.Screen
name="SyncScreen"
component={SyncScreen}
options={{ headerTitle: () => this.LogoTitle(i18n.t('global.synchronization')) }}
options={{
headerTitle: () => this.LogoTitle(i18n.t('global.synchronization'))
}}
/>
<Stack.Screen
name="DirectoriesScreen"
@ -318,6 +269,55 @@ class App extends React.Component {
);
}
LogoTitle(title) {
return (
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Image
style={{ width: 100, height: 50, resizeMode: 'stretch' }}
source={require('./assets/img/logo.png')}
/>
<Text style={{ marginLeft: 10, fontSize: 18 }}>{title}</Text>
</View>
);
}
SendEmail() {
return (
<View style={{ flexDirection: 'row', alignItems: 'center', marginRight: 10 }}>
<TextInput style={styles.searchInput} placeholder={i18n.t('global.email')} value={this.state.sendEmail} onChangeText={(text) => this.setState({ sendEmail: text })} />
<TouchableOpacity style={styles.btnSearch} onPress={() => {
if (this.state.sendEmail.length > 0) {
if (Helpers.isEmailValid(this.state.sendEmail)) {
const email = {
email: this.state.sendEmail,
subject: i18n.t('app.file_sharing'),
message: '',
documents: JSON.stringify([store.getState().currentOpenedDoc]),
user_id: store.getState().currentUser.id
};
store.dispatch({ type: 'SEND_BROCHURE', data: email });
showMessage({
message: i18n.t('global.message_sent') + '.',
description: i18n.t('global.message_will_be_sent_after_sync') + '.',
type: 'success',
duration: 1500,
});
this.setState({ sendEmail: '' });
} else {
Alert.alert(i18n.t('global.warning') + ' !', i18n.t('error.invalid_email_address') + '.', [
{ text: 'OK' },
],
{ cancelable: false },
);
}
}
}}>
<Icon name={'paper-plane'} size={20} color={'white'} />
</TouchableOpacity>
</View>
);
}
renderFlag() {
let flag;
switch (store.getState().locale.locale) {

View file

@ -135,14 +135,6 @@ class SyncController {
return true;
}
isInstalled() {
const test = Setting.get('installed');
if (test === false) {
return false;
}
return true;
}
isLogged() {
const logged = Setting.get('isLogged');
const loggedTime = Setting.get('loggedTime');

View file

@ -7,4 +7,6 @@ export const INIT_USERS = "INIT_USERS";
export const INIT_CONTACT = "INIT_CONTACT";
export const ADD_CONTACT = "ADD_CONTACT";
export const EDIT_CONTACT = "EDIT_CONTACT";
export const DELETE_CONTACT = "DELETE_CONTACT";
export const DELETE_CONTACT = "DELETE_CONTACT";
// Documents
export const INIT_DOCUMENTS = "INIT_DOCUMENTS";

View file

@ -2,20 +2,23 @@ import { INIT_CONTACT, ADD_CONTACT, EDIT_CONTACT, DELETE_CONTACT } from "./actio
/**
* Init contact
* @param {object} currentUser The currentUser
* @param {object} data The contact data
*/
export const initContact = data => {
export const initContact = (currentUser, data) => {
return {
type: INIT_CONTACT,
currentUser,
data,
};
};
/**
* Add contact
* @param {object} currentUser The currentUser
* @param {object} data The contact data
*/
export const addContact = data => {
export const addContact = (currentUser, data) => {
return {
type: ADD_CONTACT,
data,
@ -24,10 +27,11 @@ export const addContact = data => {
/**
* Edit contact
* @param {object} currentUser The currentUser
* @param {string} uid The contact uid
* @param {object} data The contact data
*/
export const editContact = (uid, data) => {
export const editContact = (currentUser, uid, data) => {
return {
type: EDIT_CONTACT,
uid,
@ -37,9 +41,10 @@ export const editContact = (uid, data) => {
/**
* Delete contact
* @param {object} currentUser The currentUser
* @param {string} uid The contact uid
*/
export const deleteContact = uid => {
export const deleteContact = (currentUser, uid) => {
return {
type: DELETE_CONTACT,
uid,

View file

@ -0,0 +1,16 @@
import { INIT_DOCUMENTS } from "./actionType";
/**
* Init contact
* @param {string} lang The lang
* @param {object} directories Directories
* @param {object} data The document data
*/
export const initDocuments = (lang, directories, data) => {
return {
type: INIT_DOCUMENTS,
lang,
directories,
data,
};
};

View file

@ -1,13 +1,15 @@
import { createStore, combineReducers } from "redux";
import appReducer from "./Reducers/AppReducer";
import contactsReducer from "./Reducers/contacts";
import documentsReducer from "./Reducers/documents";
import localesReducer from "./Reducers/locales";
import usersReducer from "./Reducers/users";
import contactsReducer from "./Reducers/contacts";
const rootReducer = combineReducers({
app: appReducer,
contacts: contactsReducer,
documents: documentsReducer,
locale: localesReducer,
users: usersReducer
});

View file

@ -1,15 +1,14 @@
import SyncController from "../../Controllers/SyncController";
// Database
import { Setting, Directory, Document, SendBrochure } from '../../../Database';
import { Setting, Directory, SendBrochure } from '../../../Database';
const initialState = {
isSetup: false,
locale: 'fr',
directories: {},
documents: {},
syncVersion: 0,
logged: undefined,
currentUser: {},
logged: false,
directories: {},
syncVersion: 0,
currentOpenedDoc: {},
ShowIsActive: 0,
};
@ -34,26 +33,20 @@ const reducer = (state = initialState, action) => {
let directories = Directory.getAll(
state.currentUser.role,
state.currentUser.authorizedFolders,
false,
true,
state.locale
);
let docs = Document.getAll(directories);
let ShowIsActive = Setting.get('ShowIsActive');
return {
...state,
directories: Directory.getAll(
state.currentUser.role,
state.currentUser.authorizedFolders,
true,
state.locale
),
documents: docs.filter(item => item.lang === state.locale),
directories: directories,
ShowIsActive: ShowIsActive === undefined ? false : ShowIsActive.value,
};
case 'SET_CURRENT_USER':
let user = Setting.get('isLogged').value
return {
...state,
currentUser: JSON.parse(action.data),
currentUser: JSON.parse(user),
};
case 'SET_LOGGED':
if (action.data === false) {

View file

@ -6,29 +6,33 @@ const initialState = [];
const reducer = (state = initialState, action) => {
switch (action.type) {
case INIT_CONTACT:
case INIT_CONTACT: {
return {
...state,
contacts: Contact.getByUser(state.currentUser.id),
contacts: Contact.getByUser(action.currentUser.id),
};
case ADD_CONTACT:
}
case ADD_CONTACT: {
Contact.add(action.data);
return {
...state,
contacts: Contact.getByUser(state.currentUser.id),
contacts: Contact.getByUser(action.currentUser.id),
};
case EDIT_CONTACT:
}
case EDIT_CONTACT: {
Contact.update(action.data);
return {
...state,
contacts: Contact.getByUser(state.currentUser.id),
contacts: Contact.getByUser(action.currentUser.id),
};
case DELETE_CONTACT:
}
case DELETE_CONTACT: {
Contact.delete(action.data);
return {
...state,
contacts: Contact.getByUser(state.currentUser.id),
contacts: Contact.getByUser(action.currentUser.id),
};
}
default: {
return state;

View file

@ -0,0 +1,23 @@
import { INIT_DOCUMENTS } from "../Actions/actionType";
// Models
import { Document } from "../../../Database";
const initialState = [];
const reducer = (state = initialState, action) => {
switch (action.type) {
case INIT_DOCUMENTS: {
let docs = Document.getAll(action.directories);
return [
...state,
docs.filter(item => item.lang === action.lang)
];
}
default: {
return state;
}
}
};
export default reducer;

View file

@ -31,7 +31,7 @@ import { BarCodeScanner } from 'expo-barcode-scanner';
function mapStateToProps(state) {
return {
contacts: state.app.contacts,
contacts: state.contacts.contacts,
currentUser: state.app.currentUser,
};
}

View file

@ -27,8 +27,8 @@ import styles from '../../Resources/Styles/ContactStyle';
function mapStateToProps(state) {
return {
users: state.app.users,
contacts: state.app.contacts,
users: state.users.users,
contacts: state.contacts.contacts,
documents: state.app.documents,
currentUser: state.app.currentUser,
};

View file

@ -4,6 +4,7 @@ import { View, ImageBackground, TouchableOpacity, Text, Image } from 'react-nati
import commonStyles from '../../Resources/CommonStyles';
// Redux
import { connect } from 'react-redux';
import { initDocuments } from '../Store/Actions/documents';
// Style
import styles from '../../Resources/Styles/HomeStyle';
// Translations
@ -18,10 +19,19 @@ function mapStateToProps(state) {
};
}
const mapDispatchToProps = dispatch => {
return {
init: (locale, directories) => {
dispatch({ type: 'INIT' })
dispatch(initDocuments(locale, directories))
}
};
};
class HomeScreen extends React.Component {
componentDidMount() {
this.props.dispatch({ type: 'INIT' });
this.props.init(this.props.locale.value, this.props.directories);
}
render() {
@ -52,4 +62,4 @@ class HomeScreen extends React.Component {
}
}
export default connect(mapStateToProps)(HomeScreen);
export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen);

View file

@ -1,6 +1,8 @@
import React from 'react';
import { View, ImageBackground, TextInput, Button, Image, Alert } from 'react-native';
// Redux
import { connect } from 'react-redux';
import { initContact } from '../Store/Actions/contacts';
// Common Styles
import commonStyles from '../../Resources/CommonStyles';
// Style
@ -17,11 +19,23 @@ import SyncController from '../Controllers/SyncController';
function mapStateToProps(state) {
return {
app: state.app,
users: state.users.users,
locale: state.locale.locale,
};
}
const mapDispatchToProps = dispatch => {
return {
initContact: currentUser => dispatch(initContact(currentUser)),
setCurrentUser: user => dispatch({
type: 'SET_CURRENT_USER',
data: JSON.stringify(user),
}),
setIsLogged: () => dispatch({ type: 'SET_LOGGED', data: true })
};
};
class LoginScreen extends React.Component {
state = {
login: 'v@b.t',
@ -85,7 +99,13 @@ class LoginScreen extends React.Component {
return;
}
const lastUser = Setting.get('lastUser');
if (lastUser === false || lastUser === undefined || lastUser.value === user.id.toString()) {
// Si on est sur une installation
if (lastUser === false || lastUser === undefined) {
this.loginAction(user, true);
return;
}
// Si on a deja une install avec une précédente connexion
if (lastUser.value === user.id.toString()) {
this.loginAction(user);
} else {
// Si user !== last user && last user not synced
@ -108,15 +128,13 @@ class LoginScreen extends React.Component {
loginAction(user, forceSync = false) {
this.setState({ login: '', password: '' });
LoginController.login(user);
this.props.dispatch({
type: 'SET_CURRENT_USER',
data: JSON.stringify(user),
});
this.props.dispatch({ type: 'SET_LOGGED', data: true });
this.props.setCurrentUser(user);
this.props.setIsLogged();
this.props.initContact(this.props.app.currentUser);
if (forceSync === true) {
this.props.navigation.navigate('SyncScreen', { isInstalled: true, forceSync: true });
this.props.navigation.navigate('SyncScreen', { forceSync: true });
}
}
}
export default connect(mapStateToProps)(LoginScreen);
export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen);

View file

@ -14,7 +14,7 @@ import styles from '../../Resources/Styles/OnlyVideosStyle';
function mapStateToProps(state) {
return {
documents: state.app.documents,
documents: state.documents,
};
}

View file

@ -2,6 +2,7 @@ import React from 'react';
import { View, Button, Alert, Text } from 'react-native';
// Redux
import { connect } from 'react-redux';
import { initDocuments } from '../Store/Actions/documents';
// Style
import styles from '../../Resources/Styles/SyncStyle';
// Translations
@ -20,9 +21,28 @@ function mapStateToProps(state) {
documents: state.app.documents,
syncVersion: state.app.syncVersion,
currentUser: state.app.currentUser,
directories: state.app.directories,
locale: state.locale.locale,
};
}
const mapDispatchToProps = dispatch => {
return {
init: (locale, directories) => {
dispatch({ type: 'INIT' })
dispatch(initDocuments(locale, directories))
},
updateVersion: version => dispatch({
type: 'UPDATE_VERSION',
data: version,
}),
updateShowIsActive: value => dispatch({
type: 'UPDATE_SHOW_IS_ACTIVE',
data: value,
})
};
};
class SyncScreen extends React.Component {
state = {
progress: 0,
@ -86,14 +106,8 @@ class SyncScreen extends React.Component {
i18n.t('error.error_has_occurred')
);
});
this.props.dispatch({
type: 'UPDATE_VERSION',
data: resVersion.version,
});
this.props.dispatch({
type: 'UPDATE_SHOW_IS_ACTIVE',
data: resVersion.ShowIsActive,
});
this.props.updateVersion(resVersion.version);
this.props.updateShowIsActive(resVersion.ShowIsActive);
this.setState({ newApp: resVersion.newApp });
// getUsers
this.setState({ txtStep: i18n.t('sync_s.updating_users') + '...' });
@ -280,7 +294,7 @@ class SyncScreen extends React.Component {
}
finishSync(version) {
this.props.dispatch({ type: 'INIT' });
this.props.init(this.props.locale.value, this.props.directories);
SyncController.updateVersion(version);
this.setState({ txtStep: i18n.t('sync_s.update_completed') + '.', processing: false });
if (this.state.newApp === true) {
@ -304,4 +318,4 @@ class SyncScreen extends React.Component {
}
export default connect(mapStateToProps)(SyncScreen);
export default connect(mapStateToProps, mapDispatchToProps)(SyncScreen);

View file

@ -54,6 +54,7 @@
"no_result": "Aucun résultat"
},
"sync_s": {
"back_home": "Retour à l'accueil",
"download": "Téléchargement",
"update_completed": "Mise à jour effectuée",
"updating_docs": "Mise à jour des documents",