forked from vergnet/application-amicale
		
	Improve Settings screen components to match linter
This commit is contained in:
		
							parent
							
								
									0a64f5fcd7
								
							
						
					
					
						commit
						a3299c19f7
					
				
					 3 changed files with 425 additions and 337 deletions
				
			
		|  | @ -131,7 +131,11 @@ export default class AsyncStorageManager { | |||
|    * @param key | ||||
|    * @param value | ||||
|    */ | ||||
|   static set(key: string, value: number | string | boolean | {...} | []) { | ||||
|   static set( | ||||
|     key: string, | ||||
|     // eslint-disable-next-line flowtype/no-weak-types
 | ||||
|     value: number | string | boolean | {...} | Array<any>, | ||||
|   ) { | ||||
|     AsyncStorageManager.getInstance().setPreference(key, value); | ||||
|   } | ||||
| 
 | ||||
|  | @ -142,7 +146,8 @@ export default class AsyncStorageManager { | |||
|    * @returns {string} | ||||
|    */ | ||||
|   static getString(key: string): string { | ||||
|     return AsyncStorageManager.getInstance().getPreference(key); | ||||
|     const value = AsyncStorageManager.getInstance().getPreference(key); | ||||
|     return value != null ? value : ''; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -207,7 +212,11 @@ export default class AsyncStorageManager { | |||
|    * @param key | ||||
|    * @param value | ||||
|    */ | ||||
|   setPreference(key: string, value: number | string | boolean | {...} | []) { | ||||
|   setPreference( | ||||
|     key: string, | ||||
|     // eslint-disable-next-line flowtype/no-weak-types
 | ||||
|     value: number | string | boolean | {...} | Array<any>, | ||||
|   ) { | ||||
|     if (AsyncStorageManager.PREFERENCES[key] != null) { | ||||
|       let convertedValue; | ||||
|       if (typeof value === 'string') convertedValue = value; | ||||
|  |  | |||
|  | @ -1,116 +1,139 @@ | |||
| // @flow
 | ||||
| 
 | ||||
| import * as React from 'react'; | ||||
| import {Avatar, Button, Card, Paragraph, withTheme} from "react-native-paper"; | ||||
| import i18n from "i18n-js"; | ||||
| import {Linking} from "react-native"; | ||||
| import type {CustomTheme} from "../../managers/ThemeManager"; | ||||
| import CollapsibleScrollView from "../../components/Collapsible/CollapsibleScrollView"; | ||||
| import {Avatar, Button, Card, Paragraph, withTheme} from 'react-native-paper'; | ||||
| import i18n from 'i18n-js'; | ||||
| import {Linking} from 'react-native'; | ||||
| import type {CustomThemeType} from '../../managers/ThemeManager'; | ||||
| import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrollView'; | ||||
| 
 | ||||
| type Props = { | ||||
|     theme: CustomTheme | ||||
| type PropsType = { | ||||
|   theme: CustomThemeType, | ||||
| }; | ||||
| 
 | ||||
| const links = { | ||||
|     bugsMail: `mailto:app@amicale-insat.fr?subject=[BUG] Application CAMPUS
 | ||||
|   bugsMail: `mailto:app@amicale-insat.fr?subject=[BUG] Application CAMPUS
 | ||||
| &body=Coucou Arnaud ça bug c'est nul,\n\n | ||||
| Informations sur ton système si tu sais (iOS ou Android, modèle du tel, version):\n\n\n | ||||
| Nature du problème :\n\n\n | ||||
| Étapes pour reproduire ce pb :\n\n\n\n | ||||
| Stp corrige le pb, bien cordialement.`,
 | ||||
|     bugsGit: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/issues/new', | ||||
|     facebook: "https://www.facebook.com/campus.insat", | ||||
|     feedbackMail: `mailto:app@amicale-insat.fr?subject=[FEEDBACK] Application CAMPUS
 | ||||
|   bugsGit: | ||||
|     'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/issues/new', | ||||
|   facebook: 'https://www.facebook.com/campus.insat', | ||||
|   feedbackMail: `mailto:app@amicale-insat.fr?subject=[FEEDBACK] Application CAMPUS
 | ||||
| &body=Coucou Arnaud j'ai du feedback\n\n\n\nBien cordialement.`,
 | ||||
|     feedbackGit: "https://git.etud.insa-toulouse.fr/vergnet/application-amicale/issues/new", | ||||
| } | ||||
|   feedbackGit: | ||||
|     'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/issues/new', | ||||
| }; | ||||
| 
 | ||||
| class FeedbackScreen extends React.Component<Props> { | ||||
| class FeedbackScreen extends React.Component<PropsType> { | ||||
|   /** | ||||
|    * Gets link buttons | ||||
|    * | ||||
|    * @param isBug True if buttons should redirect to bug report methods | ||||
|    * @returns {*} | ||||
|    */ | ||||
|   static getButtons(isBug: boolean): React.Node { | ||||
|     return ( | ||||
|       <Card.Actions | ||||
|         style={{ | ||||
|           flex: 1, | ||||
|           flexWrap: 'wrap', | ||||
|         }}> | ||||
|         <Button | ||||
|           icon="email" | ||||
|           mode="contained" | ||||
|           style={{ | ||||
|             marginLeft: 'auto', | ||||
|             marginTop: 5, | ||||
|           }} | ||||
|           onPress={() => { | ||||
|             Linking.openURL(isBug ? links.bugsMail : links.feedbackMail); | ||||
|           }}> | ||||
|           MAIL | ||||
|         </Button> | ||||
|         <Button | ||||
|           icon="git" | ||||
|           mode="contained" | ||||
|           color="#609927" | ||||
|           style={{ | ||||
|             marginLeft: 'auto', | ||||
|             marginTop: 5, | ||||
|           }} | ||||
|           onPress={() => { | ||||
|             Linking.openURL(isBug ? links.bugsGit : links.feedbackGit); | ||||
|           }}> | ||||
|           GITEA | ||||
|         </Button> | ||||
|         <Button | ||||
|           icon="facebook" | ||||
|           mode="contained" | ||||
|           color="#2e88fe" | ||||
|           style={{ | ||||
|             marginLeft: 'auto', | ||||
|             marginTop: 5, | ||||
|           }} | ||||
|           onPress={() => { | ||||
|             Linking.openURL(links.facebook); | ||||
|           }}> | ||||
|           Facebook | ||||
|         </Button> | ||||
|       </Card.Actions> | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets link buttons | ||||
|      * | ||||
|      * @param isBug True if buttons should redirect to bug report methods | ||||
|      * @returns {*} | ||||
|      */ | ||||
|     getButtons(isBug: boolean) { | ||||
|         return ( | ||||
|             <Card.Actions style={{ | ||||
|                 flex: 1, | ||||
|                 flexWrap: 'wrap', | ||||
|             }}> | ||||
|                 <Button | ||||
|                     icon="email" | ||||
|                     mode={"contained"} | ||||
|                     style={{ | ||||
|                         marginLeft: 'auto', | ||||
|                         marginTop: 5, | ||||
|                     }} | ||||
|                     onPress={() => Linking.openURL(isBug ? links.bugsMail : links.feedbackMail)}> | ||||
|                     MAIL | ||||
|                 </Button> | ||||
|                 <Button | ||||
|                     icon="git" | ||||
|                     mode={"contained"} | ||||
|                     color={"#609927"} | ||||
|                     style={{ | ||||
|                         marginLeft: 'auto', | ||||
|                         marginTop: 5, | ||||
|                     }} | ||||
|                     onPress={() => Linking.openURL(isBug ? links.bugsGit : links.feedbackGit)}> | ||||
|                     GITEA | ||||
|                 </Button> | ||||
|                 <Button | ||||
|                     icon="facebook" | ||||
|                     mode={"contained"} | ||||
|                     color={"#2e88fe"} | ||||
|                     style={{ | ||||
|                         marginLeft: 'auto', | ||||
|                         marginTop: 5, | ||||
|                     }} | ||||
|                     onPress={() => Linking.openURL(links.facebook)}> | ||||
|                     Facebook | ||||
|                 </Button> | ||||
|             </Card.Actions> | ||||
|         ); | ||||
|     } | ||||
|   render(): React.Node { | ||||
|     const {theme} = this.props; | ||||
|     return ( | ||||
|       <CollapsibleScrollView style={{padding: 5}}> | ||||
|         <Card> | ||||
|           <Card.Title | ||||
|             title={i18n.t('screens.feedback.bugs')} | ||||
|             subtitle={i18n.t('screens.feedback.bugsSubtitle')} | ||||
|             left={({ | ||||
|               size, | ||||
|               color, | ||||
|             }: { | ||||
|               size: number, | ||||
|               color: number, | ||||
|             }): React.Node => ( | ||||
|               <Avatar.Icon size={size} color={color} icon="bug" /> | ||||
|             )} | ||||
|           /> | ||||
|           <Card.Content> | ||||
|             <Paragraph>{i18n.t('screens.feedback.bugsDescription')}</Paragraph> | ||||
|             <Paragraph style={{color: theme.colors.primary}}> | ||||
|               {i18n.t('screens.feedback.contactMeans')} | ||||
|             </Paragraph> | ||||
|           </Card.Content> | ||||
|           {FeedbackScreen.getButtons(true)} | ||||
|         </Card> | ||||
| 
 | ||||
|     render() { | ||||
|         return ( | ||||
|             <CollapsibleScrollView style={{padding: 5}}> | ||||
|                 <Card> | ||||
|                     <Card.Title | ||||
|                         title={i18n.t('screens.feedback.bugs')} | ||||
|                         subtitle={i18n.t('screens.feedback.bugsSubtitle')} | ||||
|                         left={(props) => <Avatar.Icon {...props} icon="bug"/>} | ||||
|                     /> | ||||
|                     <Card.Content> | ||||
|                         <Paragraph> | ||||
|                             {i18n.t('screens.feedback.bugsDescription')} | ||||
|                         </Paragraph> | ||||
|                         <Paragraph style={{color: this.props.theme.colors.primary}}> | ||||
|                             {i18n.t('screens.feedback.contactMeans')} | ||||
|                         </Paragraph> | ||||
|                     </Card.Content> | ||||
|                     {this.getButtons(true)} | ||||
|                 </Card> | ||||
| 
 | ||||
|                 <Card style={{marginTop: 20, marginBottom: 10}}> | ||||
|                     <Card.Title | ||||
|                         title={i18n.t('screens.feedback.title')} | ||||
|                         subtitle={i18n.t('screens.feedback.feedbackSubtitle')} | ||||
|                         left={(props) => <Avatar.Icon {...props} icon="comment"/>} | ||||
|                     /> | ||||
|                     <Card.Content> | ||||
|                         <Paragraph> | ||||
|                             {i18n.t('screens.feedback.feedbackDescription')} | ||||
|                         </Paragraph> | ||||
|                     </Card.Content> | ||||
|                     {this.getButtons(false)} | ||||
|                 </Card> | ||||
|             </CollapsibleScrollView> | ||||
|         ); | ||||
|     } | ||||
|         <Card style={{marginTop: 20, marginBottom: 10}}> | ||||
|           <Card.Title | ||||
|             title={i18n.t('screens.feedback.title')} | ||||
|             subtitle={i18n.t('screens.feedback.feedbackSubtitle')} | ||||
|             left={({ | ||||
|               size, | ||||
|               color, | ||||
|             }: { | ||||
|               size: number, | ||||
|               color: number, | ||||
|             }): React.Node => ( | ||||
|               <Avatar.Icon size={size} color={color} icon="comment" /> | ||||
|             )} | ||||
|           /> | ||||
|           <Card.Content> | ||||
|             <Paragraph> | ||||
|               {i18n.t('screens.feedback.feedbackDescription')} | ||||
|             </Paragraph> | ||||
|           </Card.Content> | ||||
|           {FeedbackScreen.getButtons(false)} | ||||
|         </Card> | ||||
|       </CollapsibleScrollView> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export default withTheme(FeedbackScreen); | ||||
|  |  | |||
|  | @ -1,267 +1,323 @@ | |||
| // @flow
 | ||||
| 
 | ||||
| import * as React from 'react'; | ||||
| import {View} from "react-native"; | ||||
| import type {CustomTheme} from "../../../managers/ThemeManager"; | ||||
| import ThemeManager from '../../../managers/ThemeManager'; | ||||
| import i18n from "i18n-js"; | ||||
| import AsyncStorageManager from "../../../managers/AsyncStorageManager"; | ||||
| import {View} from 'react-native'; | ||||
| import i18n from 'i18n-js'; | ||||
| import {Card, List, Switch, ToggleButton, withTheme} from 'react-native-paper'; | ||||
| import {Appearance} from "react-native-appearance"; | ||||
| import CustomSlider from "../../../components/Overrides/CustomSlider"; | ||||
| import {StackNavigationProp} from "@react-navigation/stack"; | ||||
| import CollapsibleScrollView from "../../../components/Collapsible/CollapsibleScrollView"; | ||||
| import {Appearance} from 'react-native-appearance'; | ||||
| import {StackNavigationProp} from '@react-navigation/stack'; | ||||
| import type {CustomThemeType} from '../../../managers/ThemeManager'; | ||||
| import ThemeManager from '../../../managers/ThemeManager'; | ||||
| import AsyncStorageManager from '../../../managers/AsyncStorageManager'; | ||||
| import CustomSlider from '../../../components/Overrides/CustomSlider'; | ||||
| import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView'; | ||||
| 
 | ||||
| type Props = { | ||||
|     navigation: StackNavigationProp, | ||||
|     theme: CustomTheme, | ||||
| type PropsType = { | ||||
|   navigation: StackNavigationProp, | ||||
|   theme: CustomThemeType, | ||||
| }; | ||||
| 
 | ||||
| type State = { | ||||
|     nightMode: boolean, | ||||
|     nightModeFollowSystem: boolean, | ||||
|     notificationReminderSelected: number, | ||||
|     startScreenPickerSelected: string, | ||||
|     isDebugUnlocked: boolean, | ||||
| type StateType = { | ||||
|   nightMode: boolean, | ||||
|   nightModeFollowSystem: boolean, | ||||
|   startScreenPickerSelected: string, | ||||
|   isDebugUnlocked: boolean, | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Class defining the Settings screen. This screen shows controls to modify app preferences. | ||||
|  */ | ||||
| class SettingsScreen extends React.Component<Props, State> { | ||||
| class SettingsScreen extends React.Component<PropsType, StateType> { | ||||
|   savedNotificationReminder: number; | ||||
| 
 | ||||
|     savedNotificationReminder: number; | ||||
|   /** | ||||
|    * Loads user preferences into state | ||||
|    */ | ||||
|   constructor() { | ||||
|     super(); | ||||
|     const notifReminder = AsyncStorageManager.getString( | ||||
|       AsyncStorageManager.PREFERENCES.proxiwashNotifications.key, | ||||
|     ); | ||||
|     this.savedNotificationReminder = parseInt(notifReminder, 10); | ||||
|     if (Number.isNaN(this.savedNotificationReminder)) | ||||
|       this.savedNotificationReminder = 0; | ||||
| 
 | ||||
|     /** | ||||
|      * Loads user preferences into state | ||||
|      */ | ||||
|     constructor() { | ||||
|         super(); | ||||
|         let notifReminder = AsyncStorageManager.getString(AsyncStorageManager.PREFERENCES.proxiwashNotifications.key); | ||||
|         this.savedNotificationReminder = parseInt(notifReminder); | ||||
|         if (isNaN(this.savedNotificationReminder)) | ||||
|             this.savedNotificationReminder = 0; | ||||
| 
 | ||||
|         this.state = { | ||||
|             nightMode: ThemeManager.getNightMode(), | ||||
|             nightModeFollowSystem: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.nightModeFollowSystem.key) | ||||
|                 && Appearance.getColorScheme() !== 'no-preference', | ||||
|             notificationReminderSelected: this.savedNotificationReminder, | ||||
|             startScreenPickerSelected: AsyncStorageManager.getString(AsyncStorageManager.PREFERENCES.defaultStartScreen.key), | ||||
|             isDebugUnlocked: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.debugUnlocked.key) | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Unlocks debug mode and saves its state to user preferences | ||||
|      */ | ||||
|     unlockDebugMode = () => { | ||||
|         this.setState({isDebugUnlocked: true}); | ||||
|         AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.debugUnlocked.key, true); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Saves the value for the proxiwash reminder notification time | ||||
|      * | ||||
|      * @param value The value to store | ||||
|      */ | ||||
|     onProxiwashNotifPickerValueChange = (value: number) => { | ||||
|         this.setState({notificationReminderSelected: value}); | ||||
|         AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.proxiwashNotifications.key, value); | ||||
|     this.state = { | ||||
|       nightMode: ThemeManager.getNightMode(), | ||||
|       nightModeFollowSystem: | ||||
|         AsyncStorageManager.getBool( | ||||
|           AsyncStorageManager.PREFERENCES.nightModeFollowSystem.key, | ||||
|         ) && Appearance.getColorScheme() !== 'no-preference', | ||||
|       startScreenPickerSelected: AsyncStorageManager.getString( | ||||
|         AsyncStorageManager.PREFERENCES.defaultStartScreen.key, | ||||
|       ), | ||||
|       isDebugUnlocked: AsyncStorageManager.getBool( | ||||
|         AsyncStorageManager.PREFERENCES.debugUnlocked.key, | ||||
|       ), | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|     /** | ||||
|      * Saves the value for the proxiwash reminder notification time | ||||
|      * | ||||
|      * @param value The value to store | ||||
|      */ | ||||
|     onStartScreenPickerValueChange = (value: string) => { | ||||
|         if (value != null) { | ||||
|             this.setState({startScreenPickerSelected: value}); | ||||
|             AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.defaultStartScreen.key, value); | ||||
|         } | ||||
|     }; | ||||
|   /** | ||||
|    * Saves the value for the proxiwash reminder notification time | ||||
|    * | ||||
|    * @param value The value to store | ||||
|    */ | ||||
|   onProxiwashNotifPickerValueChange = (value: number) => { | ||||
|     AsyncStorageManager.set( | ||||
|       AsyncStorageManager.PREFERENCES.proxiwashNotifications.key, | ||||
|       value, | ||||
|     ); | ||||
|   }; | ||||
| 
 | ||||
|     /** | ||||
|      * Returns a picker allowing the user to select the proxiwash reminder notification time | ||||
|      * | ||||
|      * @returns {React.Node} | ||||
|      */ | ||||
|     getProxiwashNotifPicker() { | ||||
|         return ( | ||||
|             <CustomSlider | ||||
|                 style={{flex: 1, marginHorizontal: 10, height: 50}} | ||||
|                 minimumValue={0} | ||||
|                 maximumValue={10} | ||||
|                 step={1} | ||||
|                 value={this.savedNotificationReminder} | ||||
|                 onValueChange={this.onProxiwashNotifPickerValueChange} | ||||
|                 thumbTintColor={this.props.theme.colors.primary} | ||||
|                 minimumTrackTintColor={this.props.theme.colors.primary} | ||||
|             /> | ||||
|         ); | ||||
|   /** | ||||
|    * Saves the value for the proxiwash reminder notification time | ||||
|    * | ||||
|    * @param value The value to store | ||||
|    */ | ||||
|   onStartScreenPickerValueChange = (value: string) => { | ||||
|     if (value != null) { | ||||
|       this.setState({startScreenPickerSelected: value}); | ||||
|       AsyncStorageManager.set( | ||||
|         AsyncStorageManager.PREFERENCES.defaultStartScreen.key, | ||||
|         value, | ||||
|       ); | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|     /** | ||||
|      * Returns a picker allowing the user to select the start screen | ||||
|      * | ||||
|      * @returns {React.Node} | ||||
|      */ | ||||
|     getStartScreenPicker() { | ||||
|         return ( | ||||
|             <ToggleButton.Row | ||||
|                 onValueChange={this.onStartScreenPickerValueChange} | ||||
|                 value={this.state.startScreenPickerSelected} | ||||
|                 style={{marginLeft: 'auto', marginRight: 'auto'}} | ||||
|             > | ||||
|                 <ToggleButton icon="account-circle" value="services"/> | ||||
|                 <ToggleButton icon="tshirt-crew" value="proxiwash"/> | ||||
|                 <ToggleButton icon="triangle" value="home"/> | ||||
|                 <ToggleButton icon="calendar-range" value="planning"/> | ||||
|                 <ToggleButton icon="clock" value="planex"/> | ||||
|             </ToggleButton.Row> | ||||
|         ); | ||||
|   /** | ||||
|    * Returns a picker allowing the user to select the proxiwash reminder notification time | ||||
|    * | ||||
|    * @returns {React.Node} | ||||
|    */ | ||||
|   getProxiwashNotifPicker(): React.Node { | ||||
|     const {theme} = this.props; | ||||
|     return ( | ||||
|       <CustomSlider | ||||
|         style={{flex: 1, marginHorizontal: 10, height: 50}} | ||||
|         minimumValue={0} | ||||
|         maximumValue={10} | ||||
|         step={1} | ||||
|         value={this.savedNotificationReminder} | ||||
|         onValueChange={this.onProxiwashNotifPickerValueChange} | ||||
|         thumbTintColor={theme.colors.primary} | ||||
|         minimumTrackTintColor={theme.colors.primary} | ||||
|       /> | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Returns a picker allowing the user to select the start screen | ||||
|    * | ||||
|    * @returns {React.Node} | ||||
|    */ | ||||
|   getStartScreenPicker(): React.Node { | ||||
|     const {startScreenPickerSelected} = this.state; | ||||
|     return ( | ||||
|       <ToggleButton.Row | ||||
|         onValueChange={this.onStartScreenPickerValueChange} | ||||
|         value={startScreenPickerSelected} | ||||
|         style={{marginLeft: 'auto', marginRight: 'auto'}}> | ||||
|         <ToggleButton icon="account-circle" value="services" /> | ||||
|         <ToggleButton icon="tshirt-crew" value="proxiwash" /> | ||||
|         <ToggleButton icon="triangle" value="home" /> | ||||
|         <ToggleButton icon="calendar-range" value="planning" /> | ||||
|         <ToggleButton icon="clock" value="planex" /> | ||||
|       </ToggleButton.Row> | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Toggles night mode and saves it to preferences | ||||
|    */ | ||||
|   onToggleNightMode = () => { | ||||
|     const {nightMode} = this.state; | ||||
|     ThemeManager.getInstance().setNightMode(!nightMode); | ||||
|     this.setState({nightMode: !nightMode}); | ||||
|   }; | ||||
| 
 | ||||
|   onToggleNightModeFollowSystem = () => { | ||||
|     const {nightModeFollowSystem} = this.state; | ||||
|     const value = !nightModeFollowSystem; | ||||
|     this.setState({nightModeFollowSystem: value}); | ||||
|     AsyncStorageManager.set( | ||||
|       AsyncStorageManager.PREFERENCES.nightModeFollowSystem.key, | ||||
|       value, | ||||
|     ); | ||||
|     if (value) { | ||||
|       const nightMode = Appearance.getColorScheme() === 'dark'; | ||||
|       ThemeManager.getInstance().setNightMode(nightMode); | ||||
|       this.setState({nightMode}); | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|     /** | ||||
|      * Toggles night mode and saves it to preferences | ||||
|      */ | ||||
|     onToggleNightMode = () => { | ||||
|         ThemeManager.getInstance().setNightMode(!this.state.nightMode); | ||||
|         this.setState({nightMode: !this.state.nightMode}); | ||||
|     }; | ||||
|   /** | ||||
|    * Gets 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 | ||||
|    * @param state The current state of the switch | ||||
|    * @returns {React.Node} | ||||
|    */ | ||||
|   static getToggleItem( | ||||
|     onPressCallback: () => void, | ||||
|     icon: string, | ||||
|     title: string, | ||||
|     subtitle: string, | ||||
|     state: boolean, | ||||
|   ): React.Node { | ||||
|     return ( | ||||
|       <List.Item | ||||
|         title={title} | ||||
|         description={subtitle} | ||||
|         left={({size, color}: {size: number, color: number}): React.Node => ( | ||||
|           <List.Icon size={size} color={color} icon={icon} /> | ||||
|         )} | ||||
|         right={(): React.Node => ( | ||||
|           <Switch value={state} onValueChange={onPressCallback} /> | ||||
|         )} | ||||
|       /> | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|     onToggleNightModeFollowSystem = () => { | ||||
|         const value = !this.state.nightModeFollowSystem; | ||||
|         this.setState({nightModeFollowSystem: value}); | ||||
|         AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.nightModeFollowSystem.key, value); | ||||
|         if (value) { | ||||
|             const nightMode = Appearance.getColorScheme() === 'dark'; | ||||
|             ThemeManager.getInstance().setNightMode(nightMode); | ||||
|             this.setState({nightMode: nightMode}); | ||||
|         } | ||||
|     }; | ||||
|   getNavigateItem( | ||||
|     route: string, | ||||
|     icon: string, | ||||
|     title: string, | ||||
|     subtitle: string, | ||||
|     onLongPress?: () => void, | ||||
|   ): React.Node { | ||||
|     const {navigation} = this.props; | ||||
|     return ( | ||||
|       <List.Item | ||||
|         title={title} | ||||
|         description={subtitle} | ||||
|         onPress={() => { | ||||
|           navigation.navigate(route); | ||||
|         }} | ||||
|         left={({size, color}: {size: number, color: number}): React.Node => ( | ||||
|           <List.Icon size={size} color={color} icon={icon} /> | ||||
|         )} | ||||
|         right={({size, color}: {size: number, color: number}): React.Node => ( | ||||
|           <List.Icon size={size} color={color} icon="chevron-right" /> | ||||
|         )} | ||||
|         onLongPress={onLongPress} | ||||
|       /> | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets 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 | ||||
|      * @param state The current state of the switch | ||||
|      * @returns {React.Node} | ||||
|      */ | ||||
|     getToggleItem(onPressCallback: Function, icon: string, title: string, subtitle: string, state: boolean) { | ||||
|         return ( | ||||
|   /** | ||||
|    * Unlocks debug mode and saves its state to user preferences | ||||
|    */ | ||||
|   unlockDebugMode = () => { | ||||
|     this.setState({isDebugUnlocked: true}); | ||||
|     AsyncStorageManager.set( | ||||
|       AsyncStorageManager.PREFERENCES.debugUnlocked.key, | ||||
|       true, | ||||
|     ); | ||||
|   }; | ||||
| 
 | ||||
|   render(): React.Node { | ||||
|     const {nightModeFollowSystem, nightMode, isDebugUnlocked} = this.state; | ||||
|     return ( | ||||
|       <CollapsibleScrollView> | ||||
|         <Card style={{margin: 5}}> | ||||
|           <Card.Title title={i18n.t('screens.settings.generalCard')} /> | ||||
|           <List.Section> | ||||
|             {Appearance.getColorScheme() !== 'no-preference' | ||||
|               ? SettingsScreen.getToggleItem( | ||||
|                   this.onToggleNightModeFollowSystem, | ||||
|                   'theme-light-dark', | ||||
|                   i18n.t('screens.settings.nightModeAuto'), | ||||
|                   i18n.t('screens.settings.nightModeAutoSub'), | ||||
|                   nightModeFollowSystem, | ||||
|                 ) | ||||
|               : null} | ||||
|             {Appearance.getColorScheme() === 'no-preference' || | ||||
|             !nightModeFollowSystem | ||||
|               ? SettingsScreen.getToggleItem( | ||||
|                   this.onToggleNightMode, | ||||
|                   'theme-light-dark', | ||||
|                   i18n.t('screens.settings.nightMode'), | ||||
|                   nightMode | ||||
|                     ? i18n.t('screens.settings.nightModeSubOn') | ||||
|                     : i18n.t('screens.settings.nightModeSubOff'), | ||||
|                   nightMode, | ||||
|                 ) | ||||
|               : null} | ||||
|             <List.Item | ||||
|                 title={title} | ||||
|                 description={subtitle} | ||||
|                 left={props => <List.Icon {...props} icon={icon}/>} | ||||
|                 right={() => | ||||
|                     <Switch | ||||
|                         value={state} | ||||
|                         onValueChange={onPressCallback} | ||||
|                     />} | ||||
|               title={i18n.t('screens.settings.startScreen')} | ||||
|               description={i18n.t('screens.settings.startScreenSub')} | ||||
|               left={({ | ||||
|                 size, | ||||
|                 color, | ||||
|               }: { | ||||
|                 size: number, | ||||
|                 color: number, | ||||
|               }): React.Node => ( | ||||
|                 <List.Icon size={size} color={color} icon="power" /> | ||||
|               )} | ||||
|             /> | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     getNavigateItem(route: string, icon: string, title: string, subtitle: string, onLongPress?: () => void) { | ||||
|         return ( | ||||
|             {this.getStartScreenPicker()} | ||||
|             {this.getNavigateItem( | ||||
|               'dashboard-edit', | ||||
|               'view-dashboard', | ||||
|               i18n.t('screens.settings.dashboard'), | ||||
|               i18n.t('screens.settings.dashboardSub'), | ||||
|             )} | ||||
|           </List.Section> | ||||
|         </Card> | ||||
|         <Card style={{margin: 5}}> | ||||
|           <Card.Title title="Proxiwash" /> | ||||
|           <List.Section> | ||||
|             <List.Item | ||||
|                 title={title} | ||||
|                 description={subtitle} | ||||
|                 onPress={() => this.props.navigation.navigate(route)} | ||||
|                 left={props => <List.Icon {...props} icon={icon}/>} | ||||
|                 right={props => <List.Icon {...props} icon={"chevron-right"}/>} | ||||
|                 onLongPress={onLongPress} | ||||
|               title={i18n.t('screens.settings.proxiwashNotifReminder')} | ||||
|               description={i18n.t('screens.settings.proxiwashNotifReminderSub')} | ||||
|               left={({ | ||||
|                 size, | ||||
|                 color, | ||||
|               }: { | ||||
|                 size: number, | ||||
|                 color: number, | ||||
|               }): React.Node => ( | ||||
|                 <List.Icon size={size} color={color} icon="washing-machine" /> | ||||
|               )} | ||||
|             /> | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     render() { | ||||
|         return ( | ||||
|             <CollapsibleScrollView> | ||||
|                 <Card style={{margin: 5}}> | ||||
|                     <Card.Title title={i18n.t('screens.settings.generalCard')}/> | ||||
|                     <List.Section> | ||||
|                         {Appearance.getColorScheme() !== 'no-preference' ? this.getToggleItem( | ||||
|                             this.onToggleNightModeFollowSystem, | ||||
|                             'theme-light-dark', | ||||
|                             i18n.t('screens.settings.nightModeAuto'), | ||||
|                             i18n.t('screens.settings.nightModeAutoSub'), | ||||
|                             this.state.nightModeFollowSystem | ||||
|                         ) : null} | ||||
|                         { | ||||
|                             Appearance.getColorScheme() === 'no-preference' || !this.state.nightModeFollowSystem ? | ||||
|                                 this.getToggleItem( | ||||
|                                     this.onToggleNightMode, | ||||
|                                     'theme-light-dark', | ||||
|                                     i18n.t('screens.settings.nightMode'), | ||||
|                                     this.state.nightMode ? | ||||
|                                         i18n.t('screens.settings.nightModeSubOn') : | ||||
|                                         i18n.t('screens.settings.nightModeSubOff'), | ||||
|                                     this.state.nightMode | ||||
|                                 ) : null | ||||
|                         } | ||||
|                         <List.Item | ||||
|                             title={i18n.t('screens.settings.startScreen')} | ||||
|                             description={i18n.t('screens.settings.startScreenSub')} | ||||
|                             left={props => <List.Icon {...props} icon="power"/>} | ||||
|                         /> | ||||
|                         {this.getStartScreenPicker()} | ||||
|                         {this.getNavigateItem( | ||||
|                             "dashboard-edit", | ||||
|                             "view-dashboard", | ||||
|                             i18n.t('screens.settings.dashboard'), | ||||
|                             i18n.t('screens.settings.dashboardSub') | ||||
|                         )} | ||||
|                     </List.Section> | ||||
|                 </Card> | ||||
|                 <Card style={{margin: 5}}> | ||||
|                     <Card.Title title="Proxiwash"/> | ||||
|                     <List.Section> | ||||
|                         <List.Item | ||||
|                             title={i18n.t('screens.settings.proxiwashNotifReminder')} | ||||
|                             description={i18n.t('screens.settings.proxiwashNotifReminderSub')} | ||||
|                             left={props => <List.Icon {...props} icon="washing-machine"/>} | ||||
|                             opened={true} | ||||
|                         /> | ||||
|                         <View style={{marginLeft: 30}}> | ||||
|                             {this.getProxiwashNotifPicker()} | ||||
|                         </View> | ||||
|                     </List.Section> | ||||
|                 </Card> | ||||
|                 <Card style={{margin: 5}}> | ||||
|                     <Card.Title title={i18n.t('screens.settings.information')}/> | ||||
|                     <List.Section> | ||||
|                         {this.state.isDebugUnlocked | ||||
|                             ? this.getNavigateItem( | ||||
|                                 "debug", | ||||
|                                 "bug-check", | ||||
|                                 i18n.t('screens.debug.title'), | ||||
|                                 "" | ||||
|                             ) | ||||
|                             : null} | ||||
|                         {this.getNavigateItem( | ||||
|                             "about", | ||||
|                             "information", | ||||
|                             i18n.t('screens.about.title'), | ||||
|                             i18n.t('screens.about.buttonDesc'), | ||||
|                             this.unlockDebugMode, | ||||
|                         )} | ||||
|                         {this.getNavigateItem( | ||||
|                             "feedback", | ||||
|                             "comment-quote", | ||||
|                             i18n.t('screens.feedback.homeButtonTitle'), | ||||
|                             i18n.t('screens.feedback.homeButtonSubtitle'), | ||||
|                         )} | ||||
|                     </List.Section> | ||||
|                 </Card> | ||||
|             </CollapsibleScrollView> | ||||
|         ); | ||||
|     } | ||||
|             <View style={{marginLeft: 30}}> | ||||
|               {this.getProxiwashNotifPicker()} | ||||
|             </View> | ||||
|           </List.Section> | ||||
|         </Card> | ||||
|         <Card style={{margin: 5}}> | ||||
|           <Card.Title title={i18n.t('screens.settings.information')} /> | ||||
|           <List.Section> | ||||
|             {isDebugUnlocked | ||||
|               ? this.getNavigateItem( | ||||
|                   'debug', | ||||
|                   'bug-check', | ||||
|                   i18n.t('screens.debug.title'), | ||||
|                   '', | ||||
|                 ) | ||||
|               : null} | ||||
|             {this.getNavigateItem( | ||||
|               'about', | ||||
|               'information', | ||||
|               i18n.t('screens.about.title'), | ||||
|               i18n.t('screens.about.buttonDesc'), | ||||
|               this.unlockDebugMode, | ||||
|             )} | ||||
|             {this.getNavigateItem( | ||||
|               'feedback', | ||||
|               'comment-quote', | ||||
|               i18n.t('screens.feedback.homeButtonTitle'), | ||||
|               i18n.t('screens.feedback.homeButtonSubtitle'), | ||||
|             )} | ||||
|           </List.Section> | ||||
|         </Card> | ||||
|       </CollapsibleScrollView> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export default withTheme(SettingsScreen); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue