diff --git a/components/CustomAgenda.js b/components/CustomAgenda.js index ee2b61c..8c0f1cd 100644 --- a/components/CustomAgenda.js +++ b/components/CustomAgenda.js @@ -2,8 +2,14 @@ import * as React from 'react'; import {withTheme} from 'react-native-paper'; import {Agenda} from "react-native-calendars"; +/** + * Abstraction layer for Agenda component, using custom configuration + * + * @param props Props to pass to the element. Must specify an onRef prop to get an Agenda ref. + * @return {*} + */ function CustomAgenda(props) { - const { colors } = props.theme; + const {colors} = props.theme; return ( <Agenda {...props} diff --git a/components/CustomIntroSlider.js b/components/CustomIntroSlider.js index 8c19ba3..b62c5ac 100644 --- a/components/CustomIntroSlider.js +++ b/components/CustomIntroSlider.js @@ -9,47 +9,24 @@ import i18n from 'i18n-js'; import AppIntroSlider from "react-native-app-intro-slider"; import Update from "../constants/Update"; -// Content to be used int the intro slides - -const styles = StyleSheet.create({ - mainContent: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - paddingBottom: 100 - }, - image: { - width: 300, - height: 300, - marginBottom: -50, - }, - text: { - color: 'rgba(255, 255, 255, 0.8)', - backgroundColor: 'transparent', - textAlign: 'center', - paddingHorizontal: 16, - }, - title: { - fontSize: 22, - color: 'white', - backgroundColor: 'transparent', - textAlign: 'center', - marginBottom: 16, - }, -}); - type Props = { onDone: Function, isUpdate: boolean, isAprilFools: boolean, }; +/** + * Class used to create intro slides + */ export default class CustomIntroSlider extends React.Component<Props> { introSlides: Array<Object>; updateSlides: Array<Object>; aprilFoolsSlides: Array<Object>; + /** + * Generates intro slides + */ constructor() { super(); this.introSlides = [ @@ -126,8 +103,9 @@ export default class CustomIntroSlider extends React.Component<Props> { /** * Render item to be used for the intro introSlides - * @param item - * @param dimensions + * + * @param item The item to be displayed + * @param dimensions Dimensions of the item */ static getIntroRenderItem({item, dimensions}: Object) { @@ -178,3 +156,29 @@ export default class CustomIntroSlider extends React.Component<Props> { } +const styles = StyleSheet.create({ + mainContent: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + paddingBottom: 100 + }, + image: { + width: 300, + height: 300, + marginBottom: -50, + }, + text: { + color: 'rgba(255, 255, 255, 0.8)', + backgroundColor: 'transparent', + textAlign: 'center', + paddingHorizontal: 16, + }, + title: { + fontSize: 22, + color: 'white', + backgroundColor: 'transparent', + textAlign: 'center', + marginBottom: 16, + }, +}); diff --git a/components/CustomModal.js b/components/CustomModal.js index 99b38d6..0a9696b 100644 --- a/components/CustomModal.js +++ b/components/CustomModal.js @@ -4,8 +4,14 @@ import * as React from 'react'; import {withTheme} from 'react-native-paper'; import {Modalize} from "react-native-modalize"; +/** + * Abstraction layer for Modalize component, using custom configuration + * + * @param props Props to pass to the element. Must specify an onRef prop to get an Modalize ref. + * @return {*} + */ function CustomModal(props) { - const { colors } = props.theme; + const {colors} = props.theme; return ( <Modalize ref={props.onRef} diff --git a/components/EmptyWebSectionListItem.js b/components/EmptyWebSectionListItem.js index ecba4e0..6e5c988 100644 --- a/components/EmptyWebSectionListItem.js +++ b/components/EmptyWebSectionListItem.js @@ -1,19 +1,19 @@ import * as React from 'react'; import {ActivityIndicator, Subheading, withTheme} from 'react-native-paper'; -import {View} from "react-native"; +import {StyleSheet, View} from "react-native"; import {MaterialCommunityIcons} from "@expo/vector-icons"; -function EmptyWebSectionListItem(props) { - const { colors } = props.theme; +/** + * Component used to display a message when a list is empty + * + * @param props Props to pass to the component + * @return {*} + */ +function EmptyWebSectionListItem(props: { text: string, icon: string, refreshing: boolean, theme: {} }) { + const {colors} = props.theme; return ( <View> - <View style={{ - justifyContent: 'center', - alignItems: 'center', - width: '100%', - height: 100, - marginBottom: 20 - }}> + <View style={styles.iconContainer}> {props.refreshing ? <ActivityIndicator animating={true} @@ -27,9 +27,7 @@ function EmptyWebSectionListItem(props) { </View> <Subheading style={{ - textAlign: 'center', - marginRight: 20, - marginLeft: 20, + ...styles.subheading, color: colors.textDisabled }}> {props.text} @@ -38,4 +36,19 @@ function EmptyWebSectionListItem(props) { ); } +const styles = StyleSheet.create({ + iconContainer: { + justifyContent: 'center', + alignItems: 'center', + width: '100%', + height: 100, + marginBottom: 20 + }, + subheading: { + textAlign: 'center', + marginRight: 20, + marginLeft: 20, + } +}); + export default withTheme(EmptyWebSectionListItem); diff --git a/components/EventDashboardItem.js b/components/EventDashboardItem.js index cfcd2ee..117f5c4 100644 --- a/components/EventDashboardItem.js +++ b/components/EventDashboardItem.js @@ -2,7 +2,14 @@ import * as React from 'react'; import {Avatar, Card, withTheme} from 'react-native-paper'; +import {StyleSheet} from "react-native"; +/** + * Component used to display a dashboard item containing a preview event + * + * @param props Props to pass to the component + * @return {*} + */ function EventDashBoardItem(props) { const {colors} = props.theme; const iconColor = props.isAvailable ? @@ -13,13 +20,7 @@ function EventDashBoardItem(props) { colors.textDisabled; return ( <Card - style={{ - width: 'auto', - marginLeft: 10, - marginRight: 10, - marginTop: 10, - overflow: 'hidden', - }} + style={styles.card} onPress={props.clickAction}> <Card.Title @@ -32,7 +33,7 @@ function EventDashBoardItem(props) { icon={props.icon} color={iconColor} size={60} - style={{backgroundColor: 'transparent'}}/>} + style={styles.avatar}/>} /> <Card.Content> {props.children} @@ -41,4 +42,17 @@ function EventDashBoardItem(props) { ); } +const styles = StyleSheet.create({ + card: { + width: 'auto', + marginLeft: 10, + marginRight: 10, + marginTop: 10, + overflow: 'hidden', + }, + avatar: { + backgroundColor: 'transparent' + } +}); + export default withTheme(EventDashBoardItem); diff --git a/components/FeedItem.js b/components/FeedItem.js index 58294a9..e26f4bd 100644 --- a/components/FeedItem.js +++ b/components/FeedItem.js @@ -6,6 +6,11 @@ import i18n from "i18n-js"; const ICON_AMICALE = require('../assets/amicale.png'); +/** + * Gets the amicale INSAT logo + * + * @return {*} + */ function getAvatar() { return ( <Avatar.Image size={48} source={ICON_AMICALE} @@ -13,6 +18,12 @@ function getAvatar() { ); } +/** + * Component used to display a feed item + * + * @param props Props to pass to the component + * @return {*} + */ function FeedItem(props) { const {colors} = props.theme; return ( @@ -39,7 +50,9 @@ function FeedItem(props) { <Button color={'#57aeff'} onPress={props.onOutLinkPress} - icon={'facebook'}>{i18n.t('homeScreen.dashboard.seeMore')}</Button> + icon={'facebook'}> + {i18n.t('homeScreen.dashboard.seeMore')} + </Button> </Card.Actions> </Card> ); diff --git a/components/HeaderButton.js b/components/HeaderButton.js index 663dd44..5e09cee 100644 --- a/components/HeaderButton.js +++ b/components/HeaderButton.js @@ -1,8 +1,14 @@ import * as React from 'react'; import {IconButton, withTheme} from 'react-native-paper'; +/** + * Component used to display a header button + * + * @param props Props to pass to the component + * @return {*} + */ function HeaderButton(props) { - const { colors } = props.theme; + const {colors} = props.theme; return ( <IconButton icon={props.icon} diff --git a/components/PreviewEventDashboardItem.js b/components/PreviewEventDashboardItem.js index 237d72d..c4aafbd 100644 --- a/components/PreviewEventDashboardItem.js +++ b/components/PreviewEventDashboardItem.js @@ -1,25 +1,33 @@ // @flow import * as React from 'react'; -import {View} from "react-native"; +import {StyleSheet, View} from "react-native"; import HTML from "react-native-render-html"; import i18n from "i18n-js"; import {Avatar, Button, Card, withTheme} from 'react-native-paper'; import PlanningEventManager from "../utils/PlanningEventManager"; - +/** + * Component used to display an event preview if an event is available + * + * @param props Props to pass to the component + * @return {*} + */ function PreviewEventDashboardItem(props) { const {colors} = props.theme; - const isEmpty = props.event === undefined ? true : PlanningEventManager.isDescriptionEmpty(props.event['description']); + const isEmpty = props.event === undefined + ? true + : PlanningEventManager.isDescriptionEmpty(props.event['description']); + if (props.event !== undefined && props.event !== null) { const hasImage = props.event['logo'] !== '' && props.event['logo'] !== null; const getImage = () => <Avatar.Image source={{uri: props.event['logo']}} size={50} - style={{backgroundColor: 'transparent'}}/>; + style={styles.avatar}/>; return ( <Card - style={{marginBottom: 10}} + style={styles.card} onPress={props.clickAction} elevation={3} > @@ -34,10 +42,7 @@ function PreviewEventDashboardItem(props) { subtitle={PlanningEventManager.getFormattedEventTime(props.event['date_begin'], props.event['date_end'])} />} {!isEmpty ? - <Card.Content style={{ - maxHeight: 150, - overflow: 'hidden', - }}> + <Card.Content style={styles.content}> <HTML html={"<div>" + props.event['description'] + "</div>"} tagsStyles={{ p: {color: colors.text,}, @@ -46,11 +51,7 @@ function PreviewEventDashboardItem(props) { </Card.Content> : null} - <Card.Actions style={{ - marginLeft: 'auto', - marginTop: 'auto', - flexDirection: 'row' - }}> + <Card.Actions style={styles.actions}> <Button icon={'chevron-right'} > @@ -63,4 +64,22 @@ function PreviewEventDashboardItem(props) { return <View/> } +const styles = StyleSheet.create({ + card: { + marginBottom: 10 + }, + content: { + maxHeight: 150, + overflow: 'hidden', + }, + actions: { + marginLeft: 'auto', + marginTop: 'auto', + flexDirection: 'row' + }, + avatar: { + backgroundColor: 'transparent' + } +}); + export default withTheme(PreviewEventDashboardItem); diff --git a/components/ProxiwashListItem.js b/components/ProxiwashListItem.js index e4d091c..9d577fe 100644 --- a/components/ProxiwashListItem.js +++ b/components/ProxiwashListItem.js @@ -1,8 +1,14 @@ import * as React from 'react'; import {Avatar, Card, Text, withTheme} from 'react-native-paper'; -import {View} from "react-native"; +import {StyleSheet, View} from "react-native"; import ProxiwashConstants from "../constants/ProxiwashConstants"; +/** + * Component used to display a proxiwash item, showing machine progression and state + * + * @param props Props to pass to the component + * @return {*} + */ function ProxiwashListItem(props) { const {colors} = props.theme; let stateColors = {}; @@ -17,13 +23,13 @@ function ProxiwashListItem(props) { icon={'bell-ring'} size={45} color={colors.primary} - style={{backgroundColor: 'transparent'}} + style={styles.icon} /> : <Avatar.Icon icon={props.isDryer ? 'tumble-dryer' : 'washing-machine'} color={colors.text} size={40} - style={{backgroundColor: 'transparent'}} + style={styles.icon} /> ); return ( @@ -35,37 +41,26 @@ function ProxiwashListItem(props) { > {ProxiwashConstants.machineStates[props.state] === ProxiwashConstants.machineStates["EN COURS"] ? <Card style={{ - height: '100%', - position: 'absolute', - left: 0, - width: '100%', + ...styles.backgroundCard, backgroundColor: colors.proxiwashRunningBgColor, - elevation: 0 + }}/> : null } <Card style={{ - height: '100%', - position: 'absolute', - left: 0, + ...styles.progressionCard, width: props.progress, backgroundColor: stateColors[ProxiwashConstants.machineStates[props.state]], - elevation: 0 }}/> <Card.Title title={props.title} titleStyle={{fontSize: 17}} subtitle={props.description} - style={{ - backgroundColor: 'transparent', - height: 64 - }} + style={styles.title} left={() => icon} right={() => ( <View style={{flexDirection: 'row'}}> - <View style={{ - justifyContent: 'center', - }}> + <View style={{justifyContent: 'center'}}> <Text style={ ProxiwashConstants.machineStates[props.state] === ProxiwashConstants.machineStates.TERMINE ? {fontWeight: 'bold',} : {}} @@ -73,12 +68,11 @@ function ProxiwashListItem(props) { {props.statusText} </Text> </View> - <Avatar.Icon icon={props.statusIcon} color={colors.text} size={30} - style={{backgroundColor: 'transparent'}} + style={styles.icon} /> </View>)} /> @@ -86,4 +80,27 @@ function ProxiwashListItem(props) { ); } +const styles = StyleSheet.create({ + icon: { + backgroundColor: 'transparent' + }, + backgroundCard: { + height: '100%', + position: 'absolute', + left: 0, + width: '100%', + elevation: 0, + }, + progressionCard: { + height: '100%', + position: 'absolute', + left: 0, + elevation: 0, + }, + title: { + backgroundColor: 'transparent', + height: 64 + } +}); + export default withTheme(ProxiwashListItem); diff --git a/components/PureFlatList.js b/components/PureFlatList.js index 8389d5e..4cd030e 100644 --- a/components/PureFlatList.js +++ b/components/PureFlatList.js @@ -9,10 +9,12 @@ type Props = { } /** + * FlatList implementing PureComponent for increased performance. + * * This is a pure component, meaning it will only update if a shallow comparison of state and props is different. * To force the component to update, change the value of updateData. */ -export default class PureFlatList extends React.PureComponent<Props>{ +export default class PureFlatList extends React.PureComponent<Props> { static defaultProps = { updateData: null, diff --git a/components/Sidebar.js b/components/Sidebar.js index 3fca4cd..5149eec 100644 --- a/components/Sidebar.js +++ b/components/Sidebar.js @@ -20,7 +20,7 @@ type State = { }; /** - * Class used to define a navigation drawer + * Component used to render the drawer menu content */ export default class SideBar extends React.PureComponent<Props, State> { @@ -33,7 +33,7 @@ export default class SideBar extends React.PureComponent<Props, State> { getRenderItem: Function; /** - * Generate the datasets + * Generate the dataset * * @param props */ @@ -123,6 +123,12 @@ export default class SideBar extends React.PureComponent<Props, State> { this.getRenderItem = this.getRenderItem.bind(this); } + /** + * Callback when a drawer item is pressed. + * It will either navigate to the associated screen, or open the browser to the associated link + * + * @param item The item pressed + */ onListItemPress(item: Object) { if (item.link === undefined) this.props.navigation.navigate(item.route); @@ -130,12 +136,22 @@ export default class SideBar extends React.PureComponent<Props, State> { WebBrowser.openBrowserAsync(item.link); } - - listKeyExtractor(item: Object) { + /** + * Key extractor for list items + * + * @param item The item to extract the key from + * @return {string} The extracted key + */ + listKeyExtractor(item: Object): string { return item.route; } - + /** + * Gets the render item for the given list item + * + * @param item The item to render + * @return {*} + */ getRenderItem({item}: Object) { const onListItemPress = this.onListItemPress.bind(this, item); if (item.icon !== undefined) { diff --git a/components/SidebarDivider.js b/components/SidebarDivider.js index ec0927b..53c2419 100644 --- a/components/SidebarDivider.js +++ b/components/SidebarDivider.js @@ -1,9 +1,15 @@ import * as React from 'react'; -import { withTheme } from 'react-native-paper'; +import {withTheme} from 'react-native-paper'; import {DrawerItem} from "@react-navigation/drawer"; +/** + * Component used to render a drawer menu item divider + * + * @param props Props to pass to the component + * @return {*} + */ function SidebarDivider(props) { - const { colors } = props.theme; + const {colors} = props.theme; return ( <DrawerItem label={props.title} diff --git a/components/SidebarItem.js b/components/SidebarItem.js index 3781d29..232166f 100644 --- a/components/SidebarItem.js +++ b/components/SidebarItem.js @@ -3,6 +3,12 @@ import {withTheme} from 'react-native-paper'; import {DrawerItem} from "@react-navigation/drawer"; import {MaterialCommunityIcons} from "@expo/vector-icons"; +/** + * Component used to render a drawer menu item + * + * @param props Props to pass to the component + * @return {*} + */ function SidebarItem(props) { const {colors} = props.theme; return ( diff --git a/components/SquareDashboardItem.js b/components/SquareDashboardItem.js index da23cfb..c9e3355 100644 --- a/components/SquareDashboardItem.js +++ b/components/SquareDashboardItem.js @@ -2,6 +2,12 @@ import * as React from 'react'; import {Badge, IconButton, withTheme} from 'react-native-paper'; import {View} from "react-native"; +/** + * Component used to render a small dashboard item + * + * @param props Props to pass to the component + * @return {*} + */ function SquareDashboardItem(props) { const {colors} = props.theme; return ( @@ -9,9 +15,9 @@ function SquareDashboardItem(props) { <IconButton icon={props.icon} color={ - props.isAvailable ? - props.color : - colors.textDisabled + props.isAvailable + ? props.color + : colors.textDisabled } size={35} onPress={props.clickAction} @@ -23,9 +29,10 @@ function SquareDashboardItem(props) { position: 'absolute', top: 5, right: 5 - }}>{props.badgeNumber}</Badge> : null + }}> + {props.badgeNumber} + </Badge> : null } - </View> ); } diff --git a/components/WebSectionList.js b/components/WebSectionList.js index c3c96ff..c09dbca 100644 --- a/components/WebSectionList.js +++ b/components/WebSectionList.js @@ -27,8 +27,10 @@ type State = { }; -const MIN_REFRESH_TIME = 5 * 1000; +const MIN_REFRESH_TIME = 5 * 1000; /** + * Component used to render a SectionList with data fetched from the web + * * This is a pure component, meaning it will only update if a shallow comparison of state and props is different. * To force the component to update, change the value of updateData. */ @@ -73,7 +75,7 @@ export default class WebSectionList extends React.PureComponent<Props, State> { } /** - * Register react navigation events on first screen load. + * Registers react navigation events on first screen load. * Allows to detect when the screen is focused */ componentDidMount() { @@ -86,7 +88,7 @@ export default class WebSectionList extends React.PureComponent<Props, State> { } /** - * Refresh data when focusing the screen and setup a refresh interval if asked to + * Refreshes data when focusing the screen and setup a refresh interval if asked to */ onScreenFocus() { if (this.props.refreshOnFocus && this.lastRefresh !== undefined) @@ -96,13 +98,19 @@ export default class WebSectionList extends React.PureComponent<Props, State> { } /** - * Remove any interval on un-focus + * Removes any interval on un-focus */ onScreenBlur() { clearInterval(this.refreshInterval); } + /** + * Callback used when fetch is successful. + * It will update the displayed data and stop the refresh animation + * + * @param fetchedData The newly fetched data + */ onFetchSuccess(fetchedData: Object) { this.setState({ fetchedData: fetchedData, @@ -112,6 +120,10 @@ export default class WebSectionList extends React.PureComponent<Props, State> { this.lastRefresh = new Date(); } + /** + * Callback used when fetch encountered an error. + * It will reset the displayed data and show an error. + */ onFetchError() { this.setState({ fetchedData: {}, @@ -119,12 +131,10 @@ export default class WebSectionList extends React.PureComponent<Props, State> { firstLoading: false }); this.showSnackBar(); - // this.webDataManager.showUpdateToast(this.props.updateErrorText); } /** - * Refresh data and show a toast if any error occurred - * @private + * Refreshes data and shows an animations while doing it */ onRefresh() { let canRefresh; @@ -140,10 +150,22 @@ export default class WebSectionList extends React.PureComponent<Props, State> { } } + /** + * Gets an empty section header + * + * @param section The current section + * @return {*} + */ getEmptySectionHeader({section}: Object) { return <View/>; } + /** + * Gets an empty render item + * + * @param item The data to display + * @return {*} + */ getEmptyRenderItem({item}: Object) { return ( <EmptyWebSectionListItem @@ -154,6 +176,11 @@ export default class WebSectionList extends React.PureComponent<Props, State> { ); } + /** + * Creates an empty dataset + * + * @return {*} + */ createEmptyDataset() { return [ { @@ -174,14 +201,26 @@ export default class WebSectionList extends React.PureComponent<Props, State> { ]; } - datasetKeyExtractor(item: Object) { + /** + * Extracts a key from the given item + * + * @param item The item to extract the key from + * @return {string} The extracted key + */ + datasetKeyExtractor(item: Object): string { return item.text } + /** + * Shows the error popup + */ showSnackBar() { this.setState({snackbarVisible: true}) } + /** + * Hides the error popup + */ hideSnackBar() { this.setState({snackbarVisible: false}) } diff --git a/components/WebViewScreen.js b/components/WebViewScreen.js index bdeb5b5..206920e 100644 --- a/components/WebViewScreen.js +++ b/components/WebViewScreen.js @@ -34,8 +34,6 @@ class WebViewScreen extends React.PureComponent<Props> { onRefreshClicked: Function; onWebviewRef: Function; - onGoBackWebview: Function; - onGoForwardWebview: Function; getRenderLoading: Function; colors: Object; @@ -44,12 +42,13 @@ class WebViewScreen extends React.PureComponent<Props> { super(props); this.onRefreshClicked = this.onRefreshClicked.bind(this); this.onWebviewRef = this.onWebviewRef.bind(this); - this.onGoBackWebview = this.onGoBackWebview.bind(this); - this.onGoForwardWebview = this.onGoForwardWebview.bind(this); this.getRenderLoading = this.getRenderLoading.bind(this); this.colors = props.theme.colors; } + /** + * Creates refresh button after mounting + */ componentDidMount() { const rightButton = this.getRefreshButton.bind(this); this.props.navigation.setOptions({ @@ -57,42 +56,37 @@ class WebViewScreen extends React.PureComponent<Props> { }); } - getHeaderButton(clickAction: Function, icon: string) { - return ( - <HeaderButton icon={icon} onPress={clickAction}/> - ); - } - + /** + * Gets a header refresh button + * + * @return {*} + */ getRefreshButton() { - return ( - <View style={{ - flexDirection: 'row', - marginRight: 10 - }}> - {this.getHeaderButton(this.onRefreshClicked, 'refresh')} - </View> - ); + return <HeaderButton icon={'refresh'} onPress={this.onRefreshClicked}/> }; + /** + * Callback to use when refresh button is clicked. Reloads the webview. + */ onRefreshClicked() { if (this.webviewRef !== null) this.webviewRef.reload(); } - onGoBackWebview() { - if (this.webviewRef !== null) - this.webviewRef.goBack(); - } - - onGoForwardWebview() { - if (this.webviewRef !== null) - this.webviewRef.goForward(); - } - + /** + * Callback used when receiving the webview ref. Stores the ref for later use + * + * @param ref + */ onWebviewRef(ref: Object) { this.webviewRef = ref } + /** + * Gets the loading indicator + * + * @return {*} + */ getRenderLoading() { return ( <View style={{ @@ -115,7 +109,6 @@ class WebViewScreen extends React.PureComponent<Props> { } render() { - // console.log("rendering WebViewScreen"); return ( <WebView ref={this.onWebviewRef} diff --git a/constants/Update.js b/constants/Update.js index 072a50e..eb54734 100644 --- a/constants/Update.js +++ b/constants/Update.js @@ -1,12 +1,31 @@ import i18n from "i18n-js"; +/** + * Singleton used to manage update slides. + * Must be a singleton because it uses translations. + * + * Change values in this class to change the update slide. + * You will also need to update those translations: + * <ul> + * <li>intro.updateSlide.title</li> + * <li>intro.updateSlide.text</li> + * </ul> + */ export default class Update { + // Increment the number to show the update slide static number = 5; + // Change the icon to be displayed on the update slide static icon = 'surround-sound-2-0'; static instance: Update | null = null; + title: string; + description: string; + + /** + * Init translations + */ constructor() { this.title = i18n.t('intro.updateSlide.title'); this.description = i18n.t('intro.updateSlide.text'); @@ -14,6 +33,7 @@ export default class Update { /** * Get this class instance or create one if none is found + * * @returns {Update} */ static getInstance(): Update { diff --git a/utils/AsyncStorageManager.js b/utils/AsyncStorageManager.js index 6dcac31..33225f0 100644 --- a/utils/AsyncStorageManager.js +++ b/utils/AsyncStorageManager.js @@ -3,7 +3,7 @@ import {AsyncStorage} from "react-native"; /** - * Static class used to manage preferences. + * Singleton used to manage preferences. * Preferences are fetched at the start of the app and saved in an instance object. * This allows for a synchronous access to saved data. */ @@ -14,7 +14,7 @@ export default class AsyncStorageManager { /** * Get this class instance or create one if none is found - * @returns {ThemeManager} + * @returns {AsyncStorageManager} */ static getInstance(): AsyncStorageManager { return AsyncStorageManager.instance === null ? @@ -113,7 +113,7 @@ export default class AsyncStorageManager { /** * Save the value associated to the given key to preferences. - * This updates the preferences object and saves it to AsynStorage. + * This updates the preferences object and saves it to AsyncStorage. * * @param key * @param val diff --git a/utils/DateManager.js b/utils/DateManager.js index 3ca46ee..96e4e49 100644 --- a/utils/DateManager.js +++ b/utils/DateManager.js @@ -2,10 +2,13 @@ import i18n from 'i18n-js'; +/** + * Singleton used to manage date translations. + * Translations are hardcoded as toLocaleDateString does not work on current android JS engine + */ export default class DateManager { static instance: DateManager | null = null; - // Hard code strings as toLocaleDateString does not work on current android JS engine daysOfWeek = []; monthsOfYear = []; @@ -42,6 +45,12 @@ export default class DateManager { DateManager.instance; } + /** + * Gets a translated string representing the given date. + * + * @param dateString The date with the format YYYY-MM-DD + * @return {string} The translated string + */ getTranslatedDate(dateString: string) { let dateArray = dateString.split('-'); let date = new Date(); diff --git a/utils/NotificationsManager.js b/utils/NotificationsManager.js index 55aa76c..bca9594 100644 --- a/utils/NotificationsManager.js +++ b/utils/NotificationsManager.js @@ -49,6 +49,11 @@ export default class NotificationsManager { } } + /** + * Gets the machines watched from the server + * + * @param callback Function to execute with the fetched data + */ static getMachineNotificationWatchlist(callback: Function) { let token = AsyncStorageManager.getInstance().preferences.expoToken.current; if (token !== '') { @@ -72,10 +77,10 @@ export default class NotificationsManager { } /** - * Ask the server to enable/disable notifications for the specified machine + * Asks the server to enable/disable notifications for the specified machine * - * @param machineID - * @param isEnabled + * @param machineID The machine ID + * @param isEnabled True to enable notifications, false to disable */ static setupMachineNotification(machineID: string, isEnabled: boolean) { let token = AsyncStorageManager.getInstance().preferences.expoToken.current; @@ -100,8 +105,9 @@ export default class NotificationsManager { } /** - * Send the selected reminder time for notifications to the server - * @param time + * Sends the selected reminder time for notifications to the server + * + * @param time The reminder time to use */ static setMachineReminderNotificationTime(time: number) { let token = AsyncStorageManager.getInstance().preferences.expoToken.current; diff --git a/utils/ThemeManager.js b/utils/ThemeManager.js index 767ff1d..33f227a 100644 --- a/utils/ThemeManager.js +++ b/utils/ThemeManager.js @@ -19,7 +19,12 @@ export default class ThemeManager { this.updateThemeCallback = null; } - static getWhiteTheme() { + /** + * Gets the light theme + * + * @return {Object} Object containing theme variables + * */ + static getWhiteTheme(): Object { return { ...DefaultTheme, colors: { @@ -70,7 +75,12 @@ export default class ThemeManager { }; } - static getDarkTheme() { + /** + * Gets the dark theme + * + * @return {Object} Object containing theme variables + * */ + static getDarkTheme(): Object { return { ...DarkTheme, colors: { @@ -124,6 +134,7 @@ export default class ThemeManager { /** * Get this class instance or create one if none is found + * * @returns {ThemeManager} */ static getInstance(): ThemeManager { @@ -133,6 +144,10 @@ export default class ThemeManager { } /** + * Gets night mode status. + * If Follow System Preferences is enabled, will first use system theme. + * If disabled or not available, will use value stored din preferences + * * @returns {boolean} Night mode state */ static getNightMode(): boolean { @@ -143,8 +158,9 @@ export default class ThemeManager { } /** - * Get the current theme based on night mode - * @returns {Object} + * Get the current theme based on night mode and events + * + * @returns {Object} The current theme */ static getCurrentTheme(): Object { if (AprilFoolsManager.getInstance().isAprilFoolsEnabled()) @@ -153,6 +169,11 @@ export default class ThemeManager { return ThemeManager.getBaseTheme() } + /** + * Get the theme based on night mode + * + * @return {Object} The theme + */ static getBaseTheme() { if (ThemeManager.getNightMode()) return ThemeManager.getDarkTheme(); @@ -161,7 +182,8 @@ export default class ThemeManager { } /** - * Set the function to be called when the theme is changed (allows for general reload of the app) + * Sets the function to be called when the theme is changed (allows for general reload of the app) + * * @param callback Function to call after theme change */ setUpdateThemeCallback(callback: ?Function) { @@ -171,7 +193,7 @@ export default class ThemeManager { /** * Set night mode and save it to preferences * - * @param isNightMode Whether to enable night mode + * @param isNightMode True to enable night mode, false to disable */ setNightMode(isNightMode: boolean) { let nightModeKey = AsyncStorageManager.getInstance().preferences.nightMode.key;