From b813aa0b834de15d12f1b2835524e9867bac256b Mon Sep 17 00:00:00 2001 From: Arnaud Vergnet Date: Wed, 1 Jul 2020 13:14:17 +0200 Subject: [PATCH] Improved doc and typing, improved API connection handling --- src/constants/Update.js | 6 +- src/managers/AprilFoolsManager.js | 47 ++++++++++++---- src/managers/ConnectionManager.js | 91 ++++++++++++++++++++++--------- src/managers/DateManager.js | 8 +-- src/managers/LocaleManager.js | 4 -- src/managers/ThemeManager.js | 58 ++++++++++---------- 6 files changed, 138 insertions(+), 76 deletions(-) diff --git a/src/constants/Update.js b/src/constants/Update.js index 3ad9733..ce38d7a 100644 --- a/src/constants/Update.js +++ b/src/constants/Update.js @@ -1,3 +1,5 @@ +// @flow + import i18n from "i18n-js"; /** @@ -43,8 +45,8 @@ export default class Update { this.titleList = []; this.descriptionList = []; for (let i = 0; i < Update.slidesNumber; i++) { - this.titleList.push(i18n.t('intro.updateSlide'+ i + '.title')) - this.descriptionList.push(i18n.t('intro.updateSlide'+ i + '.text')) + this.titleList.push(i18n.t('intro.updateSlide' + i + '.title')) + this.descriptionList.push(i18n.t('intro.updateSlide' + i + '.text')) } } diff --git a/src/managers/AprilFoolsManager.js b/src/managers/AprilFoolsManager.js index 30ac90c..ed41fdd 100644 --- a/src/managers/AprilFoolsManager.js +++ b/src/managers/AprilFoolsManager.js @@ -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) { - if (dryers !== undefined) { + /** + * Changes proxiwash dryers order + * + * @param dryers + */ + static getNewProxiwashDryerOrderedList(dryers: Array | null) { + if (dryers != null) { let second = dryers[1]; dryers.splice(1, 1); dryers.push(second); } } - static getNewProxiwashWasherOrderedList(washers: Array) { - if (washers !== undefined) { + /** + * Changes proxiwash washers order + * + * @param washers + */ + static getNewProxiwashWasherOrderedList(washers: Array | 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, diff --git a/src/managers/ConnectionManager.js b/src/managers/ConnectionManager.js index 098a435..2ad0c33 100644 --- a/src/managers/ConnectionManager.js +++ b/src/managers/ConnectionManager.js @@ -23,15 +23,13 @@ export default class ConnectionManager { #email: string; #token: string | null; - listeners: Array; - 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} + */ 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} + */ 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} + */ 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} + */ async connect(email: string, password: string) { return new Promise((resolve, reject) => { const data = { @@ -117,19 +138,28 @@ export default class ConnectionManager { }; apiRequest(AUTH_PATH, 'POST', data) .then((response) => { - this.saveLogin(email, response.token) - .then(() => { - resolve(true); - }) - .catch(() => { - reject(ERROR_TYPE.TOKEN_SAVE); - }); + if (this.isConnectionResponseValid(response)) { + this.saveLogin(email, response.token) + .then(() => { + resolve(true); + }) + .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} + */ async authenticatedRequest(path: string, params: Object) { return new Promise((resolve, reject) => { if (this.getToken() !== null) { diff --git a/src/managers/DateManager.js b/src/managers/DateManager.js index a6cc82b..0269a46 100644 --- a/src/managers/DateManager.js +++ b/src/managers/DateManager.js @@ -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; - } - } diff --git a/src/managers/LocaleManager.js b/src/managers/LocaleManager.js index ca45c40..08c7980 100644 --- a/src/managers/LocaleManager.js +++ b/src/managers/LocaleManager.js @@ -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; - } } diff --git a/src/managers/ThemeManager.js b/src/managers/ThemeManager.js index 7edb06a..1c7e398 100644 --- a/src/managers/ThemeManager.js +++ b/src/managers/ThemeManager.js @@ -46,15 +46,15 @@ export type CustomTheme = { // Tetris tetrisBackground: string, - tetrisBorder:string, - tetrisScore:string, - tetrisI : string, - tetrisO : string, - tetrisT : string, - tetrisS : string, - tetrisZ : string, - tetrisJ : string, - tetrisL : string, + tetrisBorder: string, + tetrisScore: string, + tetrisI: string, + tetrisO: string, + tetrisT: string, + tetrisS: string, + tetrisZ: string, + tetrisJ: string, + tetrisL: string, }, } @@ -116,16 +116,16 @@ export default class ThemeManager { tutorinsaColor: '#f93943', // Tetris - tetrisBackground:'#e6e6e6', - tetrisBorder:'#2f2f2f', - tetrisScore:'#e2bd33', - tetrisI : '#3cd9e6', - tetrisO : '#ffdd00', - tetrisT : '#a716e5', - tetrisS : '#09c528', - tetrisZ : '#ff0009', - tetrisJ : '#2a67e3', - tetrisL : '#da742d', + tetrisBackground: '#e6e6e6', + tetrisBorder: '#2f2f2f', + tetrisScore: '#e2bd33', + tetrisI: '#3cd9e6', + tetrisO: '#ffdd00', + tetrisT: '#a716e5', + tetrisS: '#09c528', + tetrisZ: '#ff0009', + tetrisJ: '#2a67e3', + tetrisL: '#da742d', }, }; } @@ -176,16 +176,16 @@ export default class ThemeManager { tutorinsaColor: '#f93943', // Tetris - tetrisBackground:'#2c2c2c', - tetrisBorder:'#1b1b1b', - tetrisScore:'#e2d707', - tetrisI : '#30b3be', - tetrisO : '#c1a700', - tetrisT : '#9114c7', - tetrisS : '#08a121', - tetrisZ : '#b50008', - tetrisJ : '#0f37b9', - tetrisL : '#b96226', + tetrisBackground: '#2c2c2c', + tetrisBorder: '#1b1b1b', + tetrisScore: '#e2d707', + tetrisI: '#30b3be', + tetrisO: '#c1a700', + tetrisT: '#9114c7', + tetrisS: '#08a121', + tetrisZ: '#b50008', + tetrisJ: '#0f37b9', + tetrisL: '#b96226', }, }; }