Added documentation
This commit is contained in:
parent
0385bbb882
commit
0bdcf5a4ba
13 changed files with 260 additions and 27 deletions
|
@ -13,14 +13,19 @@ type Props = {
|
||||||
navigation: Object,
|
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<Props> {
|
export default class CustomHeader extends React.Component<Props> {
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
backButton: false,
|
backButton: false,
|
||||||
rightMenu: <Right/>,
|
rightMenu: <Right/>,
|
||||||
fontSize: 26,
|
|
||||||
width: 30,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -12,6 +12,15 @@ type Props = {
|
||||||
width: number,
|
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<Props> {
|
export default class CustomMaterialIcon extends React.Component<Props> {
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
|
|
@ -20,15 +20,24 @@ type State = {
|
||||||
active: string,
|
active: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to define a navigation drawer
|
||||||
|
*/
|
||||||
export default class SideBar extends React.Component<Props, State> {
|
export default class SideBar extends React.Component<Props, State> {
|
||||||
|
|
||||||
dataSet: Array<Object>;
|
dataSet: Array<Object>;
|
||||||
|
|
||||||
|
state = {
|
||||||
|
active: 'Home',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the datasets
|
||||||
|
*
|
||||||
|
* @param props
|
||||||
|
*/
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
|
||||||
active: 'Home',
|
|
||||||
};
|
|
||||||
this.dataSet = [
|
this.dataSet = [
|
||||||
{
|
{
|
||||||
name: i18n.t('screens.home'),
|
name: i18n.t('screens.home'),
|
||||||
|
@ -82,6 +91,10 @@ export default class SideBar extends React.Component<Props, State> {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
navigateToScreen(route: string) {
|
||||||
this.props.navigation.navigate(route);
|
this.props.navigation.navigate(route);
|
||||||
this.props.navigation.closeDrawer();
|
this.props.navigation.closeDrawer();
|
||||||
|
|
|
@ -6,6 +6,9 @@ import MainDrawerNavigator from './MainDrawerNavigator';
|
||||||
import ProximoListScreen from '../screens/Proximo/ProximoListScreen';
|
import ProximoListScreen from '../screens/Proximo/ProximoListScreen';
|
||||||
import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
|
import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a stack navigator using the drawer to handle navigation between screens
|
||||||
|
*/
|
||||||
export default createAppContainer(
|
export default createAppContainer(
|
||||||
createStackNavigator({
|
createStackNavigator({
|
||||||
Main: MainDrawerNavigator,
|
Main: MainDrawerNavigator,
|
||||||
|
|
|
@ -11,7 +11,9 @@ import SettingsScreen from '../screens/SettingsScreen';
|
||||||
import AboutScreen from '../screens/About/AboutScreen';
|
import AboutScreen from '../screens/About/AboutScreen';
|
||||||
import SideMenu from "../components/SideMenu";
|
import SideMenu from "../components/SideMenu";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the drawer navigation stack
|
||||||
|
*/
|
||||||
export default createDrawerNavigator({
|
export default createDrawerNavigator({
|
||||||
Home: {screen: HomeScreen},
|
Home: {screen: HomeScreen},
|
||||||
Planning: {screen: PlanningScreen,},
|
Planning: {screen: PlanningScreen,},
|
||||||
|
|
|
@ -20,6 +20,9 @@ type Props = {
|
||||||
navigation: Object
|
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<Props> {
|
export default class AboutDependenciesScreen extends React.Component<Props> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -26,13 +26,22 @@ type Props = {
|
||||||
navigation: Object,
|
navigation: Object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a link in the device's browser
|
||||||
|
* @param link The link to open
|
||||||
|
*/
|
||||||
function openWebLink(link) {
|
function openWebLink(link) {
|
||||||
Linking.openURL(link).catch((err) => console.error('Error opening link', err));
|
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<Props> {
|
export default class AboutScreen extends React.Component<Props> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data to be displayed in the app card
|
||||||
|
*/
|
||||||
appData: Array<Object> = [
|
appData: Array<Object> = [
|
||||||
{
|
{
|
||||||
onPressCallback: () => openWebLink(Platform.OS === "ios" ? links.appstore : links.playstore),
|
onPressCallback: () => openWebLink(Platform.OS === "ios" ? links.appstore : links.playstore),
|
||||||
|
@ -66,6 +75,9 @@ export default class AboutScreen extends React.Component<Props> {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data to be displayed in the author card
|
||||||
|
*/
|
||||||
authorData: Array<Object> = [
|
authorData: Array<Object> = [
|
||||||
{
|
{
|
||||||
onPressCallback: () => Alert.alert('Coucou', 'Whaou'),
|
onPressCallback: () => Alert.alert('Coucou', 'Whaou'),
|
||||||
|
@ -93,6 +105,9 @@ export default class AboutScreen extends React.Component<Props> {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data to be displayed in the technologies card
|
||||||
|
*/
|
||||||
technoData: Array<Object> = [
|
technoData: Array<Object> = [
|
||||||
{
|
{
|
||||||
onPressCallback: () => openWebLink(links.react),
|
onPressCallback: () => openWebLink(links.react),
|
||||||
|
@ -108,7 +123,16 @@ export default class AboutScreen extends React.Component<Props> {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
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 (
|
return (
|
||||||
<CardItem button
|
<CardItem button
|
||||||
onPress={onPressCallback}>
|
onPress={onPressCallback}>
|
||||||
|
@ -150,7 +174,7 @@ export default class AboutScreen extends React.Component<Props> {
|
||||||
data={this.appData}
|
data={this.appData}
|
||||||
keyExtractor={(item) => item.icon}
|
keyExtractor={(item) => item.icon}
|
||||||
renderItem={({item}) =>
|
renderItem={({item}) =>
|
||||||
this.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron)
|
AboutScreen.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -163,7 +187,7 @@ export default class AboutScreen extends React.Component<Props> {
|
||||||
data={this.authorData}
|
data={this.authorData}
|
||||||
keyExtractor={(item) => item.icon}
|
keyExtractor={(item) => item.icon}
|
||||||
renderItem={({item}) =>
|
renderItem={({item}) =>
|
||||||
this.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron)
|
AboutScreen.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -176,7 +200,7 @@ export default class AboutScreen extends React.Component<Props> {
|
||||||
data={this.technoData}
|
data={this.technoData}
|
||||||
keyExtractor={(item) => item.icon}
|
keyExtractor={(item) => item.icon}
|
||||||
renderItem={({item}) =>
|
renderItem={({item}) =>
|
||||||
this.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron)
|
AboutScreen.getCardItem(item.onPressCallback, item.icon, item.text, item.showChevron)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
@ -10,6 +10,9 @@ type Props = {
|
||||||
navigation: Object,
|
navigation: Object,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class defining the app's home screen
|
||||||
|
*/
|
||||||
export default class HomeScreen extends React.Component<Props> {
|
export default class HomeScreen extends React.Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
const nav = this.props.navigation;
|
const nav = this.props.navigation;
|
||||||
|
|
|
@ -9,6 +9,9 @@ type Props = {
|
||||||
navigation: Object,
|
navigation: Object,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class defining the app's planning screen
|
||||||
|
*/
|
||||||
export default class PlanningScreen extends React.Component<Props> {
|
export default class PlanningScreen extends React.Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
const nav = this.props.navigation;
|
const nav = this.props.navigation;
|
||||||
|
|
|
@ -16,7 +16,6 @@ const sortMode = {
|
||||||
name: '1',
|
name: '1',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function sortPrice(a, b) {
|
function sortPrice(a, b) {
|
||||||
return a.price - b.price;
|
return a.price - b.price;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +52,10 @@ type State = {
|
||||||
sortNameIcon: React.Node,
|
sortNameIcon: React.Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ProximoMainScreen extends React.Component<Props, State> {
|
/**
|
||||||
|
* Class defining proximo's article list of a certain category.
|
||||||
|
*/
|
||||||
|
export default class ProximoListScreen extends React.Component<Props, State> {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
navData: this.props.navigation.getParam('data', []).sort(sortPrice),
|
navData: this.props.navigation.getParam('data', []).sort(sortPrice),
|
||||||
|
@ -65,11 +67,22 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
|
||||||
|
|
||||||
_menu: Menu;
|
_menu: Menu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the reference to the sort menu for later use
|
||||||
|
*
|
||||||
|
* @param ref The menu reference
|
||||||
|
*/
|
||||||
setMenuRef = (ref: Menu) => {
|
setMenuRef = (ref: Menu) => {
|
||||||
this._menu = ref;
|
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;
|
let isReverse = this.state.isSortReversed;
|
||||||
if (mode === this.state.currentSortMode) // reverse mode
|
if (mode === this.state.currentSortMode) // reverse mode
|
||||||
isReverse = !isReverse; // this.state not updating on this function cycle
|
isReverse = !isReverse; // this.state not updating on this function cycle
|
||||||
|
@ -78,6 +91,12 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
|
||||||
this.setSortMode(mode, isReverse);
|
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) {
|
setSortMode(mode: string, isReverse: boolean) {
|
||||||
this.setState({
|
this.setState({
|
||||||
currentSortMode: mode,
|
currentSortMode: mode,
|
||||||
|
@ -107,10 +126,19 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
|
||||||
this._menu.hide();
|
this._menu.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the sort mode from state when components are ready
|
||||||
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.setSortMode(this.state.currentSortMode, this.state.isSortReversed);
|
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) {
|
setupSortIcons(mode: string, isReverse: boolean) {
|
||||||
const downSortIcon =
|
const downSortIcon =
|
||||||
<Icon
|
<Icon
|
||||||
|
@ -166,12 +194,12 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onPress={() => this.toggleSortMode(sortMode.name)}>
|
onPress={() => this.sortModeSelected(sortMode.name)}>
|
||||||
{this.state.sortNameIcon}
|
{this.state.sortNameIcon}
|
||||||
{i18n.t('proximoScreen.sortName')}
|
{i18n.t('proximoScreen.sortName')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onPress={() => this.toggleSortMode(sortMode.price)}>
|
onPress={() => this.sortModeSelected(sortMode.price)}>
|
||||||
{this.state.sortPriceIcon}
|
{this.state.sortPriceIcon}
|
||||||
{i18n.t('proximoScreen.sortPrice')}
|
{i18n.t('proximoScreen.sortPrice')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
|
@ -27,6 +27,10 @@ type State = {
|
||||||
data: Object,
|
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<Props, State> {
|
export default class ProximoMainScreen extends React.Component<Props, State> {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -35,7 +39,15 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
|
||||||
data: {},
|
data: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
static generateDataset(types: Array<string>, 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<string>, data: Array<Object>) {
|
||||||
let finalData = [];
|
let finalData = [];
|
||||||
for (let i = 0; i < types.length; i++) {
|
for (let i = 0; i < types.length; i++) {
|
||||||
finalData.push({
|
finalData.push({
|
||||||
|
@ -51,6 +63,11 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
|
||||||
return finalData;
|
return finalData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Async function reading data from the proximo website and setting the state to rerender the list
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
async readData() {
|
async readData() {
|
||||||
try {
|
try {
|
||||||
let response = await fetch(DATA_URL);
|
let response = await fetch(DATA_URL);
|
||||||
|
@ -68,10 +85,18 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the list on first screen load
|
||||||
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this._onRefresh();
|
this._onRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a loading indicator and fetch data from the internet
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
_onRefresh = () => {
|
_onRefresh = () => {
|
||||||
this.setState({refreshing: true});
|
this.setState({refreshing: true});
|
||||||
this.readData().then(() => {
|
this.readData().then(() => {
|
||||||
|
@ -88,7 +113,12 @@ export default class ProximoMainScreen extends React.Component<Props, State> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {
|
render() {
|
||||||
const nav = this.props.navigation;
|
const nav = this.props.navigation;
|
||||||
const data = [
|
const data = [
|
||||||
|
|
|
@ -38,6 +38,10 @@ type State = {
|
||||||
machinesWatched: Array<Object>
|
machinesWatched: Array<Object>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<Props, State> {
|
export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -47,6 +51,11 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
machinesWatched: [],
|
machinesWatched: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates machine state parameters using current theme and translations
|
||||||
|
*
|
||||||
|
* @param props
|
||||||
|
*/
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
let colors = ThemeManager.getInstance().getCurrentThemeVariables();
|
let colors = ThemeManager.getInstance().getCurrentThemeVariables();
|
||||||
|
@ -63,6 +72,11 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
stateStrings[MACHINE_STATES.ERREUR] = i18n.t('proxiwashScreen.states.error');
|
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<void>}
|
||||||
|
*/
|
||||||
async readData() {
|
async readData() {
|
||||||
try {
|
try {
|
||||||
let response = await fetch(DATA_URL);
|
let response = await fetch(DATA_URL);
|
||||||
|
@ -75,6 +89,11 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get which machines have notifications enabled before loading the screen
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
async componentWillMount() {
|
async componentWillMount() {
|
||||||
let dataString = await AsyncStorage.getItem(WATCHED_MACHINES_PREFKEY);
|
let dataString = await AsyncStorage.getItem(WATCHED_MACHINES_PREFKEY);
|
||||||
if (dataString === null)
|
if (dataString === null)
|
||||||
|
@ -84,11 +103,18 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the data on first screen load
|
||||||
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this._onRefresh();
|
this._onRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the refresh inddicator and wait for data to be fetched from the scrapper
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
_onRefresh = () => {
|
_onRefresh = () => {
|
||||||
this.setState({refreshing: true});
|
this.setState({refreshing: true});
|
||||||
this.readData().then(() => {
|
this.readData().then(() => {
|
||||||
|
@ -105,6 +131,14 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
static getRemainingTime(startString: string, endString: string, percentDone: string): number {
|
||||||
let startArray = startString.split(':');
|
let startArray = startString.split(':');
|
||||||
let endArray = endString.split(':');
|
let endArray = endString.split(':');
|
||||||
|
@ -117,6 +151,15 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
return parseInt(time);
|
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<void>}
|
||||||
|
*/
|
||||||
async setupNotifications(machineId: string, remainingTime: number) {
|
async setupNotifications(machineId: string, remainingTime: number) {
|
||||||
if (!this.isMachineWatched(machineId)) {
|
if (!this.isMachineWatched(machineId)) {
|
||||||
let endNotifID = await NotificationsManager.scheduleNotification(
|
let endNotifID = await NotificationsManager.scheduleNotification(
|
||||||
|
@ -148,6 +191,12 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
this.disableNotification(machineId);
|
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) {
|
disableNotification(machineId: string) {
|
||||||
let data: Object = this.state.machinesWatched;
|
let data: Object = this.state.machinesWatched;
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
|
@ -164,12 +213,26 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 this.state.machinesWatched.find(function (elem) {
|
||||||
return elem.machineNumber === number
|
return elem.machineNumber === machineID
|
||||||
}) !== undefined;
|
}) !== 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) {
|
renderItem(item: Object, section: Object, data: Object) {
|
||||||
return (
|
return (
|
||||||
<ListItem
|
<ListItem
|
||||||
|
@ -226,6 +289,12 @@ export default class ProxiwashScreen extends React.Component<Props, State> {
|
||||||
</ListItem>);
|
</ListItem>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {
|
render() {
|
||||||
const nav = this.props.navigation;
|
const nav = this.props.navigation;
|
||||||
const data = [
|
const data = [
|
||||||
|
|
|
@ -33,12 +33,20 @@ type State = {
|
||||||
proxiwashNotifPickerSelected: string,
|
proxiwashNotifPickerSelected: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class defining the Settings screen. This screen shows controls to modify app preferences.
|
||||||
|
*/
|
||||||
export default class SettingsScreen extends React.Component<Props, State> {
|
export default class SettingsScreen extends React.Component<Props, State> {
|
||||||
state = {
|
state = {
|
||||||
nightMode: ThemeManager.getInstance().getNightMode(),
|
nightMode: ThemeManager.getInstance().getNightMode(),
|
||||||
proxiwashNotifPickerSelected: "5"
|
proxiwashNotifPickerSelected: "5"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets data from preferences before rendering components
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
async componentWillMount() {
|
async componentWillMount() {
|
||||||
let val = await AsyncStorage.getItem(proxiwashNotifKey);
|
let val = await AsyncStorage.getItem(proxiwashNotifKey);
|
||||||
if (val === null)
|
if (val === null)
|
||||||
|
@ -48,7 +56,11 @@ export default class SettingsScreen extends React.Component<Props, State> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the value for the proxiwash reminder notification time
|
||||||
|
*
|
||||||
|
* @param value The value to store
|
||||||
|
*/
|
||||||
onProxiwashNotifPickerValueChange(value: string) {
|
onProxiwashNotifPickerValueChange(value: string) {
|
||||||
AsyncStorage.setItem(proxiwashNotifKey, value);
|
AsyncStorage.setItem(proxiwashNotifKey, value);
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -56,6 +68,11 @@ export default class SettingsScreen extends React.Component<Props, State> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a picker allowing the user to select the proxiwash reminder notification time
|
||||||
|
*
|
||||||
|
* @returns {React.Node}
|
||||||
|
*/
|
||||||
getProxiwashNotifPicker() {
|
getProxiwashNotifPicker() {
|
||||||
return (
|
return (
|
||||||
<Picker
|
<Picker
|
||||||
|
@ -77,6 +94,9 @@ export default class SettingsScreen extends React.Component<Props, State> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle night mode and save it to preferences
|
||||||
|
*/
|
||||||
toggleNightMode() {
|
toggleNightMode() {
|
||||||
ThemeManager.getInstance().setNightMode(!this.state.nightMode);
|
ThemeManager.getInstance().setNightMode(!this.state.nightMode);
|
||||||
this.setState({nightMode: !this.state.nightMode});
|
this.setState({nightMode: !this.state.nightMode});
|
||||||
|
@ -84,6 +104,9 @@ export default class SettingsScreen extends React.Component<Props, State> {
|
||||||
this.resetStack();
|
this.resetStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset react navigation stack to allow for a theme reset
|
||||||
|
*/
|
||||||
resetStack() {
|
resetStack() {
|
||||||
const resetAction = StackActions.reset({
|
const resetAction = StackActions.reset({
|
||||||
index: 0,
|
index: 0,
|
||||||
|
@ -94,7 +117,16 @@ export default class SettingsScreen extends React.Component<Props, State> {
|
||||||
this.props.navigation.navigate('Settings');
|
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 (
|
return (
|
||||||
<ListItem
|
<ListItem
|
||||||
button
|
button
|
||||||
|
@ -106,7 +138,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
|
||||||
</Left>
|
</Left>
|
||||||
<Body>
|
<Body>
|
||||||
<Text>
|
<Text>
|
||||||
{text}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
<Text note>
|
<Text note>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
|
@ -120,7 +152,16 @@ export default class SettingsScreen extends React.Component<Props, State> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (
|
return (
|
||||||
<ListItem
|
<ListItem
|
||||||
thumbnail
|
thumbnail
|
||||||
|
@ -130,7 +171,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
|
||||||
</Left>
|
</Left>
|
||||||
<Body>
|
<Body>
|
||||||
<Text>
|
<Text>
|
||||||
{text}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
<Text note>
|
<Text note>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
|
|
Loading…
Reference in a new issue