Improved doc

This commit is contained in:
Arnaud Vergnet 2020-03-29 15:59:25 +02:00
parent 03549957a8
commit fac9d8208e
14 changed files with 433 additions and 151 deletions

View file

@ -56,6 +56,7 @@ class HomeScreen extends React.Component<Props> {
/** /**
* Converts a dateString using Unix Timestamp to a formatted date * Converts a dateString using Unix Timestamp to a formatted date
*
* @param dateString {string} The Unix Timestamp representation of a date * @param dateString {string} The Unix Timestamp representation of a date
* @return {string} The formatted output date * @return {string} The formatted output date
*/ */
@ -80,10 +81,22 @@ class HomeScreen extends React.Component<Props> {
this.props.navigation.navigate('SelfMenuScreen'); this.props.navigation.navigate('SelfMenuScreen');
} }
/**
* Extract a key for the given item
*
* @param item The item to extract the key from
* @return {*} The extracted key
*/
getKeyExtractor(item: Object) { getKeyExtractor(item: Object) {
return item !== undefined ? item.id : undefined; return item !== undefined ? item.id : undefined;
} }
/**
* Creates the dataset to be used in the FlatList
*
* @param fetchedData
* @return {*}
*/
createDataset(fetchedData: Object) { createDataset(fetchedData: Object) {
// fetchedData = DATA; // fetchedData = DATA;
let newsData = []; let newsData = [];
@ -110,6 +123,12 @@ class HomeScreen extends React.Component<Props> {
]; ];
} }
/**
* Generates the dataset associated to the dashboard to be displayed in the FlatList as a section
*
* @param dashboardData
* @return {*}
*/
generateDashboardDataset(dashboardData: Object) { generateDashboardDataset(dashboardData: Object) {
let dataset = [ let dataset = [
@ -145,6 +164,12 @@ class HomeScreen extends React.Component<Props> {
return dataset return dataset
} }
/**
* Gets a dashboard item
*
* @param item The item to display
* @return {*}
*/
getDashboardItem(item: Object) { getDashboardItem(item: Object) {
let content = item['content']; let content = item['content'];
if (item['id'] === 'event') if (item['id'] === 'event')
@ -154,7 +179,7 @@ class HomeScreen extends React.Component<Props> {
} }
/** /**
* Get the time limit depending on the current day: * Gets the time limit depending on the current day:
* 17:30 for every day of the week except for thursday 11:30 * 17:30 for every day of the week except for thursday 11:30
* 00:00 on weekends * 00:00 on weekends
*/ */
@ -170,7 +195,8 @@ class HomeScreen extends React.Component<Props> {
} }
/** /**
* Get the duration (in milliseconds) of an event * Gets the duration (in milliseconds) of an event
*
* @param event {Object} * @param event {Object}
* @return {number} The number of milliseconds * @return {number} The number of milliseconds
*/ */
@ -184,7 +210,7 @@ class HomeScreen extends React.Component<Props> {
} }
/** /**
* Get events starting after the limit * Gets events starting after the limit
* *
* @param events * @param events
* @param limit * @param limit
@ -202,8 +228,9 @@ class HomeScreen extends React.Component<Props> {
} }
/** /**
* Get the event with the longest duration in the given array. * Gets the event with the longest duration in the given array.
* If all events have the same duration, return the first in the array. * If all events have the same duration, return the first in the array.
*
* @param events * @param events
*/ */
getLongestEvent(events: Array<Object>): Object { getLongestEvent(events: Array<Object>): Object {
@ -220,7 +247,7 @@ class HomeScreen extends React.Component<Props> {
} }
/** /**
* Get events that have not yet ended/started * Gets events that have not yet ended/started
* *
* @param events * @param events
*/ */
@ -243,7 +270,7 @@ class HomeScreen extends React.Component<Props> {
} }
/** /**
* * Gets the event to display in the preview
* *
* @param events * @param events
* @return {Object} * @return {Object}
@ -266,7 +293,13 @@ class HomeScreen extends React.Component<Props> {
return displayEvent; return displayEvent;
} }
/**
* Gets the event render item.
* If a preview is available, it will be rendered inside
*
* @param content
* @return {*}
*/
getDashboardEventItem(content: Array<Object>) { getDashboardEventItem(content: Array<Object>) {
let icon = 'calendar-range'; let icon = 'calendar-range';
let title = i18n.t('homeScreen.dashboard.todayEventsTitle'); let title = i18n.t('homeScreen.dashboard.todayEventsTitle');
@ -310,7 +343,12 @@ class HomeScreen extends React.Component<Props> {
); );
} }
/**
* Gets a classic dashboard item.
*
* @param content
* @return {*}
*/
getDashboardMiddleItem(content: Array<Object>) { getDashboardMiddleItem(content: Array<Object>) {
let proxiwashData = content[0]['data']; let proxiwashData = content[0]['data'];
let tutorinsaData = content[1]['data']; let tutorinsaData = content[1]['data'];
@ -367,6 +405,12 @@ class HomeScreen extends React.Component<Props> {
WebBrowser.openBrowserAsync(link); WebBrowser.openBrowserAsync(link);
} }
/**
* Gets a render item for the given feed object
*
* @param item The feed item to display
* @return {*}
*/
getFeedItem(item: Object) { getFeedItem(item: Object) {
const onImagePress = this.openLink.bind(this, item.full_picture); const onImagePress = this.openLink.bind(this, item.full_picture);
const onOutLinkPress = this.openLink.bind(this, item.permalink_url); const onOutLinkPress = this.openLink.bind(this, item.permalink_url);
@ -382,6 +426,13 @@ class HomeScreen extends React.Component<Props> {
); );
} }
/**
* Gets a FlatList render item
*
* @param item The item to display
* @param section The current section
* @return {*}
*/
getRenderItem({item, section}: Object) { getRenderItem({item, section}: Object) {
return (section['id'] === SECTIONS_ID[0] ? return (section['id'] === SECTIONS_ID[0] ?
this.getDashboardItem(item) : this.getFeedItem(item)); this.getDashboardItem(item) : this.getFeedItem(item));

View file

@ -18,7 +18,7 @@ function openWebLink(event, link) {
} }
/** /**
* Class defining an about screen. This screen shows the user information about the app and it's author. * Class defining a planning event information page.
*/ */
class PlanningDisplayScreen extends React.Component<Props> { class PlanningDisplayScreen extends React.Component<Props> {

View file

@ -78,6 +78,9 @@ export default class PlanningScreen extends React.Component<Props, State> {
this.onBackButtonPressAndroid = this.onBackButtonPressAndroid.bind(this); this.onBackButtonPressAndroid = this.onBackButtonPressAndroid.bind(this);
} }
/**
* Captures focus and blur events to hook on android back button
*/
componentDidMount() { componentDidMount() {
this.onRefresh(); this.onRefresh();
this.didFocusSubscription = this.props.navigation.addListener( this.didFocusSubscription = this.props.navigation.addListener(
@ -98,6 +101,11 @@ export default class PlanningScreen extends React.Component<Props, State> {
); );
} }
/**
* Overrides default android back button behaviour to close the calendar if it was open.
*
* @return {boolean}
*/
onBackButtonPressAndroid() { onBackButtonPressAndroid() {
if (this.state.calendarShowing) { if (this.state.calendarShowing) {
this.agendaRef.chooseDay(this.agendaRef.state.selectedDay); this.agendaRef.chooseDay(this.agendaRef.state.selectedDay);
@ -107,6 +115,13 @@ export default class PlanningScreen extends React.Component<Props, State> {
} }
}; };
/**
* Function used to check if a row has changed
*
* @param r1
* @param r2
* @return {boolean}
*/
rowHasChanged(r1: Object, r2: Object) { rowHasChanged(r1: Object, r2: Object) {
return false; return false;
// if (r1 !== undefined && r2 !== undefined) // if (r1 !== undefined && r2 !== undefined)
@ -115,8 +130,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
} }
/** /**
* Refresh data and show a toast if any error occurred * Refreshes data and shows an animation while doing it
* @private
*/ */
onRefresh = () => { onRefresh = () => {
let canRefresh; let canRefresh;
@ -143,14 +157,30 @@ export default class PlanningScreen extends React.Component<Props, State> {
} }
}; };
/**
* Callback used when receiving the agenda ref
*
* @param ref
*/
onAgendaRef(ref: Object) { onAgendaRef(ref: Object) {
this.agendaRef = ref; this.agendaRef = ref;
} }
/**
* Callback used when a button is pressed to toggle the calendar
*
* @param isCalendarOpened True is the calendar is already open, false otherwise
*/
onCalendarToggled(isCalendarOpened: boolean) { onCalendarToggled(isCalendarOpened: boolean) {
this.setState({calendarShowing: isCalendarOpened}); this.setState({calendarShowing: isCalendarOpened});
} }
/**
* Gets an event render item
*
* @param item The current event to render
* @return {*}
*/
getRenderItem(item: eventObject) { getRenderItem(item: eventObject) {
const onPress = this.props.navigation.navigate.bind(this, 'PlanningDisplayScreen', {data: item}); const onPress = this.props.navigation.navigate.bind(this, 'PlanningDisplayScreen', {data: item});
if (item.logo !== null) { if (item.logo !== null) {
@ -182,6 +212,11 @@ export default class PlanningScreen extends React.Component<Props, State> {
} }
} }
/**
* Gets an empty render item for an empty date
*
* @return {*}
*/
getRenderEmptyDate() { getRenderEmptyDate() {
return ( return (
<Divider/> <Divider/>

View file

@ -10,7 +10,7 @@ type Props = {
}; };
/** /**
* Class defining an about screen. This screen shows the user information about the app and it's author. * Class defining the proximo about screen.
*/ */
export default class ProximoAboutScreen extends React.Component<Props> { export default class ProximoAboutScreen extends React.Component<Props> {

View file

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {Platform, Image, ScrollView, View} from "react-native"; import {Image, Platform, ScrollView, View} from "react-native";
import i18n from "i18n-js"; import i18n from "i18n-js";
import CustomModal from "../../components/CustomModal"; import CustomModal from "../../components/CustomModal";
import {Avatar, IconButton, List, RadioButton, Searchbar, Subheading, Text, Title, withTheme} from "react-native-paper"; import {Avatar, IconButton, List, RadioButton, Searchbar, Subheading, Text, Title, withTheme} from "react-native-paper";
@ -77,10 +77,10 @@ class ProximoListScreen extends React.Component<Props, State> {
/** /**
* Set the sort mode from state when components are ready * Creates the header content
*/ */
componentDidMount() { componentDidMount() {
const button = this.getSortMenu.bind(this); const button = this.getSortMenuButton.bind(this);
const title = this.getSearchBar.bind(this); const title = this.getSearchBar.bind(this);
this.props.navigation.setOptions({ this.props.navigation.setOptions({
headerRight: button, headerRight: button,
@ -93,7 +93,50 @@ class ProximoListScreen extends React.Component<Props, State> {
} }
/** /**
* Set the current sort mode. * Gets the header search bar
*
* @return {*}
*/
getSearchBar() {
return (
<Searchbar
placeholder={i18n.t('proximoScreen.search')}
onChangeText={this.onSearchStringChange}
/>
);
}
/**
* Gets the sort menu header button
*
* @return {*}
*/
getSortMenuButton() {
return (
<IconButton
icon="sort"
color={this.colors.text}
size={26}
onPress={this.onSortMenuPress}
/>
);
}
/**
* Callback used when clicking on the sort menu button.
* It will open the modal to show a sort selection
*/
onSortMenuPress() {
this.setState({
modalCurrentDisplayItem: this.getModalSortMenu()
});
if (this.modalRef) {
this.modalRef.open();
}
}
/**
* Sets the current sort mode.
* *
* @param mode The number representing the mode * @param mode The number representing the mode
*/ */
@ -121,19 +164,10 @@ class ProximoListScreen extends React.Component<Props, State> {
} }
} }
getSearchBar() {
return (
<Searchbar
placeholder={i18n.t('proximoScreen.search')}
onChangeText={this.onSearchStringChange}
/>
);
}
/** /**
* get color depending on quantity available * Gets a color depending on the quantity available
* *
* @param availableStock * @param availableStock The quantity available
* @return * @return
*/ */
getStockColor(availableStock: number) { getStockColor(availableStock: number) {
@ -147,13 +181,21 @@ class ProximoListScreen extends React.Component<Props, State> {
return color; return color;
} }
sanitizeString(str: string) { /**
* Sanitizes the given string to improve search performance
*
* @param str The string to sanitize
* @return {string} The sanitized string
*/
sanitizeString(str: string): string {
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, ""); return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
} }
/** /**
* Returns only the articles whose name contains str. Case and accents insensitive. * Returns only articles whose name contains the given string.
* @param str * Case and accents insensitive.
*
* @param str The string used to filter article names
* @returns {[]} * @returns {[]}
*/ */
filterData(str: string) { filterData(str: string) {
@ -169,12 +211,23 @@ class ProximoListScreen extends React.Component<Props, State> {
return filteredData; return filteredData;
} }
/**
* Callback used when the search changes
*
* @param str The new search string
*/
onSearchStringChange(str: string) { onSearchStringChange(str: string) {
this.setState({ this.setState({
currentlyDisplayedData: this.filterData(str) currentlyDisplayedData: this.filterData(str)
}) })
} }
/**
* Gets the modal content depending on the given article
*
* @param item The article to display
* @return {*}
*/
getModalItemContent(item: Object) { getModalItemContent(item: Object) {
return ( return (
<View style={{ <View style={{
@ -206,6 +259,11 @@ class ProximoListScreen extends React.Component<Props, State> {
); );
} }
/**
* Gets the modal content to display a sort menu
*
* @return {*}
*/
getModalSortMenu() { getModalSortMenu() {
return ( return (
<View style={{ <View style={{
@ -254,6 +312,12 @@ class ProximoListScreen extends React.Component<Props, State> {
); );
} }
/**
* Callback used when clicking an article in the list.
* It opens the modal to show detailed information about the article
*
* @param item The article pressed
*/
onListItemPress(item: Object) { onListItemPress(item: Object) {
this.setState({ this.setState({
modalCurrentDisplayItem: this.getModalItemContent(item) modalCurrentDisplayItem: this.getModalItemContent(item)
@ -263,26 +327,12 @@ class ProximoListScreen extends React.Component<Props, State> {
} }
} }
onSortMenuPress() { /**
this.setState({ * Gets a render item for the given article
modalCurrentDisplayItem: this.getModalSortMenu() *
}); * @param item The article to render
if (this.modalRef) { * @return {*}
this.modalRef.open(); */
}
}
getSortMenu() {
return (
<IconButton
icon="sort"
color={this.colors.text}
size={26}
onPress={this.onSortMenuPress}
/>
);
}
renderItem({item}: Object) { renderItem({item}: Object) {
const onPress = this.onListItemPress.bind(this, item); const onPress = this.onListItemPress.bind(this, item);
return ( return (
@ -301,10 +351,21 @@ class ProximoListScreen extends React.Component<Props, State> {
); );
} }
/**
* Extracts a key for the given article
*
* @param item The article to extract the key from
* @return {*} The extracted key
*/
keyExtractor(item: Object) { keyExtractor(item: Object) {
return item.name + item.code; return item.name + item.code;
} }
/**
* Callback used when receiving the modal ref
*
* @param ref
*/
onModalRef(ref: Object) { onModalRef(ref: Object) {
this.modalRef = ref; this.modalRef = ref;
} }

View file

@ -18,8 +18,8 @@ type State = {
} }
/** /**
* Class defining the main proximo screen. This screen shows the different categories of articles * Class defining the main proximo screen.
* offered by proximo. * This screen shows the different categories of articles offered by proximo.
*/ */
class ProximoMainScreen extends React.Component<Props, State> { class ProximoMainScreen extends React.Component<Props, State> {
@ -41,6 +41,14 @@ class ProximoMainScreen extends React.Component<Props, State> {
this.colors = props.theme.colors; this.colors = props.theme.colors;
} }
/**
* Function used to sort items in the list.
* Makes the All category stick to the top and sorts the others by name ascending
*
* @param a
* @param b
* @return {number}
*/
static sortFinalData(a: Object, b: Object) { static sortFinalData(a: Object, b: Object) {
let str1 = a.type.name.toLowerCase(); let str1 = a.type.name.toLowerCase();
let str2 = b.type.name.toLowerCase(); let str2 = b.type.name.toLowerCase();
@ -59,17 +67,76 @@ class ProximoMainScreen extends React.Component<Props, State> {
return 0; return 0;
} }
/**
* Creates header button
*/
componentDidMount() { componentDidMount() {
const rightButton = this.getRightButton.bind(this); const rightButton = this.getHeaderButtons.bind(this);
this.props.navigation.setOptions({ this.props.navigation.setOptions({
headerRight: rightButton, headerRight: rightButton,
}); });
} }
/**
* Callback used when the search button is pressed.
* This will open a new ProximoListScreen with all items displayed
*/
onPressSearchBtn() {
let searchScreenData = {
shouldFocusSearchBar: true,
data: {
type: {
id: "0",
name: i18n.t('proximoScreen.all'),
icon: 'star'
},
data: this.articles !== undefined ?
this.getAvailableArticles(this.articles, undefined) : []
},
};
this.props.navigation.navigate('ProximoListScreen', searchScreenData);
}
/**
* Callback used when the about button is pressed.
* This will open the ProximoAboutScreen
*/
onPressAboutBtn() {
this.props.navigation.navigate('ProximoAboutScreen');
}
/**
* Gets the header buttons
* @return {*}
*/
getHeaderButtons() {
return (
<View
style={{
flexDirection: 'row',
}}>
<HeaderButton icon={'magnify'} onPress={this.onPressSearchBtn}/>
<HeaderButton icon={'information'} onPress={this.onPressAboutBtn}/>
</View>
);
}
/**
* Extracts a key for the given category
*
* @param item The category to extract the key from
* @return {*} The extracted key
*/
getKeyExtractor(item: Object) { getKeyExtractor(item: Object) {
return item !== undefined ? item.type['id'] : undefined; return item !== undefined ? item.type['id'] : undefined;
} }
/**
* Creates the dataset to be used in the FlatList
*
* @param fetchedData
* @return {*}
* */
createDataset(fetchedData: Object) { createDataset(fetchedData: Object) {
return [ return [
{ {
@ -133,39 +200,12 @@ class ProximoMainScreen extends React.Component<Props, State> {
return availableArticles; return availableArticles;
} }
onPressSearchBtn() { /**
let searchScreenData = { * Gets the given category render item
shouldFocusSearchBar: true, *
data: { * @param item The category to render
type: { * @return {*}
id: "0", */
name: i18n.t('proximoScreen.all'),
icon: 'star'
},
data: this.articles !== undefined ?
this.getAvailableArticles(this.articles, undefined) : []
},
};
this.props.navigation.navigate('ProximoListScreen', searchScreenData);
}
onPressAboutBtn() {
this.props.navigation.navigate('ProximoAboutScreen');
}
getRightButton() {
return (
<View
style={{
flexDirection: 'row',
}}>
<HeaderButton icon={'magnify'} onPress={this.onPressSearchBtn}/>
<HeaderButton icon={'information'} onPress={this.onPressAboutBtn}/>
</View>
);
}
getRenderItem({item}: Object) { getRenderItem({item}: Object) {
let dataToSend = { let dataToSend = {
shouldFocusSearchBar: false, shouldFocusSearchBar: false,

View file

@ -10,7 +10,7 @@ type Props = {
}; };
/** /**
* Class defining an about screen. This screen shows the user information about the app and it's author. * Class defining the proxiwash about screen.
*/ */
export default class ProxiwashAboutScreen extends React.Component<Props> { export default class ProxiwashAboutScreen extends React.Component<Props> {

View file

@ -58,7 +58,6 @@ class ProxiwashScreen extends React.Component<Props, State> {
refreshing: false, refreshing: false,
firstLoading: true, firstLoading: true,
fetchedData: {}, fetchedData: {},
// machinesWatched: JSON.parse(dataString),
machinesWatched: [], machinesWatched: [],
modalCurrentDisplayItem: null, modalCurrentDisplayItem: null,
bannerVisible: AsyncStorageManager.getInstance().preferences.proxiwashShowBanner.current === '1', bannerVisible: AsyncStorageManager.getInstance().preferences.proxiwashShowBanner.current === '1',
@ -97,6 +96,10 @@ class ProxiwashScreen extends React.Component<Props, State> {
this.colors = props.theme.colors; this.colors = props.theme.colors;
} }
/**
* Callback used when closing the banner.
* This hides the banner and saves to preferences to prevent it from reopening
*/
onHideBanner() { onHideBanner() {
this.setState({bannerVisible: false}); this.setState({bannerVisible: false});
AsyncStorageManager.getInstance().savePref( AsyncStorageManager.getInstance().savePref(
@ -109,7 +112,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
* Setup notification channel for android and add listeners to detect notifications fired * Setup notification channel for android and add listeners to detect notifications fired
*/ */
componentDidMount() { componentDidMount() {
const rightButton = this.getRightButton.bind(this); const rightButton = this.getAboutButton.bind(this);
this.props.navigation.setOptions({ this.props.navigation.setOptions({
headerRight: rightButton, headerRight: rightButton,
}); });
@ -134,16 +137,35 @@ class ProxiwashScreen extends React.Component<Props, State> {
} }
} }
getDryersKeyExtractor(item: Object) { /**
return item !== undefined ? "dryer" + item.number : undefined; * Callback used when pressing the about button.
} * This will open the ProxiwashAboutScreen.
*/
getWashersKeyExtractor(item: Object) { onAboutPress() {
return item !== undefined ? "washer" + item.number : undefined; this.props.navigation.navigate('ProxiwashAboutScreen');
} }
/** /**
* Setup notifications for the machine with the given ID. * Gets the about header button
*
* @return {*}
*/
getAboutButton() {
return <HeaderButton icon={'information'} onPress={this.onAboutPress}/>;
}
/**
* Extracts the key for the given item
*
* @param item The item to extract the key from
* @return {*} The extracted key
*/
getKeyExtractor(item: Object) {
return item !== undefined ? item.number : undefined;
}
/**
* Setups notifications for the machine with the given ID.
* One notification will be sent at the end of the program. * 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 * Another will be send a few minutes before the end, based on the value of reminderNotifTime
* *
@ -162,6 +184,9 @@ class ProxiwashScreen extends React.Component<Props, State> {
} }
} }
/**
* Shows a warning telling the user notifications are disabled for the app
*/
showNotificationsDisabledWarning() { showNotificationsDisabledWarning() {
Alert.alert( Alert.alert(
i18n.t("proxiwashScreen.modal.notificationErrorTitle"), i18n.t("proxiwashScreen.modal.notificationErrorTitle"),
@ -170,7 +195,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
} }
/** /**
* Stop scheduled notifications for the machine of the given ID. * Stops scheduled notifications for the machine of the given ID.
* This will also remove the notification if it was already shown. * This will also remove the notification if it was already shown.
* *
* @param machineId The machine's ID * @param machineId The machine's ID
@ -187,7 +212,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
} }
/** /**
* Add the given notifications associated to a machine ID to the watchlist, and save the array to the preferences * Adds the given notifications associated to a machine ID to the watchlist, and saves the array to the preferences
* *
* @param machineId * @param machineId
*/ */
@ -198,7 +223,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
} }
/** /**
* remove the given index from the watchlist array and save it to preferences * Removes the given index from the watchlist array and saves it to preferences
* *
* @param index * @param index
*/ */
@ -209,14 +234,12 @@ class ProxiwashScreen extends React.Component<Props, State> {
} }
/** /**
* Set the given data as the watchlist and save it to preferences * Sets the given data as the watchlist
* *
* @param data * @param data
*/ */
updateNotificationState(data: Array<Object>) { updateNotificationState(data: Array<Object>) {
this.setState({machinesWatched: data}); this.setState({machinesWatched: data});
// let prefKey = AsyncStorageManager.getInstance().preferences.proxiwashWatchedMachines.key;
// AsyncStorageManager.getInstance().savePref(prefKey, JSON.stringify(data));
} }
/** /**
@ -229,6 +252,12 @@ class ProxiwashScreen extends React.Component<Props, State> {
return this.state.machinesWatched.indexOf(machineID) !== -1; return this.state.machinesWatched.indexOf(machineID) !== -1;
} }
/**
* Creates the dataset to be used by the flatlist
*
* @param fetchedData
* @return {*}
*/
createDataset(fetchedData: Object) { createDataset(fetchedData: Object) {
let data = fetchedData; let data = fetchedData;
if (AprilFoolsManager.getInstance().isAprilFoolsEnabled()) { if (AprilFoolsManager.getInstance().isAprilFoolsEnabled()) {
@ -244,18 +273,25 @@ class ProxiwashScreen extends React.Component<Props, State> {
icon: 'tumble-dryer', icon: 'tumble-dryer',
data: data.dryers === undefined ? [] : data.dryers, data: data.dryers === undefined ? [] : data.dryers,
extraData: this.state, extraData: this.state,
keyExtractor: this.getDryersKeyExtractor keyExtractor: this.getKeyExtractor
}, },
{ {
title: i18n.t('proxiwashScreen.washers'), title: i18n.t('proxiwashScreen.washers'),
icon: 'washing-machine', icon: 'washing-machine',
data: data.washers === undefined ? [] : data.washers, data: data.washers === undefined ? [] : data.washers,
extraData: this.state, extraData: this.state,
keyExtractor: this.getWashersKeyExtractor keyExtractor: this.getKeyExtractor
}, },
]; ];
} }
/**
* Shows a modal for the given item
*
* @param title The title to use
* @param item The item to display information for in the modal
* @param isDryer True if the given item is a dryer
*/
showModal(title: string, item: Object, isDryer: boolean) { showModal(title: string, item: Object, isDryer: boolean) {
this.setState({ this.setState({
modalCurrentDisplayItem: this.getModalContent(title, item, isDryer) modalCurrentDisplayItem: this.getModalContent(title, item, isDryer)
@ -265,6 +301,11 @@ class ProxiwashScreen extends React.Component<Props, State> {
} }
} }
/**
* Callback used when the user clicks on enable notifications for a machine
*
* @param machineId The machine's id to set notifications for
*/
onSetupNotificationsPress(machineId: string) { onSetupNotificationsPress(machineId: string) {
if (this.modalRef) { if (this.modalRef) {
this.modalRef.close(); this.modalRef.close();
@ -272,6 +313,15 @@ class ProxiwashScreen extends React.Component<Props, State> {
this.setupNotifications(machineId) this.setupNotifications(machineId)
} }
/**
* Generates the modal content.
* This shows information for the given machine.
*
* @param title The title to use
* @param item The item to display information for in the modal
* @param isDryer True if the given item is a dryer
* @return {*}
*/
getModalContent(title: string, item: Object, isDryer: boolean) { getModalContent(title: string, item: Object, isDryer: boolean) {
let button = { let button = {
text: i18n.t("proxiwashScreen.modal.ok"), text: i18n.t("proxiwashScreen.modal.ok"),
@ -334,20 +384,21 @@ class ProxiwashScreen extends React.Component<Props, State> {
); );
} }
onAboutPress() { /**
this.props.navigation.navigate('ProxiwashAboutScreen'); * Callback used when receiving modal ref
} *
* @param ref
getRightButton() { */
return (
<HeaderButton icon={'information'} onPress={this.onAboutPress}/>
);
}
onModalRef(ref: Object) { onModalRef(ref: Object) {
this.modalRef = ref; this.modalRef = ref;
} }
/**
* Gets the number of machines available
*
* @param isDryer True if we are only checking for dryer, false for washers
* @return {number} The number of machines available
*/
getMachineAvailableNumber(isDryer: boolean) { getMachineAvailableNumber(isDryer: boolean) {
let data; let data;
if (isDryer) if (isDryer)
@ -362,6 +413,12 @@ class ProxiwashScreen extends React.Component<Props, State> {
return count; return count;
} }
/**
* Gets the section render item
*
* @param section The section to render
* @return {*}
*/
getRenderSectionHeader({section}: Object) { getRenderSectionHeader({section}: Object) {
const isDryer = section.title === i18n.t('proxiwashScreen.dryers'); const isDryer = section.title === i18n.t('proxiwashScreen.dryers');
const nbAvailable = this.getMachineAvailableNumber(isDryer); const nbAvailable = this.getMachineAvailableNumber(isDryer);
@ -401,7 +458,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
} }
/** /**
* Get list item to be rendered * Gets the list item to be rendered
* *
* @param item The object containing the item's FetchedData * @param item The object containing the item's FetchedData
* @param section The object describing the current SectionList section * @param section The object describing the current SectionList section
@ -467,7 +524,6 @@ class ProxiwashScreen extends React.Component<Props, State> {
refreshOnFocus={true} refreshOnFocus={true}
updateData={this.state.machinesWatched.length}/> updateData={this.state.machinesWatched.length}/>
</View> </View>
); );
} }
} }

View file

@ -15,7 +15,6 @@ type Props = {
/** /**
* Class defining the app's menu screen. * Class defining the app's menu screen.
* This screen fetches data from etud to render the RU menu
*/ */
class SelfMenuScreen extends React.Component<Props> { class SelfMenuScreen extends React.Component<Props> {
@ -33,10 +32,22 @@ class SelfMenuScreen extends React.Component<Props> {
this.colors = props.theme.colors; this.colors = props.theme.colors;
} }
/**
* Extract a key for the given item
*
* @param item The item to extract the key from
* @return {*} The extracted key
*/
getKeyExtractor(item: Object) { getKeyExtractor(item: Object) {
return item !== undefined ? item['name'] : undefined; return item !== undefined ? item['name'] : undefined;
} }
/**
* Creates the dataset to be used in the FlatList
*
* @param fetchedData
* @return {[]}
*/
createDataset(fetchedData: Object) { createDataset(fetchedData: Object) {
let result = []; let result = [];
// Prevent crash by giving a default value when fetchedData is empty (not yet available) // Prevent crash by giving a default value when fetchedData is empty (not yet available)
@ -66,6 +77,12 @@ class SelfMenuScreen extends React.Component<Props> {
return result return result
} }
/**
* Gets the render section header
*
* @param section The section to render the header from
* @return {*}
*/
getRenderSectionHeader({section}: Object) { getRenderSectionHeader({section}: Object) {
return ( return (
<Card style={{ <Card style={{
@ -92,6 +109,12 @@ class SelfMenuScreen extends React.Component<Props> {
); );
} }
/**
* Gets a FlatList render item
*
* @param item The item to render
* @return {*}
*/
getRenderItem({item}: Object) { getRenderItem({item}: Object) {
return ( return (
<Card style={{ <Card style={{
@ -128,6 +151,12 @@ class SelfMenuScreen extends React.Component<Props> {
); );
} }
/**
* Formats the given string to make sure it starts with a capital letter
*
* @param name The string to format
* @return {string} The formatted string
*/
formatName(name: String) { formatName(name: String) {
return name.charAt(0) + name.substr(1).toLowerCase(); return name.charAt(0) + name.substr(1).toLowerCase();
} }

View file

@ -27,7 +27,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
state = { state = {
nightMode: ThemeManager.getNightMode(), nightMode: ThemeManager.getNightMode(),
nightModeFollowSystem: AsyncStorageManager.getInstance().preferences.nightModeFollowSystem.current === '1' && nightModeFollowSystem: AsyncStorageManager.getInstance().preferences.nightModeFollowSystem.current === '1' &&
Appearance.getColorScheme() !== 'no-preference', Appearance.getColorScheme() !== 'no-preference',
proxiwashNotifPickerSelected: AsyncStorageManager.getInstance().preferences.proxiwashNotifications.current, proxiwashNotifPickerSelected: AsyncStorageManager.getInstance().preferences.proxiwashNotifications.current,
startScreenPickerSelected: AsyncStorageManager.getInstance().preferences.defaultStartScreen.current, startScreenPickerSelected: AsyncStorageManager.getInstance().preferences.defaultStartScreen.current,
}; };
@ -46,7 +46,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
} }
/** /**
* Save the value for the proxiwash reminder notification time * Saves the value for the proxiwash reminder notification time
* *
* @param value The value to store * @param value The value to store
*/ */
@ -65,7 +65,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
} }
/** /**
* Save the value for the proxiwash reminder notification time * Saves the value for the proxiwash reminder notification time
* *
* @param value The value to store * @param value The value to store
*/ */
@ -118,7 +118,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
} }
/** /**
* Toggle night mode and save it to preferences * Toggles night mode and saves it to preferences
*/ */
onToggleNightMode() { onToggleNightMode() {
ThemeManager.getInstance().setNightMode(!this.state.nightMode); ThemeManager.getInstance().setNightMode(!this.state.nightMode);
@ -138,7 +138,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
} }
/** /**
* Get a list item using a checkbox control * Gets a list item using a checkbox control
* *
* @param onPressCallback The callback when the checkbox state changes * @param onPressCallback The callback when the checkbox state changes
* @param icon The icon name to display on the list item * @param icon The icon name to display on the list item
@ -178,15 +178,15 @@ export default class SettingsScreen extends React.Component<Props, State> {
) : null} ) : null}
{ {
Appearance.getColorScheme() === 'no-preference' || !this.state.nightModeFollowSystem ? Appearance.getColorScheme() === 'no-preference' || !this.state.nightModeFollowSystem ?
this.getToggleItem( this.getToggleItem(
this.onToggleNightMode, this.onToggleNightMode,
'theme-light-dark', 'theme-light-dark',
i18n.t('settingsScreen.nightMode'), i18n.t('settingsScreen.nightMode'),
this.state.nightMode ? this.state.nightMode ?
i18n.t('settingsScreen.nightModeSubOn') : i18n.t('settingsScreen.nightModeSubOn') :
i18n.t('settingsScreen.nightModeSubOff'), i18n.t('settingsScreen.nightModeSubOff'),
this.state.nightMode this.state.nightMode
) : null ) : null
} }
<List.Accordion <List.Accordion
title={i18n.t('settingsScreen.startScreen')} title={i18n.t('settingsScreen.startScreen')}
@ -209,7 +209,6 @@ export default class SettingsScreen extends React.Component<Props, State> {
</List.Accordion> </List.Accordion>
</List.Section> </List.Section>
</Card> </Card>
</ScrollView> </ScrollView>
); );
} }

View file

@ -14,14 +14,16 @@ const PC_URL = 'http://planex.insa-toulouse.fr/sallesInfo.php';
const CUSTOM_CSS_GENERAL = 'https://etud.insa-toulouse.fr/~amicale_app/custom_css/rooms/customMobile.css'; const CUSTOM_CSS_GENERAL = 'https://etud.insa-toulouse.fr/~amicale_app/custom_css/rooms/customMobile.css';
/** /**
* Class defining the app's planex screen. * Class defining the app's available rooms screen.
* This screen uses a webview to render the planex page * This screen uses a webview to render the page
*/ */
export default class AvailableRoomScreen extends React.Component<Props> { export default class AvailableRoomScreen extends React.Component<Props> {
customInjectedJS: string; customInjectedJS: string;
customBibInjectedJS: string;
/**
* Defines custom injected JavaScript to improve the page display on mobile
*/
constructor() { constructor() {
super(); super();
this.customInjectedJS = this.customInjectedJS =

View file

@ -13,14 +13,17 @@ const CUSTOM_CSS_GENERAL = 'https://etud.insa-toulouse.fr/~amicale_app/custom_cs
const CUSTOM_CSS_Bib = 'https://etud.insa-toulouse.fr/~amicale_app/custom_css/rooms/customBibMobile.css'; const CUSTOM_CSS_Bib = 'https://etud.insa-toulouse.fr/~amicale_app/custom_css/rooms/customBibMobile.css';
/** /**
* Class defining the app's planex screen. * Class defining the app's Bib screen.
* This screen uses a webview to render the planex page * This screen uses a webview to render the page
*/ */
export default class AvailableRoomScreen extends React.Component<Props> { export default class AvailableRoomScreen extends React.Component<Props> {
customInjectedJS: string; customInjectedJS: string;
customBibInjectedJS: string; customBibInjectedJS: string;
/**
* Defines custom injected JavaScript to improve the page display on mobile
*/
constructor() { constructor() {
super(); super();
this.customInjectedJS = this.customInjectedJS =

View file

@ -80,15 +80,23 @@ const OBSERVE_MUTATIONS_INJECTED =
' removeAlpha($(this));\n' + ' removeAlpha($(this));\n' +
'});'; '});';
/** /**
* Class defining the app's planex screen. * Class defining the app's Planex screen.
* This screen uses a webview to render the planex page * This screen uses a webview to render the page
*/ */
export default class PlanexScreen extends React.Component<Props, State> { export default class PlanexScreen extends React.Component<Props, State> {
customInjectedJS: string; customInjectedJS: string;
onHideBanner: Function; onHideBanner: Function;
onGoToSettings: Function; onGoToSettings: Function;
state = {
bannerVisible:
AsyncStorageManager.getInstance().preferences.planexShowBanner.current === '1' &&
AsyncStorageManager.getInstance().preferences.defaultStartScreen.current !== 'Planex',
};
/**
* Defines custom injected JavaScript to improve the page display on mobile
*/
constructor() { constructor() {
super(); super();
this.customInjectedJS = this.customInjectedJS =
@ -102,17 +110,15 @@ export default class PlanexScreen extends React.Component<Props, State> {
this.customInjectedJS += this.customInjectedJS +=
'removeAlpha();' + 'removeAlpha();' +
'});true;'; // Prevent crash on ios '});true;'; // Prevents crash on ios
this.onHideBanner = this.onHideBanner.bind(this); this.onHideBanner = this.onHideBanner.bind(this);
this.onGoToSettings = this.onGoToSettings.bind(this); this.onGoToSettings = this.onGoToSettings.bind(this);
} }
state = { /**
bannerVisible: * Callback used when closing the banner.
AsyncStorageManager.getInstance().preferences.planexShowBanner.current === '1' && * This hides the banner and saves to preferences to prevent it from reopening
AsyncStorageManager.getInstance().preferences.defaultStartScreen.current !== 'Planex', */
};
onHideBanner() { onHideBanner() {
this.setState({bannerVisible: false}); this.setState({bannerVisible: false});
AsyncStorageManager.getInstance().savePref( AsyncStorageManager.getInstance().savePref(
@ -121,6 +127,11 @@ export default class PlanexScreen extends React.Component<Props, State> {
); );
} }
/**
* Callback used when the used click on the navigate to settings button.
* This will hide the banner and open the SettingsScreen
*
*/
onGoToSettings() { onGoToSettings() {
this.onHideBanner(); this.onHideBanner();
this.props.navigation.navigate('SettingsScreen'); this.props.navigation.navigate('SettingsScreen');

View file

@ -39,11 +39,6 @@ export default class AsyncStorageManager {
default: '5', default: '5',
current: '', current: '',
}, },
proxiwashWatchedMachines: {
key: 'proxiwashWatchedMachines',
default: '[]',
current: '',
},
nightModeFollowSystem: { nightModeFollowSystem: {
key: 'nightModeFollowSystem', key: 'nightModeFollowSystem',
default: '1', default: '1',