forked from vergnet/application-amicale
Recover credentials on startup for increased performance and added login/profile button on home
This commit is contained in:
parent
1ede8f4e9a
commit
17016b6452
6 changed files with 85 additions and 62 deletions
5
App.js
5
App.js
|
@ -14,6 +14,7 @@ import {initExpoToken} from "./utils/Notifications";
|
||||||
import {Provider as PaperProvider} from 'react-native-paper';
|
import {Provider as PaperProvider} from 'react-native-paper';
|
||||||
import AprilFoolsManager from "./managers/AprilFoolsManager";
|
import AprilFoolsManager from "./managers/AprilFoolsManager";
|
||||||
import Update from "./constants/Update";
|
import Update from "./constants/Update";
|
||||||
|
import ConnectionManager from "./managers/ConnectionManager";
|
||||||
|
|
||||||
type Props = {};
|
type Props = {};
|
||||||
|
|
||||||
|
@ -91,6 +92,10 @@ export default class App extends React.Component<Props, State> {
|
||||||
await AsyncStorageManager.getInstance().loadPreferences();
|
await AsyncStorageManager.getInstance().loadPreferences();
|
||||||
ThemeManager.getInstance().setUpdateThemeCallback(this.onUpdateTheme);
|
ThemeManager.getInstance().setUpdateThemeCallback(this.onUpdateTheme);
|
||||||
await initExpoToken();
|
await initExpoToken();
|
||||||
|
try {
|
||||||
|
await ConnectionManager.getInstance().recoverLogin();
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
this.onLoadFinished();
|
this.onLoadFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class AuthenticatedScreen extends React.Component<Props, State> {
|
||||||
loading: true,
|
loading: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
currentUserToken: string;
|
currentUserToken: string | null;
|
||||||
connectionManager: ConnectionManager;
|
connectionManager: ConnectionManager;
|
||||||
errorCode: number;
|
errorCode: number;
|
||||||
data: Object;
|
data: Object;
|
||||||
|
@ -35,8 +35,6 @@ class AuthenticatedScreen extends React.Component<Props, State> {
|
||||||
this.colors = props.theme.colors;
|
this.colors = props.theme.colors;
|
||||||
this.connectionManager = ConnectionManager.getInstance();
|
this.connectionManager = ConnectionManager.getInstance();
|
||||||
this.props.navigation.addListener('focus', this.onScreenFocus.bind(this));
|
this.props.navigation.addListener('focus', this.onScreenFocus.bind(this));
|
||||||
|
|
||||||
this.fetchData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onScreenFocus() {
|
onScreenFocus() {
|
||||||
|
@ -47,26 +45,24 @@ class AuthenticatedScreen extends React.Component<Props, State> {
|
||||||
fetchData = () => {
|
fetchData = () => {
|
||||||
if (!this.state.loading)
|
if (!this.state.loading)
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
this.connectionManager.isLoggedIn()
|
if (this.connectionManager.isLoggedIn()) {
|
||||||
.then(() => {
|
this.connectionManager.authenticatedRequest(this.props.link)
|
||||||
this.connectionManager.authenticatedRequest(this.props.link)
|
.then((data) => {
|
||||||
.then((data) => {
|
this.onFinishedLoading(data, -1);
|
||||||
this.onFinishedLoading(data, -1);
|
})
|
||||||
})
|
.catch((error) => {
|
||||||
.catch((error) => {
|
this.onFinishedLoading(undefined, error);
|
||||||
this.onFinishedLoading(undefined, error);
|
});
|
||||||
});
|
} else {
|
||||||
})
|
this.onFinishedLoading(undefined, ERROR_TYPE.BAD_CREDENTIALS);
|
||||||
.catch((error) => {
|
}
|
||||||
this.onFinishedLoading(undefined, ERROR_TYPE.BAD_CREDENTIALS);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onFinishedLoading(data: Object, error: number) {
|
onFinishedLoading(data: Object, error: number) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.currentUserToken = data !== undefined
|
this.currentUserToken = data !== undefined
|
||||||
? this.connectionManager.getToken()
|
? this.connectionManager.getToken()
|
||||||
: '';
|
: null;
|
||||||
this.errorCode = error;
|
this.errorCode = error;
|
||||||
this.setState({loading: false});
|
this.setState({loading: false});
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,13 +154,12 @@ class SideBar extends React.PureComponent<Props, State> {
|
||||||
];
|
];
|
||||||
this.getRenderItem = this.getRenderItem.bind(this);
|
this.getRenderItem = this.getRenderItem.bind(this);
|
||||||
this.colors = props.theme.colors;
|
this.colors = props.theme.colors;
|
||||||
ConnectionManager.getInstance().setLoginCallback((value) => this.onLoginStateChange(value));
|
ConnectionManager.getInstance().addLoginStateListener((value) => this.onLoginStateChange(value));
|
||||||
this.state = {
|
this.state = {
|
||||||
active: 'Home',
|
active: 'Home',
|
||||||
isLoggedIn: false,
|
isLoggedIn: ConnectionManager.getInstance().isLoggedIn(),
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
};
|
};
|
||||||
ConnectionManager.getInstance().isLoggedIn().then(data => undefined).catch(error => undefined);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
showDisconnectDialog = () => this.setState({ dialogVisible: true });
|
showDisconnectDialog = () => this.setState({ dialogVisible: true });
|
||||||
|
|
|
@ -16,10 +16,17 @@ export default class ConnectionManager {
|
||||||
static instance: ConnectionManager | null = null;
|
static instance: ConnectionManager | null = null;
|
||||||
|
|
||||||
#email: string;
|
#email: string;
|
||||||
#token: string;
|
#token: string | null;
|
||||||
|
|
||||||
loginCallback: Function;
|
loginCallback: Function;
|
||||||
|
|
||||||
|
listeners: Array<Function>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.#token = null;
|
||||||
|
this.listeners = [];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get this class instance or create one if none is found
|
* Get this class instance or create one if none is found
|
||||||
* @returns {ConnectionManager}
|
* @returns {ConnectionManager}
|
||||||
|
@ -35,20 +42,24 @@ export default class ConnectionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoginStateChange(newState: boolean) {
|
onLoginStateChange(newState: boolean) {
|
||||||
this.loginCallback(newState);
|
for (let i = 0; i < this.listeners.length; i++) {
|
||||||
|
if (this.listeners[i] !== undefined)
|
||||||
|
this.listeners[i](newState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoginCallback(callback: Function) {
|
addLoginStateListener(listener: Function) {
|
||||||
this.loginCallback = callback;
|
this.listeners.push(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
async recoverLogin() {
|
async recoverLogin() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (this.#token !== undefined)
|
if (this.#token !== null)
|
||||||
resolve(this.#token);
|
resolve(this.#token);
|
||||||
else {
|
else {
|
||||||
SecureStore.getItemAsync('token')
|
SecureStore.getItemAsync('token')
|
||||||
.then((token) => {
|
.then((token) => {
|
||||||
|
this.#token = token;
|
||||||
if (token !== null) {
|
if (token !== null) {
|
||||||
this.onLoginStateChange(true);
|
this.onLoginStateChange(true);
|
||||||
resolve(token);
|
resolve(token);
|
||||||
|
@ -62,16 +73,8 @@ export default class ConnectionManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async isLoggedIn() {
|
isLoggedIn() {
|
||||||
return new Promise((resolve, reject) => {
|
return this.#token !== null;
|
||||||
this.recoverLogin()
|
|
||||||
.then(() => {
|
|
||||||
resolve(true);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
reject(false);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveLogin(email: string, token: string) {
|
async saveLogin(email: string, token: string) {
|
||||||
|
@ -93,6 +96,7 @@ export default class ConnectionManager {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
SecureStore.deleteItemAsync('token')
|
SecureStore.deleteItemAsync('token')
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
this.#token = null;
|
||||||
this.onLoginStateChange(false);
|
this.onLoginStateChange(false);
|
||||||
resolve(true);
|
resolve(true);
|
||||||
})
|
})
|
||||||
|
@ -166,32 +170,29 @@ export default class ConnectionManager {
|
||||||
|
|
||||||
async authenticatedRequest(url: string) {
|
async authenticatedRequest(url: string) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.recoverLogin()
|
if (this.#token !== null) {
|
||||||
.then(token => {
|
fetch(url, {
|
||||||
fetch(url, {
|
method: 'POST',
|
||||||
method: 'POST',
|
headers: new Headers({
|
||||||
headers: new Headers({
|
'Accept': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Content-Type': 'application/json',
|
}),
|
||||||
}),
|
body: JSON.stringify({token: this.#token})
|
||||||
body: JSON.stringify({token: token})
|
}).then(async (response) => response.json())
|
||||||
}).then(async (response) => response.json())
|
.then((data) => {
|
||||||
.then((data) => {
|
if (this.isRequestResponseValid(data)) {
|
||||||
if (this.isRequestResponseValid(data)) {
|
if (data.state)
|
||||||
if (data.state)
|
resolve(data.data);
|
||||||
resolve(data.data);
|
else
|
||||||
else
|
reject(ERROR_TYPE.BAD_CREDENTIALS);
|
||||||
reject(ERROR_TYPE.BAD_CREDENTIALS);
|
} else
|
||||||
} else
|
|
||||||
reject(ERROR_TYPE.CONNECTION_ERROR);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
reject(ERROR_TYPE.CONNECTION_ERROR);
|
reject(ERROR_TYPE.CONNECTION_ERROR);
|
||||||
});
|
})
|
||||||
})
|
.catch(() => {
|
||||||
.catch(() => {
|
reject(ERROR_TYPE.CONNECTION_ERROR);
|
||||||
reject(ERROR_TYPE.NO_TOKEN);
|
});
|
||||||
});
|
} else
|
||||||
|
reject(ERROR_TYPE.NO_TOKEN);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,8 @@ const emailRegex = /^.+@.+\..+$/;
|
||||||
class LoginScreen extends React.Component<Props, State> {
|
class LoginScreen extends React.Component<Props, State> {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
email: '',
|
email: 'vergnet@etud.insa-toulouse.fr',
|
||||||
password: '',
|
password: '3D514ùdsqg',
|
||||||
isEmailValidated: false,
|
isEmailValidated: false,
|
||||||
isPasswordValidated: false,
|
isPasswordValidated: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
|
|
@ -12,6 +12,8 @@ import PreviewEventDashboardItem from "../components/Home/PreviewEventDashboardI
|
||||||
import {stringToDate} from "../utils/Planning";
|
import {stringToDate} from "../utils/Planning";
|
||||||
import {openBrowser} from "../utils/WebBrowser";
|
import {openBrowser} from "../utils/WebBrowser";
|
||||||
import ActionsDashBoardItem from "../components/Home/ActionsDashboardItem";
|
import ActionsDashBoardItem from "../components/Home/ActionsDashboardItem";
|
||||||
|
import HeaderButton from "../components/Custom/HeaderButton";
|
||||||
|
import ConnectionManager from "../managers/ConnectionManager";
|
||||||
// import DATA from "../dashboard_data.json";
|
// import DATA from "../dashboard_data.json";
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,6 +35,7 @@ type Props = {
|
||||||
type State = {
|
type State = {
|
||||||
imageModalVisible: boolean,
|
imageModalVisible: boolean,
|
||||||
imageList: Array<Object>,
|
imageList: Array<Object>,
|
||||||
|
isLoggedIn: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,10 +55,12 @@ class HomeScreen extends React.Component<Props, State> {
|
||||||
state = {
|
state = {
|
||||||
imageModalVisible: false,
|
imageModalVisible: false,
|
||||||
imageList: [],
|
imageList: [],
|
||||||
|
isLoggedIn: ConnectionManager.getInstance().isLoggedIn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
ConnectionManager.getInstance().addLoginStateListener((value) => this.setState({isLoggedIn: value}));
|
||||||
this.onProxiwashClick = this.onProxiwashClick.bind(this);
|
this.onProxiwashClick = this.onProxiwashClick.bind(this);
|
||||||
this.onTutorInsaClick = this.onTutorInsaClick.bind(this);
|
this.onTutorInsaClick = this.onTutorInsaClick.bind(this);
|
||||||
this.onMenuClick = this.onMenuClick.bind(this);
|
this.onMenuClick = this.onMenuClick.bind(this);
|
||||||
|
@ -76,6 +81,23 @@ class HomeScreen extends React.Component<Props, State> {
|
||||||
return date.toLocaleString();
|
return date.toLocaleString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.props.navigation.setOptions({
|
||||||
|
headerRight: this.getHeaderButton,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getHeaderButton = () => {
|
||||||
|
const screen = this.state.isLoggedIn
|
||||||
|
? "ProfileScreen"
|
||||||
|
: "LoginScreen";
|
||||||
|
const icon = this.state.isLoggedIn
|
||||||
|
? "account"
|
||||||
|
: "login";
|
||||||
|
const onPress = () => this.props.navigation.navigate(screen);
|
||||||
|
return <HeaderButton icon={icon} onPress={onPress}/>;
|
||||||
|
};
|
||||||
|
|
||||||
onProxiwashClick() {
|
onProxiwashClick() {
|
||||||
this.props.navigation.navigate('Proxiwash');
|
this.props.navigation.navigate('Proxiwash');
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue