forked from vergnet/application-amicale
Improved documentation
This commit is contained in:
parent
a533f48a12
commit
4cdfc607e6
21 changed files with 380 additions and 156 deletions
|
@ -2,8 +2,14 @@ import * as React from 'react';
|
||||||
import {withTheme} from 'react-native-paper';
|
import {withTheme} from 'react-native-paper';
|
||||||
import {Agenda} from "react-native-calendars";
|
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) {
|
function CustomAgenda(props) {
|
||||||
const { colors } = props.theme;
|
const {colors} = props.theme;
|
||||||
return (
|
return (
|
||||||
<Agenda
|
<Agenda
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
@ -9,47 +9,24 @@ import i18n from 'i18n-js';
|
||||||
import AppIntroSlider from "react-native-app-intro-slider";
|
import AppIntroSlider from "react-native-app-intro-slider";
|
||||||
import Update from "../constants/Update";
|
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 = {
|
type Props = {
|
||||||
onDone: Function,
|
onDone: Function,
|
||||||
isUpdate: boolean,
|
isUpdate: boolean,
|
||||||
isAprilFools: boolean,
|
isAprilFools: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to create intro slides
|
||||||
|
*/
|
||||||
export default class CustomIntroSlider extends React.Component<Props> {
|
export default class CustomIntroSlider extends React.Component<Props> {
|
||||||
|
|
||||||
introSlides: Array<Object>;
|
introSlides: Array<Object>;
|
||||||
updateSlides: Array<Object>;
|
updateSlides: Array<Object>;
|
||||||
aprilFoolsSlides: Array<Object>;
|
aprilFoolsSlides: Array<Object>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates intro slides
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.introSlides = [
|
this.introSlides = [
|
||||||
|
@ -126,8 +103,9 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render item to be used for the intro introSlides
|
* 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) {
|
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,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
|
@ -4,8 +4,14 @@ import * as React from 'react';
|
||||||
import {withTheme} from 'react-native-paper';
|
import {withTheme} from 'react-native-paper';
|
||||||
import {Modalize} from "react-native-modalize";
|
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) {
|
function CustomModal(props) {
|
||||||
const { colors } = props.theme;
|
const {colors} = props.theme;
|
||||||
return (
|
return (
|
||||||
<Modalize
|
<Modalize
|
||||||
ref={props.onRef}
|
ref={props.onRef}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {ActivityIndicator, Subheading, withTheme} from 'react-native-paper';
|
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";
|
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 (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<View style={{
|
<View style={styles.iconContainer}>
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
width: '100%',
|
|
||||||
height: 100,
|
|
||||||
marginBottom: 20
|
|
||||||
}}>
|
|
||||||
{props.refreshing ?
|
{props.refreshing ?
|
||||||
<ActivityIndicator
|
<ActivityIndicator
|
||||||
animating={true}
|
animating={true}
|
||||||
|
@ -27,9 +27,7 @@ function EmptyWebSectionListItem(props) {
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Subheading style={{
|
<Subheading style={{
|
||||||
textAlign: 'center',
|
...styles.subheading,
|
||||||
marginRight: 20,
|
|
||||||
marginLeft: 20,
|
|
||||||
color: colors.textDisabled
|
color: colors.textDisabled
|
||||||
}}>
|
}}>
|
||||||
{props.text}
|
{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);
|
export default withTheme(EmptyWebSectionListItem);
|
||||||
|
|
|
@ -2,7 +2,14 @@
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Avatar, Card, withTheme} from 'react-native-paper';
|
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) {
|
function EventDashBoardItem(props) {
|
||||||
const {colors} = props.theme;
|
const {colors} = props.theme;
|
||||||
const iconColor = props.isAvailable ?
|
const iconColor = props.isAvailable ?
|
||||||
|
@ -13,13 +20,7 @@ function EventDashBoardItem(props) {
|
||||||
colors.textDisabled;
|
colors.textDisabled;
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
style={{
|
style={styles.card}
|
||||||
width: 'auto',
|
|
||||||
marginLeft: 10,
|
|
||||||
marginRight: 10,
|
|
||||||
marginTop: 10,
|
|
||||||
overflow: 'hidden',
|
|
||||||
}}
|
|
||||||
onPress={props.clickAction}>
|
onPress={props.clickAction}>
|
||||||
|
|
||||||
<Card.Title
|
<Card.Title
|
||||||
|
@ -32,7 +33,7 @@ function EventDashBoardItem(props) {
|
||||||
icon={props.icon}
|
icon={props.icon}
|
||||||
color={iconColor}
|
color={iconColor}
|
||||||
size={60}
|
size={60}
|
||||||
style={{backgroundColor: 'transparent'}}/>}
|
style={styles.avatar}/>}
|
||||||
/>
|
/>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
{props.children}
|
{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);
|
export default withTheme(EventDashBoardItem);
|
||||||
|
|
|
@ -6,6 +6,11 @@ import i18n from "i18n-js";
|
||||||
|
|
||||||
const ICON_AMICALE = require('../assets/amicale.png');
|
const ICON_AMICALE = require('../assets/amicale.png');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the amicale INSAT logo
|
||||||
|
*
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
function getAvatar() {
|
function getAvatar() {
|
||||||
return (
|
return (
|
||||||
<Avatar.Image size={48} source={ICON_AMICALE}
|
<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) {
|
function FeedItem(props) {
|
||||||
const {colors} = props.theme;
|
const {colors} = props.theme;
|
||||||
return (
|
return (
|
||||||
|
@ -39,7 +50,9 @@ function FeedItem(props) {
|
||||||
<Button
|
<Button
|
||||||
color={'#57aeff'}
|
color={'#57aeff'}
|
||||||
onPress={props.onOutLinkPress}
|
onPress={props.onOutLinkPress}
|
||||||
icon={'facebook'}>{i18n.t('homeScreen.dashboard.seeMore')}</Button>
|
icon={'facebook'}>
|
||||||
|
{i18n.t('homeScreen.dashboard.seeMore')}
|
||||||
|
</Button>
|
||||||
</Card.Actions>
|
</Card.Actions>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {IconButton, withTheme} from 'react-native-paper';
|
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) {
|
function HeaderButton(props) {
|
||||||
const { colors } = props.theme;
|
const {colors} = props.theme;
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={props.icon}
|
icon={props.icon}
|
||||||
|
|
|
@ -1,25 +1,33 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {View} from "react-native";
|
import {StyleSheet, View} from "react-native";
|
||||||
import HTML from "react-native-render-html";
|
import HTML from "react-native-render-html";
|
||||||
import i18n from "i18n-js";
|
import i18n from "i18n-js";
|
||||||
import {Avatar, Button, Card, withTheme} from 'react-native-paper';
|
import {Avatar, Button, Card, withTheme} from 'react-native-paper';
|
||||||
import PlanningEventManager from "../utils/PlanningEventManager";
|
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) {
|
function PreviewEventDashboardItem(props) {
|
||||||
const {colors} = props.theme;
|
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) {
|
if (props.event !== undefined && props.event !== null) {
|
||||||
const hasImage = props.event['logo'] !== '' && props.event['logo'] !== null;
|
const hasImage = props.event['logo'] !== '' && props.event['logo'] !== null;
|
||||||
const getImage = () => <Avatar.Image
|
const getImage = () => <Avatar.Image
|
||||||
source={{uri: props.event['logo']}}
|
source={{uri: props.event['logo']}}
|
||||||
size={50}
|
size={50}
|
||||||
style={{backgroundColor: 'transparent'}}/>;
|
style={styles.avatar}/>;
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
style={{marginBottom: 10}}
|
style={styles.card}
|
||||||
onPress={props.clickAction}
|
onPress={props.clickAction}
|
||||||
elevation={3}
|
elevation={3}
|
||||||
>
|
>
|
||||||
|
@ -34,10 +42,7 @@ function PreviewEventDashboardItem(props) {
|
||||||
subtitle={PlanningEventManager.getFormattedEventTime(props.event['date_begin'], props.event['date_end'])}
|
subtitle={PlanningEventManager.getFormattedEventTime(props.event['date_begin'], props.event['date_end'])}
|
||||||
/>}
|
/>}
|
||||||
{!isEmpty ?
|
{!isEmpty ?
|
||||||
<Card.Content style={{
|
<Card.Content style={styles.content}>
|
||||||
maxHeight: 150,
|
|
||||||
overflow: 'hidden',
|
|
||||||
}}>
|
|
||||||
<HTML html={"<div>" + props.event['description'] + "</div>"}
|
<HTML html={"<div>" + props.event['description'] + "</div>"}
|
||||||
tagsStyles={{
|
tagsStyles={{
|
||||||
p: {color: colors.text,},
|
p: {color: colors.text,},
|
||||||
|
@ -46,11 +51,7 @@ function PreviewEventDashboardItem(props) {
|
||||||
|
|
||||||
</Card.Content> : null}
|
</Card.Content> : null}
|
||||||
|
|
||||||
<Card.Actions style={{
|
<Card.Actions style={styles.actions}>
|
||||||
marginLeft: 'auto',
|
|
||||||
marginTop: 'auto',
|
|
||||||
flexDirection: 'row'
|
|
||||||
}}>
|
|
||||||
<Button
|
<Button
|
||||||
icon={'chevron-right'}
|
icon={'chevron-right'}
|
||||||
>
|
>
|
||||||
|
@ -63,4 +64,22 @@ function PreviewEventDashboardItem(props) {
|
||||||
return <View/>
|
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);
|
export default withTheme(PreviewEventDashboardItem);
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Avatar, Card, Text, withTheme} from 'react-native-paper';
|
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";
|
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) {
|
function ProxiwashListItem(props) {
|
||||||
const {colors} = props.theme;
|
const {colors} = props.theme;
|
||||||
let stateColors = {};
|
let stateColors = {};
|
||||||
|
@ -17,13 +23,13 @@ function ProxiwashListItem(props) {
|
||||||
icon={'bell-ring'}
|
icon={'bell-ring'}
|
||||||
size={45}
|
size={45}
|
||||||
color={colors.primary}
|
color={colors.primary}
|
||||||
style={{backgroundColor: 'transparent'}}
|
style={styles.icon}
|
||||||
/> :
|
/> :
|
||||||
<Avatar.Icon
|
<Avatar.Icon
|
||||||
icon={props.isDryer ? 'tumble-dryer' : 'washing-machine'}
|
icon={props.isDryer ? 'tumble-dryer' : 'washing-machine'}
|
||||||
color={colors.text}
|
color={colors.text}
|
||||||
size={40}
|
size={40}
|
||||||
style={{backgroundColor: 'transparent'}}
|
style={styles.icon}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
@ -35,37 +41,26 @@ function ProxiwashListItem(props) {
|
||||||
>
|
>
|
||||||
{ProxiwashConstants.machineStates[props.state] === ProxiwashConstants.machineStates["EN COURS"] ?
|
{ProxiwashConstants.machineStates[props.state] === ProxiwashConstants.machineStates["EN COURS"] ?
|
||||||
<Card style={{
|
<Card style={{
|
||||||
height: '100%',
|
...styles.backgroundCard,
|
||||||
position: 'absolute',
|
|
||||||
left: 0,
|
|
||||||
width: '100%',
|
|
||||||
backgroundColor: colors.proxiwashRunningBgColor,
|
backgroundColor: colors.proxiwashRunningBgColor,
|
||||||
elevation: 0
|
|
||||||
}}/> : null
|
}}/> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
<Card style={{
|
<Card style={{
|
||||||
height: '100%',
|
...styles.progressionCard,
|
||||||
position: 'absolute',
|
|
||||||
left: 0,
|
|
||||||
width: props.progress,
|
width: props.progress,
|
||||||
backgroundColor: stateColors[ProxiwashConstants.machineStates[props.state]],
|
backgroundColor: stateColors[ProxiwashConstants.machineStates[props.state]],
|
||||||
elevation: 0
|
|
||||||
}}/>
|
}}/>
|
||||||
<Card.Title
|
<Card.Title
|
||||||
title={props.title}
|
title={props.title}
|
||||||
titleStyle={{fontSize: 17}}
|
titleStyle={{fontSize: 17}}
|
||||||
subtitle={props.description}
|
subtitle={props.description}
|
||||||
style={{
|
style={styles.title}
|
||||||
backgroundColor: 'transparent',
|
|
||||||
height: 64
|
|
||||||
}}
|
|
||||||
left={() => icon}
|
left={() => icon}
|
||||||
right={() => (
|
right={() => (
|
||||||
<View style={{flexDirection: 'row'}}>
|
<View style={{flexDirection: 'row'}}>
|
||||||
<View style={{
|
<View style={{justifyContent: 'center'}}>
|
||||||
justifyContent: 'center',
|
|
||||||
}}>
|
|
||||||
<Text style={
|
<Text style={
|
||||||
ProxiwashConstants.machineStates[props.state] === ProxiwashConstants.machineStates.TERMINE ?
|
ProxiwashConstants.machineStates[props.state] === ProxiwashConstants.machineStates.TERMINE ?
|
||||||
{fontWeight: 'bold',} : {}}
|
{fontWeight: 'bold',} : {}}
|
||||||
|
@ -73,12 +68,11 @@ function ProxiwashListItem(props) {
|
||||||
{props.statusText}
|
{props.statusText}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Avatar.Icon
|
<Avatar.Icon
|
||||||
icon={props.statusIcon}
|
icon={props.statusIcon}
|
||||||
color={colors.text}
|
color={colors.text}
|
||||||
size={30}
|
size={30}
|
||||||
style={{backgroundColor: 'transparent'}}
|
style={styles.icon}
|
||||||
/>
|
/>
|
||||||
</View>)}
|
</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);
|
export default withTheme(ProxiwashListItem);
|
||||||
|
|
|
@ -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.
|
* 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.
|
* 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 = {
|
static defaultProps = {
|
||||||
updateData: null,
|
updateData: null,
|
||||||
|
|
|
@ -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> {
|
export default class SideBar extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ export default class SideBar extends React.PureComponent<Props, State> {
|
||||||
getRenderItem: Function;
|
getRenderItem: Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the datasets
|
* Generate the dataset
|
||||||
*
|
*
|
||||||
* @param props
|
* @param props
|
||||||
*/
|
*/
|
||||||
|
@ -123,6 +123,12 @@ export default class SideBar extends React.PureComponent<Props, State> {
|
||||||
this.getRenderItem = this.getRenderItem.bind(this);
|
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) {
|
onListItemPress(item: Object) {
|
||||||
if (item.link === undefined)
|
if (item.link === undefined)
|
||||||
this.props.navigation.navigate(item.route);
|
this.props.navigation.navigate(item.route);
|
||||||
|
@ -130,12 +136,22 @@ export default class SideBar extends React.PureComponent<Props, State> {
|
||||||
WebBrowser.openBrowserAsync(item.link);
|
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;
|
return item.route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the render item for the given list item
|
||||||
|
*
|
||||||
|
* @param item The item to render
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
getRenderItem({item}: Object) {
|
getRenderItem({item}: Object) {
|
||||||
const onListItemPress = this.onListItemPress.bind(this, item);
|
const onListItemPress = this.onListItemPress.bind(this, item);
|
||||||
if (item.icon !== undefined) {
|
if (item.icon !== undefined) {
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { withTheme } from 'react-native-paper';
|
import {withTheme} from 'react-native-paper';
|
||||||
import {DrawerItem} from "@react-navigation/drawer";
|
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) {
|
function SidebarDivider(props) {
|
||||||
const { colors } = props.theme;
|
const {colors} = props.theme;
|
||||||
return (
|
return (
|
||||||
<DrawerItem
|
<DrawerItem
|
||||||
label={props.title}
|
label={props.title}
|
||||||
|
|
|
@ -3,6 +3,12 @@ import {withTheme} from 'react-native-paper';
|
||||||
import {DrawerItem} from "@react-navigation/drawer";
|
import {DrawerItem} from "@react-navigation/drawer";
|
||||||
import {MaterialCommunityIcons} from "@expo/vector-icons";
|
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) {
|
function SidebarItem(props) {
|
||||||
const {colors} = props.theme;
|
const {colors} = props.theme;
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,6 +2,12 @@ import * as React from 'react';
|
||||||
import {Badge, IconButton, withTheme} from 'react-native-paper';
|
import {Badge, IconButton, withTheme} from 'react-native-paper';
|
||||||
import {View} from "react-native";
|
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) {
|
function SquareDashboardItem(props) {
|
||||||
const {colors} = props.theme;
|
const {colors} = props.theme;
|
||||||
return (
|
return (
|
||||||
|
@ -9,9 +15,9 @@ function SquareDashboardItem(props) {
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={props.icon}
|
icon={props.icon}
|
||||||
color={
|
color={
|
||||||
props.isAvailable ?
|
props.isAvailable
|
||||||
props.color :
|
? props.color
|
||||||
colors.textDisabled
|
: colors.textDisabled
|
||||||
}
|
}
|
||||||
size={35}
|
size={35}
|
||||||
onPress={props.clickAction}
|
onPress={props.clickAction}
|
||||||
|
@ -23,9 +29,10 @@ function SquareDashboardItem(props) {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 5,
|
top: 5,
|
||||||
right: 5
|
right: 5
|
||||||
}}>{props.badgeNumber}</Badge> : null
|
}}>
|
||||||
|
{props.badgeNumber}
|
||||||
|
</Badge> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* 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.
|
* 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
|
* Allows to detect when the screen is focused
|
||||||
*/
|
*/
|
||||||
componentDidMount() {
|
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() {
|
onScreenFocus() {
|
||||||
if (this.props.refreshOnFocus && this.lastRefresh !== undefined)
|
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() {
|
onScreenBlur() {
|
||||||
clearInterval(this.refreshInterval);
|
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) {
|
onFetchSuccess(fetchedData: Object) {
|
||||||
this.setState({
|
this.setState({
|
||||||
fetchedData: fetchedData,
|
fetchedData: fetchedData,
|
||||||
|
@ -112,6 +120,10 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
||||||
this.lastRefresh = new Date();
|
this.lastRefresh = new Date();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback used when fetch encountered an error.
|
||||||
|
* It will reset the displayed data and show an error.
|
||||||
|
*/
|
||||||
onFetchError() {
|
onFetchError() {
|
||||||
this.setState({
|
this.setState({
|
||||||
fetchedData: {},
|
fetchedData: {},
|
||||||
|
@ -119,12 +131,10 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
||||||
firstLoading: false
|
firstLoading: false
|
||||||
});
|
});
|
||||||
this.showSnackBar();
|
this.showSnackBar();
|
||||||
// this.webDataManager.showUpdateToast(this.props.updateErrorText);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh data and show a toast if any error occurred
|
* Refreshes data and shows an animations while doing it
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
onRefresh() {
|
onRefresh() {
|
||||||
let canRefresh;
|
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) {
|
getEmptySectionHeader({section}: Object) {
|
||||||
return <View/>;
|
return <View/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an empty render item
|
||||||
|
*
|
||||||
|
* @param item The data to display
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
getEmptyRenderItem({item}: Object) {
|
getEmptyRenderItem({item}: Object) {
|
||||||
return (
|
return (
|
||||||
<EmptyWebSectionListItem
|
<EmptyWebSectionListItem
|
||||||
|
@ -154,6 +176,11 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an empty dataset
|
||||||
|
*
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
createEmptyDataset() {
|
createEmptyDataset() {
|
||||||
return [
|
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
|
return item.text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the error popup
|
||||||
|
*/
|
||||||
showSnackBar() {
|
showSnackBar() {
|
||||||
this.setState({snackbarVisible: true})
|
this.setState({snackbarVisible: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides the error popup
|
||||||
|
*/
|
||||||
hideSnackBar() {
|
hideSnackBar() {
|
||||||
this.setState({snackbarVisible: false})
|
this.setState({snackbarVisible: false})
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,6 @@ class WebViewScreen extends React.PureComponent<Props> {
|
||||||
|
|
||||||
onRefreshClicked: Function;
|
onRefreshClicked: Function;
|
||||||
onWebviewRef: Function;
|
onWebviewRef: Function;
|
||||||
onGoBackWebview: Function;
|
|
||||||
onGoForwardWebview: Function;
|
|
||||||
getRenderLoading: Function;
|
getRenderLoading: Function;
|
||||||
|
|
||||||
colors: Object;
|
colors: Object;
|
||||||
|
@ -44,12 +42,13 @@ class WebViewScreen extends React.PureComponent<Props> {
|
||||||
super(props);
|
super(props);
|
||||||
this.onRefreshClicked = this.onRefreshClicked.bind(this);
|
this.onRefreshClicked = this.onRefreshClicked.bind(this);
|
||||||
this.onWebviewRef = this.onWebviewRef.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.getRenderLoading = this.getRenderLoading.bind(this);
|
||||||
this.colors = props.theme.colors;
|
this.colors = props.theme.colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates refresh button after mounting
|
||||||
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const rightButton = this.getRefreshButton.bind(this);
|
const rightButton = this.getRefreshButton.bind(this);
|
||||||
this.props.navigation.setOptions({
|
this.props.navigation.setOptions({
|
||||||
|
@ -57,42 +56,37 @@ class WebViewScreen extends React.PureComponent<Props> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getHeaderButton(clickAction: Function, icon: string) {
|
/**
|
||||||
return (
|
* Gets a header refresh button
|
||||||
<HeaderButton icon={icon} onPress={clickAction}/>
|
*
|
||||||
);
|
* @return {*}
|
||||||
}
|
*/
|
||||||
|
|
||||||
getRefreshButton() {
|
getRefreshButton() {
|
||||||
return (
|
return <HeaderButton icon={'refresh'} onPress={this.onRefreshClicked}/>
|
||||||
<View style={{
|
|
||||||
flexDirection: 'row',
|
|
||||||
marginRight: 10
|
|
||||||
}}>
|
|
||||||
{this.getHeaderButton(this.onRefreshClicked, 'refresh')}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to use when refresh button is clicked. Reloads the webview.
|
||||||
|
*/
|
||||||
onRefreshClicked() {
|
onRefreshClicked() {
|
||||||
if (this.webviewRef !== null)
|
if (this.webviewRef !== null)
|
||||||
this.webviewRef.reload();
|
this.webviewRef.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
onGoBackWebview() {
|
/**
|
||||||
if (this.webviewRef !== null)
|
* Callback used when receiving the webview ref. Stores the ref for later use
|
||||||
this.webviewRef.goBack();
|
*
|
||||||
}
|
* @param ref
|
||||||
|
*/
|
||||||
onGoForwardWebview() {
|
|
||||||
if (this.webviewRef !== null)
|
|
||||||
this.webviewRef.goForward();
|
|
||||||
}
|
|
||||||
|
|
||||||
onWebviewRef(ref: Object) {
|
onWebviewRef(ref: Object) {
|
||||||
this.webviewRef = ref
|
this.webviewRef = ref
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the loading indicator
|
||||||
|
*
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
getRenderLoading() {
|
getRenderLoading() {
|
||||||
return (
|
return (
|
||||||
<View style={{
|
<View style={{
|
||||||
|
@ -115,7 +109,6 @@ class WebViewScreen extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// console.log("rendering WebViewScreen");
|
|
||||||
return (
|
return (
|
||||||
<WebView
|
<WebView
|
||||||
ref={this.onWebviewRef}
|
ref={this.onWebviewRef}
|
||||||
|
|
|
@ -1,12 +1,31 @@
|
||||||
import i18n from "i18n-js";
|
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 {
|
export default class Update {
|
||||||
|
|
||||||
|
// Increment the number to show the update slide
|
||||||
static number = 5;
|
static number = 5;
|
||||||
|
// Change the icon to be displayed on the update slide
|
||||||
static icon = 'surround-sound-2-0';
|
static icon = 'surround-sound-2-0';
|
||||||
|
|
||||||
static instance: Update | null = null;
|
static instance: Update | null = null;
|
||||||
|
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init translations
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.title = i18n.t('intro.updateSlide.title');
|
this.title = i18n.t('intro.updateSlide.title');
|
||||||
this.description = i18n.t('intro.updateSlide.text');
|
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
|
* Get this class instance or create one if none is found
|
||||||
|
*
|
||||||
* @returns {Update}
|
* @returns {Update}
|
||||||
*/
|
*/
|
||||||
static getInstance(): Update {
|
static getInstance(): Update {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import {AsyncStorage} from "react-native";
|
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.
|
* Preferences are fetched at the start of the app and saved in an instance object.
|
||||||
* This allows for a synchronous access to saved data.
|
* 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
|
* Get this class instance or create one if none is found
|
||||||
* @returns {ThemeManager}
|
* @returns {AsyncStorageManager}
|
||||||
*/
|
*/
|
||||||
static getInstance(): AsyncStorageManager {
|
static getInstance(): AsyncStorageManager {
|
||||||
return AsyncStorageManager.instance === null ?
|
return AsyncStorageManager.instance === null ?
|
||||||
|
@ -113,7 +113,7 @@ export default class AsyncStorageManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the value associated to the given key to preferences.
|
* 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 key
|
||||||
* @param val
|
* @param val
|
||||||
|
|
|
@ -2,10 +2,13 @@
|
||||||
|
|
||||||
import i18n from 'i18n-js';
|
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 {
|
export default class DateManager {
|
||||||
static instance: DateManager | null = null;
|
static instance: DateManager | null = null;
|
||||||
|
|
||||||
// Hard code strings as toLocaleDateString does not work on current android JS engine
|
|
||||||
daysOfWeek = [];
|
daysOfWeek = [];
|
||||||
monthsOfYear = [];
|
monthsOfYear = [];
|
||||||
|
|
||||||
|
@ -42,6 +45,12 @@ export default class DateManager {
|
||||||
DateManager.instance;
|
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) {
|
getTranslatedDate(dateString: string) {
|
||||||
let dateArray = dateString.split('-');
|
let dateArray = dateString.split('-');
|
||||||
let date = new Date();
|
let date = new Date();
|
||||||
|
|
|
@ -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) {
|
static getMachineNotificationWatchlist(callback: Function) {
|
||||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
||||||
if (token !== '') {
|
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 machineID The machine ID
|
||||||
* @param isEnabled
|
* @param isEnabled True to enable notifications, false to disable
|
||||||
*/
|
*/
|
||||||
static setupMachineNotification(machineID: string, isEnabled: boolean) {
|
static setupMachineNotification(machineID: string, isEnabled: boolean) {
|
||||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
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
|
* Sends the selected reminder time for notifications to the server
|
||||||
* @param time
|
*
|
||||||
|
* @param time The reminder time to use
|
||||||
*/
|
*/
|
||||||
static setMachineReminderNotificationTime(time: number) {
|
static setMachineReminderNotificationTime(time: number) {
|
||||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
||||||
|
|
|
@ -19,7 +19,12 @@ export default class ThemeManager {
|
||||||
this.updateThemeCallback = null;
|
this.updateThemeCallback = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getWhiteTheme() {
|
/**
|
||||||
|
* Gets the light theme
|
||||||
|
*
|
||||||
|
* @return {Object} Object containing theme variables
|
||||||
|
* */
|
||||||
|
static getWhiteTheme(): Object {
|
||||||
return {
|
return {
|
||||||
...DefaultTheme,
|
...DefaultTheme,
|
||||||
colors: {
|
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 {
|
return {
|
||||||
...DarkTheme,
|
...DarkTheme,
|
||||||
colors: {
|
colors: {
|
||||||
|
@ -124,6 +134,7 @@ export default class ThemeManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get this class instance or create one if none is found
|
* Get this class instance or create one if none is found
|
||||||
|
*
|
||||||
* @returns {ThemeManager}
|
* @returns {ThemeManager}
|
||||||
*/
|
*/
|
||||||
static getInstance(): 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
|
* @returns {boolean} Night mode state
|
||||||
*/
|
*/
|
||||||
static getNightMode(): boolean {
|
static getNightMode(): boolean {
|
||||||
|
@ -143,8 +158,9 @@ export default class ThemeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current theme based on night mode
|
* Get the current theme based on night mode and events
|
||||||
* @returns {Object}
|
*
|
||||||
|
* @returns {Object} The current theme
|
||||||
*/
|
*/
|
||||||
static getCurrentTheme(): Object {
|
static getCurrentTheme(): Object {
|
||||||
if (AprilFoolsManager.getInstance().isAprilFoolsEnabled())
|
if (AprilFoolsManager.getInstance().isAprilFoolsEnabled())
|
||||||
|
@ -153,6 +169,11 @@ export default class ThemeManager {
|
||||||
return ThemeManager.getBaseTheme()
|
return ThemeManager.getBaseTheme()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the theme based on night mode
|
||||||
|
*
|
||||||
|
* @return {Object} The theme
|
||||||
|
*/
|
||||||
static getBaseTheme() {
|
static getBaseTheme() {
|
||||||
if (ThemeManager.getNightMode())
|
if (ThemeManager.getNightMode())
|
||||||
return ThemeManager.getDarkTheme();
|
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
|
* @param callback Function to call after theme change
|
||||||
*/
|
*/
|
||||||
setUpdateThemeCallback(callback: ?Function) {
|
setUpdateThemeCallback(callback: ?Function) {
|
||||||
|
@ -171,7 +193,7 @@ export default class ThemeManager {
|
||||||
/**
|
/**
|
||||||
* Set night mode and save it to preferences
|
* 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) {
|
setNightMode(isNightMode: boolean) {
|
||||||
let nightModeKey = AsyncStorageManager.getInstance().preferences.nightMode.key;
|
let nightModeKey = AsyncStorageManager.getInstance().preferences.nightMode.key;
|
||||||
|
|
Loading…
Reference in a new issue