From 0bdcf5a4bae2958a582377bb2c760c06309fa73f Mon Sep 17 00:00:00 2001 From: keplyx Date: Sat, 29 Jun 2019 15:43:57 +0200 Subject: [PATCH] Added documentation --- components/CustomHeader.js | 11 +++- components/CustomMaterialIcon.js | 9 +++ components/SideMenu.js | 19 +++++- navigation/AppNavigator.js | 3 + navigation/MainDrawerNavigator.js | 4 +- screens/About/AboutDependenciesScreen.js | 3 + screens/About/AboutScreen.js | 34 +++++++++-- screens/HomeScreen.js | 3 + screens/PlanningScreen.js | 3 + screens/Proximo/ProximoListScreen.js | 38 ++++++++++-- screens/Proximo/ProximoMainScreen.js | 34 ++++++++++- screens/ProxiwashScreen.js | 75 +++++++++++++++++++++++- screens/SettingsScreen.js | 51 ++++++++++++++-- 13 files changed, 260 insertions(+), 27 deletions(-) diff --git a/components/CustomHeader.js b/components/CustomHeader.js index d701046..22e941e 100644 --- a/components/CustomHeader.js +++ b/components/CustomHeader.js @@ -13,14 +13,19 @@ type Props = { navigation: Object, }; - +/** + * Custom component defining a header using native base + * + * @prop backButton {boolean} Whether to show a back button or a burger menu. Use burger if unspecified + * @prop rightMenu {React.Node} Element to place at the right of the header. Use nothing if unspecified + * @prop title {string} This header title + * @prop navigation {Object} The navigation object from react navigation + */ export default class CustomHeader extends React.Component { static defaultProps = { backButton: false, rightMenu: , - fontSize: 26, - width: 30, }; render() { diff --git a/components/CustomMaterialIcon.js b/components/CustomMaterialIcon.js index 656c31f..a3d81f8 100644 --- a/components/CustomMaterialIcon.js +++ b/components/CustomMaterialIcon.js @@ -12,6 +12,15 @@ type Props = { width: number, } +/** + * Custom component defining a material icon using native base + * + * @prop active {boolean} Whether to set the icon color to active + * @prop icon {string} The icon string to use from MaterialCommunityIcons + * @prop color {string} The icon color. Use default theme color if unspecified + * @prop fontSize {number} The icon size. Use 26 if unspecified + * @prop width {number} The icon width. Use 30 if unspecified + */ export default class CustomMaterialIcon extends React.Component { static defaultProps = { diff --git a/components/SideMenu.js b/components/SideMenu.js index af745e4..f321ff8 100644 --- a/components/SideMenu.js +++ b/components/SideMenu.js @@ -20,15 +20,24 @@ type State = { active: string, }; +/** + * Class used to define a navigation drawer + */ export default class SideBar extends React.Component { dataSet: Array; + state = { + active: 'Home', + }; + + /** + * Generate the datasets + * + * @param props + */ constructor(props: Props) { super(props); - this.state = { - active: 'Home', - }; this.dataSet = [ { name: i18n.t('screens.home'), @@ -82,6 +91,10 @@ export default class SideBar extends React.Component { ]; } + /** + * Navigate to the selected route, close the drawer, and mark the correct item as selected + * @param route {string} The route name to navigate to + */ navigateToScreen(route: string) { this.props.navigation.navigate(route); this.props.navigation.closeDrawer(); diff --git a/navigation/AppNavigator.js b/navigation/AppNavigator.js index 34a800e..b1a2710 100644 --- a/navigation/AppNavigator.js +++ b/navigation/AppNavigator.js @@ -6,6 +6,9 @@ import MainDrawerNavigator from './MainDrawerNavigator'; import ProximoListScreen from '../screens/Proximo/ProximoListScreen'; import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen'; +/** + * Create a stack navigator using the drawer to handle navigation between screens + */ export default createAppContainer( createStackNavigator({ Main: MainDrawerNavigator, diff --git a/navigation/MainDrawerNavigator.js b/navigation/MainDrawerNavigator.js index 5781202..dd3c9d5 100644 --- a/navigation/MainDrawerNavigator.js +++ b/navigation/MainDrawerNavigator.js @@ -11,7 +11,9 @@ import SettingsScreen from '../screens/SettingsScreen'; import AboutScreen from '../screens/About/AboutScreen'; import SideMenu from "../components/SideMenu"; - +/** + * Creates the drawer navigation stack + */ export default createDrawerNavigator({ Home: {screen: HomeScreen}, Planning: {screen: PlanningScreen,}, diff --git a/screens/About/AboutDependenciesScreen.js b/screens/About/AboutDependenciesScreen.js index fb173bd..c1b6eb5 100644 --- a/screens/About/AboutDependenciesScreen.js +++ b/screens/About/AboutDependenciesScreen.js @@ -20,6 +20,9 @@ type Props = { navigation: Object } +/** + * Class defining a screen showing the list of libraries used by the app, taken from package.json + */ export default class AboutDependenciesScreen extends React.Component { render() { diff --git a/screens/About/AboutScreen.js b/screens/About/AboutScreen.js index 38255ce..4792fc4 100644 --- a/screens/About/AboutScreen.js +++ b/screens/About/AboutScreen.js @@ -26,13 +26,22 @@ type Props = { navigation: Object, }; - +/** + * Opens a link in the device's browser + * @param link The link to open + */ function openWebLink(link) { Linking.openURL(link).catch((err) => console.error('Error opening link', err)); } +/** + * Class defining an about screen. This screen shows the user information about the app and it's author. + */ export default class AboutScreen extends React.Component { + /** + * Data to be displayed in the app card + */ appData: Array = [ { onPressCallback: () => openWebLink(Platform.OS === "ios" ? links.appstore : links.playstore), @@ -66,6 +75,9 @@ export default class AboutScreen extends React.Component { }, ]; + /** + * Data to be displayed in the author card + */ authorData: Array = [ { onPressCallback: () => Alert.alert('Coucou', 'Whaou'), @@ -93,6 +105,9 @@ export default class AboutScreen extends React.Component { }, ]; + /** + * Data to be displayed in the technologies card + */ technoData: Array = [ { onPressCallback: () => openWebLink(links.react), @@ -108,7 +123,16 @@ export default class AboutScreen extends React.Component { }, ]; - getCardItem(onPressCallback: Function, icon: string, text: string, showChevron: boolean) { + /** + * Get a clickable card item to be rendered inside a card. + * + * @param onPressCallback The callback to use when the item is clicked + * @param icon The icon name to use from MaterialCommunityIcons + * @param text The text to show + * @param showChevron Whether to show a chevron indicating this button will change screen + * @returns {React.Node} + */ + static getCardItem(onPressCallback: Function, icon: string, text: string, showChevron: boolean) { return ( @@ -150,7 +174,7 @@ export default class AboutScreen extends React.Component { data={this.appData} keyExtractor={(item) => item.icon} renderItem={({item}) => - this.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron) + AboutScreen.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron) } /> @@ -163,7 +187,7 @@ export default class AboutScreen extends React.Component { data={this.authorData} keyExtractor={(item) => item.icon} renderItem={({item}) => - this.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron) + AboutScreen.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron) } /> @@ -176,7 +200,7 @@ export default class AboutScreen extends React.Component { data={this.technoData} keyExtractor={(item) => item.icon} renderItem={({item}) => - this.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron) + AboutScreen.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron) } /> diff --git a/screens/HomeScreen.js b/screens/HomeScreen.js index 1cd12eb..5db80c8 100644 --- a/screens/HomeScreen.js +++ b/screens/HomeScreen.js @@ -10,6 +10,9 @@ type Props = { navigation: Object, } +/** + * Class defining the app's home screen + */ export default class HomeScreen extends React.Component { render() { const nav = this.props.navigation; diff --git a/screens/PlanningScreen.js b/screens/PlanningScreen.js index c6ce3b5..2c53a04 100644 --- a/screens/PlanningScreen.js +++ b/screens/PlanningScreen.js @@ -9,6 +9,9 @@ type Props = { navigation: Object, } +/** + * Class defining the app's planning screen + */ export default class PlanningScreen extends React.Component { render() { const nav = this.props.navigation; diff --git a/screens/Proximo/ProximoListScreen.js b/screens/Proximo/ProximoListScreen.js index ee69d55..af9fefd 100644 --- a/screens/Proximo/ProximoListScreen.js +++ b/screens/Proximo/ProximoListScreen.js @@ -16,7 +16,6 @@ const sortMode = { name: '1', }; - function sortPrice(a, b) { return a.price - b.price; } @@ -53,7 +52,10 @@ type State = { sortNameIcon: React.Node, }; -export default class ProximoMainScreen extends React.Component { +/** + * Class defining proximo's article list of a certain category. + */ +export default class ProximoListScreen extends React.Component { state = { navData: this.props.navigation.getParam('data', []).sort(sortPrice), @@ -65,11 +67,22 @@ export default class ProximoMainScreen extends React.Component { _menu: Menu; + /** + * Saves the reference to the sort menu for later use + * + * @param ref The menu reference + */ setMenuRef = (ref: Menu) => { this._menu = ref; }; - toggleSortMode(mode: string) { + /** + * Sets the sort mode based on the one selected. + * If the selected mode is the current one, reverse it. + * + * @param mode The string representing the mode + */ + sortModeSelected(mode: string) { let isReverse = this.state.isSortReversed; if (mode === this.state.currentSortMode) // reverse mode isReverse = !isReverse; // this.state not updating on this function cycle @@ -78,6 +91,12 @@ export default class ProximoMainScreen extends React.Component { this.setSortMode(mode, isReverse); } + /** + * Set the current sort mode. + * + * @param mode The string representing the mode + * @param isReverse Whether to use a reverse sort + */ setSortMode(mode: string, isReverse: boolean) { this.setState({ currentSortMode: mode, @@ -107,10 +126,19 @@ export default class ProximoMainScreen extends React.Component { this._menu.hide(); } + /** + * Set the sort mode from state when components are ready + */ componentDidMount() { this.setSortMode(this.state.currentSortMode, this.state.isSortReversed); } + /** + * Set the sort menu icon based on the given mode. + * + * @param mode The string representing the mode + * @param isReverse Whether to use a reversed icon + */ setupSortIcons(mode: string, isReverse: boolean) { const downSortIcon = { } > this.toggleSortMode(sortMode.name)}> + onPress={() => this.sortModeSelected(sortMode.name)}> {this.state.sortNameIcon} {i18n.t('proximoScreen.sortName')} this.toggleSortMode(sortMode.price)}> + onPress={() => this.sortModeSelected(sortMode.price)}> {this.state.sortPriceIcon} {i18n.t('proximoScreen.sortPrice')} diff --git a/screens/Proximo/ProximoMainScreen.js b/screens/Proximo/ProximoMainScreen.js index d2a9c2e..9844f24 100644 --- a/screens/Proximo/ProximoMainScreen.js +++ b/screens/Proximo/ProximoMainScreen.js @@ -27,6 +27,10 @@ type State = { data: Object, }; +/** + * Class defining the main proximo screen. This screen shows the different categories of articles + * offered by proximo. + */ export default class ProximoMainScreen extends React.Component { state = { @@ -35,7 +39,15 @@ export default class ProximoMainScreen extends React.Component { data: {}, }; - static generateDataset(types: Array, data: Object) { + /** + * Generate the dataset using types and data. + * This will group items under the same type. + * + * @param types An array containing the types available (categories) + * @param data The array of articles represented by objects + * @returns {Array} The formatted dataset + */ + static generateDataset(types: Array, data: Array) { let finalData = []; for (let i = 0; i < types.length; i++) { finalData.push({ @@ -51,6 +63,11 @@ export default class ProximoMainScreen extends React.Component { return finalData; } + /** + * Async function reading data from the proximo website and setting the state to rerender the list + * + * @returns {Promise} + */ async readData() { try { let response = await fetch(DATA_URL); @@ -68,10 +85,18 @@ export default class ProximoMainScreen extends React.Component { } } + /** + * Refresh the list on first screen load + */ componentDidMount() { this._onRefresh(); } + /** + * Display a loading indicator and fetch data from the internet + * + * @private + */ _onRefresh = () => { this.setState({refreshing: true}); this.readData().then(() => { @@ -88,7 +113,12 @@ export default class ProximoMainScreen extends React.Component { }); }; - + /** + * Renders the proximo categories list. + * If we are loading for the first time, change the data for the SectionList to display a loading message. + * + * @returns {react.Node} + */ render() { const nav = this.props.navigation; const data = [ diff --git a/screens/ProxiwashScreen.js b/screens/ProxiwashScreen.js index 0df7953..c9e1f40 100644 --- a/screens/ProxiwashScreen.js +++ b/screens/ProxiwashScreen.js @@ -38,6 +38,10 @@ type State = { machinesWatched: Array }; +/** + * Class defining the app's proxiwash screen. This screen shows information about washing machines and + * dryers, taken from a scrapper reading proxiwash website + */ export default class ProxiwashScreen extends React.Component { state = { @@ -47,6 +51,11 @@ export default class ProxiwashScreen extends React.Component { machinesWatched: [], }; + /** + * Creates machine state parameters using current theme and translations + * + * @param props + */ constructor(props: Props) { super(props); let colors = ThemeManager.getInstance().getCurrentThemeVariables(); @@ -63,6 +72,11 @@ export default class ProxiwashScreen extends React.Component { stateStrings[MACHINE_STATES.ERREUR] = i18n.t('proxiwashScreen.states.error'); } + /** + * Read the data from the proxiwash scrapper and set it to current state to reload the screen + * + * @returns {Promise} + */ async readData() { try { let response = await fetch(DATA_URL); @@ -75,6 +89,11 @@ export default class ProxiwashScreen extends React.Component { } } + /** + * Get which machines have notifications enabled before loading the screen + * + * @returns {Promise} + */ async componentWillMount() { let dataString = await AsyncStorage.getItem(WATCHED_MACHINES_PREFKEY); if (dataString === null) @@ -84,11 +103,18 @@ export default class ProxiwashScreen extends React.Component { }); } - + /** + * Refresh the data on first screen load + */ componentDidMount() { this._onRefresh(); } + /** + * Show the refresh inddicator and wait for data to be fetched from the scrapper + * + * @private + */ _onRefresh = () => { this.setState({refreshing: true}); this.readData().then(() => { @@ -105,6 +131,14 @@ export default class ProxiwashScreen extends React.Component { }); }; + /** + * Get the time remaining based on start/end time and done percent + * + * @param startString The string representing the start time. Format: hh:mm + * @param endString The string representing the end time. Format: hh:mm + * @param percentDone The percentage done + * @returns {number} How many minutes are remaining for this machine + */ static getRemainingTime(startString: string, endString: string, percentDone: string): number { let startArray = startString.split(':'); let endArray = endString.split(':'); @@ -117,6 +151,15 @@ export default class ProxiwashScreen extends React.Component { return parseInt(time); } + /** + * Setup notifications for the machine with the given ID. + * One notification will be sent at the end of the program. + * Another will be send a few minutes before the end, based on the value of reminderNotifTime + * + * @param machineId The machine's ID + * @param remainingTime The time remaining for this machine + * @returns {Promise} + */ async setupNotifications(machineId: string, remainingTime: number) { if (!this.isMachineWatched(machineId)) { let endNotifID = await NotificationsManager.scheduleNotification( @@ -148,6 +191,12 @@ export default class ProxiwashScreen extends React.Component { this.disableNotification(machineId); } + /** + * Stop scheduled notifications for the machine of the given ID. + * This will also remove the notification if it was already shown. + * + * @param machineId The machine's ID + */ disableNotification(machineId: string) { let data: Object = this.state.machinesWatched; if (data.length > 0) { @@ -164,12 +213,26 @@ export default class ProxiwashScreen extends React.Component { } } - isMachineWatched(number: string) { + /** + * Checks whether the machine of the given ID has scheduled notifications + * + * @param machineID The machine's ID + * @returns {boolean} + */ + isMachineWatched(machineID: string) { return this.state.machinesWatched.find(function (elem) { - return elem.machineNumber === number + return elem.machineNumber === machineID }) !== undefined; } + /** + * Get list item to be rendered + * + * @param item The object containing the item's data + * @param section The object describing the current SectionList section + * @param data The full data used by the SectionList + * @returns {React.Node} + */ renderItem(item: Object, section: Object, data: Object) { return ( { ); } + /** + * Renders the machines list. + * If we are loading for the first time, change the data for the SectionList to display a loading message. + * + * @returns {react.Node} + */ render() { const nav = this.props.navigation; const data = [ diff --git a/screens/SettingsScreen.js b/screens/SettingsScreen.js index 3d1e5c7..1c56c8f 100644 --- a/screens/SettingsScreen.js +++ b/screens/SettingsScreen.js @@ -33,12 +33,20 @@ type State = { proxiwashNotifPickerSelected: string, }; +/** + * Class defining the Settings screen. This screen shows controls to modify app preferences. + */ export default class SettingsScreen extends React.Component { state = { nightMode: ThemeManager.getInstance().getNightMode(), proxiwashNotifPickerSelected: "5" }; + /** + * Gets data from preferences before rendering components + * + * @returns {Promise} + */ async componentWillMount() { let val = await AsyncStorage.getItem(proxiwashNotifKey); if (val === null) @@ -48,7 +56,11 @@ export default class SettingsScreen extends React.Component { }); } - + /** + * Save the value for the proxiwash reminder notification time + * + * @param value The value to store + */ onProxiwashNotifPickerValueChange(value: string) { AsyncStorage.setItem(proxiwashNotifKey, value); this.setState({ @@ -56,6 +68,11 @@ export default class SettingsScreen extends React.Component { }); } + /** + * Returns a picker allowing the user to select the proxiwash reminder notification time + * + * @returns {React.Node} + */ getProxiwashNotifPicker() { return ( { ); } + /** + * Toggle night mode and save it to preferences + */ toggleNightMode() { ThemeManager.getInstance().setNightMode(!this.state.nightMode); this.setState({nightMode: !this.state.nightMode}); @@ -84,6 +104,9 @@ export default class SettingsScreen extends React.Component { this.resetStack(); } + /** + * Reset react navigation stack to allow for a theme reset + */ resetStack() { const resetAction = StackActions.reset({ index: 0, @@ -94,7 +117,16 @@ export default class SettingsScreen extends React.Component { this.props.navigation.navigate('Settings'); } - getToggleItem(onPressCallback: Function, icon: string, text: string, subtitle: string) { + /** + * Get a list item using a checkbox control + * + * @param onPressCallback The callback when the checkbox state changes + * @param icon The icon name to display on the list item + * @param title The text to display as this list item title + * @param subtitle The text to display as this list item subtitle + * @returns {React.Node} + */ + getToggleItem(onPressCallback: Function, icon: string, title: string, subtitle: string) { return ( { - {text} + {title} {subtitle} @@ -120,7 +152,16 @@ export default class SettingsScreen extends React.Component { ); } - static getGeneralItem(control: React.Node, icon: string, text: string, subtitle: string) { + /** + * Get a list item using the specified control + * + * @param control The custom control to use + * @param icon The icon name to display on the list item + * @param title The text to display as this list item title + * @param subtitle The text to display as this list item subtitle + * @returns {React.Node} + */ + static getGeneralItem(control: React.Node, icon: string, title: string, subtitle: string) { return ( { - {text} + {title} {subtitle}