Improved doc and typing, improved API connection handling

This commit is contained in:
Arnaud Vergnet 2020-07-01 13:14:17 +02:00
parent 3f14f7bb96
commit b813aa0b83
6 changed files with 138 additions and 76 deletions

View file

@ -1,3 +1,5 @@
// @flow
import i18n from "i18n-js";
/**

View file

@ -1,14 +1,13 @@
// @flow
import type {Machine} from "../screens/Proxiwash/ProxiwashScreen";
/**
* Singleton class used to manage themes
* Singleton class used to manage april fools
*/
export default class AprilFoolsManager {
static instance: AprilFoolsManager | null = null;
aprilFoolsEnabled: boolean;
static fakeMachineNumber = [
"",
"cos(ln(1))",
@ -24,6 +23,7 @@ export default class AprilFoolsManager {
"1×10¹+1×10⁰",
"Re(√192e^(iπ/6))",
];
aprilFoolsEnabled: boolean;
constructor() {
let today = new Date();
@ -40,7 +40,13 @@ export default class AprilFoolsManager {
AprilFoolsManager.instance;
}
static getFakeMenuItem(menu: Object) {
/**
* Adds fake menu entries
*
* @param menu
* @returns {Object}
*/
static getFakeMenuItem(menu: Array<{dishes: Array<{name: string}>}>) {
menu[1]["dishes"].splice(4, 0, {name: "Coq au vin"});
menu[1]["dishes"].splice(2, 0, {name: "Bat'Soupe"});
menu[1]["dishes"].splice(1, 0, {name: "Pave de loup"});
@ -49,16 +55,26 @@ export default class AprilFoolsManager {
return menu;
}
static getNewProxiwashDryerOrderedList(dryers: Array<Object>) {
if (dryers !== undefined) {
/**
* Changes proxiwash dryers order
*
* @param dryers
*/
static getNewProxiwashDryerOrderedList(dryers: Array<Machine> | null) {
if (dryers != null) {
let second = dryers[1];
dryers.splice(1, 1);
dryers.push(second);
}
}
static getNewProxiwashWasherOrderedList(washers: Array<Object>) {
if (washers !== undefined) {
/**
* Changes proxiwash washers order
*
* @param washers
*/
static getNewProxiwashWasherOrderedList(washers: Array<Machine> | null) {
if (washers != null) {
let first = washers[0];
let second = washers[1];
let fifth = washers[4];
@ -67,14 +83,25 @@ export default class AprilFoolsManager {
washers.splice(4, 1, ninth);
washers.splice(1, 1, first);
washers.splice(0, 1, fifth);
// washers.push(fifth);
}
}
/**
* Gets the new display number for the given machine number
*
* @param number
* @returns {string}
*/
static getProxiwashMachineDisplayNumber(number: number) {
return AprilFoolsManager.fakeMachineNumber[number];
}
/**
* Gets the new and ugly april fools theme
*
* @param currentTheme
* @returns {{colors: {textDisabled: string, agendaDayTextColor: string, surface: string, background: string, dividerBackground: string, accent: string, agendaBackgroundColor: string, tabIcon: string, card: string, primary: string}}}
*/
static getAprilFoolsTheme(currentTheme: Object) {
return {
...currentTheme,

View file

@ -23,15 +23,13 @@ export default class ConnectionManager {
#email: string;
#token: string | null;
listeners: Array<Function>;
constructor() {
this.#token = null;
this.listeners = [];
}
/**
* Get this class instance or create one if none is found
* Gets this class instance or create one if none is found
*
* @returns {ConnectionManager}
*/
static getInstance(): ConnectionManager {
@ -40,21 +38,20 @@ export default class ConnectionManager {
ConnectionManager.instance;
}
getToken() {
/**
* Gets the current token
*
* @returns {string | null}
*/
getToken(): string | null {
return this.#token;
}
onLoginStateChange(newState: boolean) {
for (let i = 0; i < this.listeners.length; i++) {
if (this.listeners[i] !== undefined)
this.listeners[i](newState);
}
}
addLoginStateListener(listener: Function) {
this.listeners.push(listener);
}
/**
* Tries to recover login token from the secure keychain
*
* @returns {Promise<R>}
*/
async recoverLogin() {
return new Promise((resolve, reject) => {
if (this.getToken() !== null)
@ -64,7 +61,6 @@ export default class ConnectionManager {
.then((data) => {
if (data) {
this.#token = data.password;
this.onLoginStateChange(true);
resolve(this.#token);
} else
reject(false);
@ -76,17 +72,28 @@ export default class ConnectionManager {
});
}
/**
* Check if the user has a valid token
*
* @returns {boolean}
*/
isLoggedIn() {
return this.getToken() !== null;
}
/**
* Saves the login token in the secure keychain
*
* @param email
* @param token
* @returns {Promise<R>}
*/
async saveLogin(email: string, token: string) {
return new Promise((resolve, reject) => {
Keychain.setInternetCredentials(SERVER_NAME, 'token', token)
.then(() => {
this.#token = token;
this.#email = email;
this.onLoginStateChange(true);
resolve(true);
})
.catch(() => {
@ -95,12 +102,16 @@ export default class ConnectionManager {
});
}
/**
* Deletes the login token from the keychain
*
* @returns {Promise<R>}
*/
async disconnect() {
return new Promise((resolve, reject) => {
Keychain.resetInternetCredentials(SERVER_NAME)
.then(() => {
this.#token = null;
this.onLoginStateChange(false);
resolve(true);
})
.catch(() => {
@ -109,6 +120,16 @@ export default class ConnectionManager {
});
}
/**
* Sends the given login and password to the api.
* If the combination is valid, the login token is received and saved in the secure keychain.
* If not, the promise is rejected with the corresponding error code.
*
* @param email
* @param password
* @returns {Promise<R>}
*/
async connect(email: string, password: string) {
return new Promise((resolve, reject) => {
const data = {
@ -117,6 +138,7 @@ export default class ConnectionManager {
};
apiRequest(AUTH_PATH, 'POST', data)
.then((response) => {
if (this.isConnectionResponseValid(response)) {
this.saveLogin(email, response.token)
.then(() => {
resolve(true);
@ -124,12 +146,20 @@ export default class ConnectionManager {
.catch(() => {
reject(ERROR_TYPE.TOKEN_SAVE);
});
} else
reject(ERROR_TYPE.SERVER_ERROR);
})
.catch((error) => reject(error));
});
}
isConnectionResponseValid(response: Object) {
/**
* Checks if the API connection response is correctly formatted
*
* @param response
* @returns {boolean}
*/
isConnectionResponseValid(response: { [key: string]: any }) {
let valid = isResponseValid(response);
if (valid && response.error === ERROR_TYPE.SUCCESS)
@ -140,6 +170,13 @@ export default class ConnectionManager {
return valid;
}
/**
* Sends an authenticated request with the login token to the API
*
* @param path
* @param params
* @returns {Promise<R>}
*/
async authenticatedRequest(path: string, params: Object) {
return new Promise((resolve, reject) => {
if (this.getToken() !== null) {

View file

@ -45,6 +45,10 @@ export default class DateManager {
DateManager.instance;
}
static isWeekend(date: Date) {
return date.getDay() === 6 || date.getDay() === 0;
}
/**
* Gets a translated string representing the given date.
*
@ -58,8 +62,4 @@ export default class DateManager {
return this.daysOfWeek[date.getDay()] + " " + date.getDate() + " " + this.monthsOfYear[date.getMonth()] + " " + date.getFullYear();
}
static isWeekend(date: Date) {
return date.getDay() === 6 || date.getDay() === 0;
}
}

View file

@ -19,8 +19,4 @@ export default class LocaleManager {
i18n.translations = {fr, en};
i18n.locale = RNLocalize.findBestAvailableLanguage(["en", "fr"]).languageTag;
}
static getCurrentLocale() {
return RNLocalize.findBestAvailableLanguage(["en", "fr"]).languageTag;
}
}