Follow system night mode when available

This commit is contained in:
keplyx 2020-03-08 19:50:17 +01:00
parent 992e2d8286
commit 9ec986574f
8 changed files with 57 additions and 17 deletions

8
App.js
View file

@ -42,6 +42,7 @@ export default class App extends React.Component<Props, State> {
super(); super();
LocaleManager.initTranslations(); LocaleManager.initTranslations();
this.onIntroDone = this.onIntroDone.bind(this); this.onIntroDone = this.onIntroDone.bind(this);
SplashScreen.preventAutoHide();
} }
/** /**
@ -84,13 +85,9 @@ export default class App extends React.Component<Props, State> {
async loadAssetsAsync() { async loadAssetsAsync() {
// Wait for custom fonts to be loaded before showing the app // Wait for custom fonts to be loaded before showing the app
// console.log("loading Fonts");
SplashScreen.preventAutoHide();
// console.log("loading preferences");
await AsyncStorageManager.getInstance().loadPreferences(); await AsyncStorageManager.getInstance().loadPreferences();
ThemeManager.getInstance().setUpdateThemeCallback(() => this.updateTheme()); ThemeManager.getInstance().setUpdateThemeCallback(() => this.updateTheme());
// console.log("loading Expo token"); // await NotificationsManager.initExpoToken();
await NotificationsManager.initExpoToken();
this.onLoadFinished(); this.onLoadFinished();
} }
@ -122,7 +119,6 @@ export default class App extends React.Component<Props, State> {
isAprilFools={this.state.showAprilFools && !this.state.showIntro} isAprilFools={this.state.showAprilFools && !this.state.showIntro}
/>; />;
} else { } else {
return ( return (
<PaperProvider theme={this.state.currentTheme}> <PaperProvider theme={this.state.currentTheme}>
<NavigationContainer theme={this.state.currentTheme}> <NavigationContainer theme={this.state.currentTheme}>

View file

@ -13,6 +13,7 @@
"version": "1.5.2", "version": "1.5.2",
"orientation": "portrait", "orientation": "portrait",
"primaryColor": "#be1522", "primaryColor": "#be1522",
"userInterfaceStyle": "automatic",
"icon": "./assets/android.icon.png", "icon": "./assets/android.icon.png",
"splash": { "splash": {
"backgroundColor": "#be1522", "backgroundColor": "#be1522",

View file

@ -34,7 +34,8 @@
"react-native-render-html": "^4.1.2", "react-native-render-html": "^4.1.2",
"react-native-safe-area-context": "0.6.0", "react-native-safe-area-context": "0.6.0",
"react-native-screens": "2.0.0-alpha.12", "react-native-screens": "2.0.0-alpha.12",
"react-native-webview": "7.4.3" "react-native-webview": "7.4.3",
"react-native-appearance": "~0.3.1"
}, },
"devDependencies": { "devDependencies": {
"babel-preset-expo": "^8.0.0" "babel-preset-expo": "^8.0.0"

View file

@ -7,6 +7,7 @@ import i18n from "i18n-js";
import AsyncStorageManager from "../utils/AsyncStorageManager"; import AsyncStorageManager from "../utils/AsyncStorageManager";
import NotificationsManager from "../utils/NotificationsManager"; import NotificationsManager from "../utils/NotificationsManager";
import {Card, List, Switch, ToggleButton} from 'react-native-paper'; import {Card, List, Switch, ToggleButton} from 'react-native-paper';
import {Appearance} from "react-native-appearance";
type Props = { type Props = {
navigation: Object, navigation: Object,
@ -14,6 +15,7 @@ type Props = {
type State = { type State = {
nightMode: boolean, nightMode: boolean,
nightModeFollowSystem: boolean,
proxiwashNotifPickerSelected: string, proxiwashNotifPickerSelected: string,
startScreenPickerSelected: string, startScreenPickerSelected: string,
}; };
@ -24,6 +26,8 @@ type State = {
export default class SettingsScreen extends React.Component<Props, State> { export default class SettingsScreen extends React.Component<Props, State> {
state = { state = {
nightMode: ThemeManager.getNightMode(), nightMode: ThemeManager.getNightMode(),
nightModeFollowSystem: AsyncStorageManager.getInstance().preferences.nightModeFollowSystem.current === '1' &&
Appearance.getColorScheme() !== 'no-preference',
proxiwashNotifPickerSelected: AsyncStorageManager.getInstance().preferences.proxiwashNotifications.current, proxiwashNotifPickerSelected: AsyncStorageManager.getInstance().preferences.proxiwashNotifications.current,
startScreenPickerSelected: AsyncStorageManager.getInstance().preferences.defaultStartScreen.current, startScreenPickerSelected: AsyncStorageManager.getInstance().preferences.defaultStartScreen.current,
}; };
@ -31,12 +35,14 @@ export default class SettingsScreen extends React.Component<Props, State> {
onProxiwashNotifPickerValueChange: Function; onProxiwashNotifPickerValueChange: Function;
onStartScreenPickerValueChange: Function; onStartScreenPickerValueChange: Function;
onToggleNightMode: Function; onToggleNightMode: Function;
onToggleNightModeFollowSystem: Function;
constructor() { constructor() {
super(); super();
this.onProxiwashNotifPickerValueChange = this.onProxiwashNotifPickerValueChange.bind(this); this.onProxiwashNotifPickerValueChange = this.onProxiwashNotifPickerValueChange.bind(this);
this.onStartScreenPickerValueChange = this.onStartScreenPickerValueChange.bind(this); this.onStartScreenPickerValueChange = this.onStartScreenPickerValueChange.bind(this);
this.onToggleNightMode = this.onToggleNightMode.bind(this); this.onToggleNightMode = this.onToggleNightMode.bind(this);
this.onToggleNightModeFollowSystem = this.onToggleNightModeFollowSystem.bind(this);
} }
/** /**
@ -119,6 +125,18 @@ export default class SettingsScreen extends React.Component<Props, State> {
this.setState({nightMode: !this.state.nightMode}); this.setState({nightMode: !this.state.nightMode});
} }
onToggleNightModeFollowSystem() {
const value = !this.state.nightModeFollowSystem;
this.setState({nightModeFollowSystem: value});
let key = AsyncStorageManager.getInstance().preferences.nightModeFollowSystem.key;
AsyncStorageManager.getInstance().savePref(key, value ? '1' : '0');
if (value) {
const nightMode = Appearance.getColorScheme() === 'dark';
ThemeManager.getInstance().setNightMode(nightMode);
this.setState({nightMode: nightMode});
}
}
/** /**
* Get a list item using a checkbox control * Get a list item using a checkbox control
* *
@ -128,7 +146,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
* @param subtitle The text to display as this list item subtitle * @param subtitle The text to display as this list item subtitle
* @returns {React.Node} * @returns {React.Node}
*/ */
getToggleItem(onPressCallback: Function, icon: string, title: string, subtitle: string) { getToggleItem(onPressCallback: Function, icon: string, title: string, subtitle: string, state: boolean) {
return ( return (
<List.Item <List.Item
title={title} title={title}
@ -136,7 +154,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
left={props => <List.Icon {...props} icon={icon}/>} left={props => <List.Icon {...props} icon={icon}/>}
right={props => right={props =>
<Switch <Switch
value={this.state.nightMode} value={state}
onValueChange={onPressCallback} onValueChange={onPressCallback}
/>} />}
/> />
@ -149,14 +167,27 @@ export default class SettingsScreen extends React.Component<Props, State> {
<Card style={{margin: 5}}> <Card style={{margin: 5}}>
<Card.Title title={i18n.t('settingsScreen.generalCard')}/> <Card.Title title={i18n.t('settingsScreen.generalCard')}/>
<List.Section> <List.Section>
{this.getToggleItem( {Appearance.getColorScheme() !== 'no-preference' ? this.getToggleItem(
this.onToggleNightModeFollowSystem,
'theme-light-dark',
i18n.t('settingsScreen.nightModeAuto'),
this.state.nightMode ?
i18n.t('settingsScreen.nightModeSubOn') :
i18n.t('settingsScreen.nightModeSubOff'),
this.state.nightModeFollowSystem
) : null}
{
Appearance.getColorScheme() === 'no-preference' || !this.state.nightModeFollowSystem ?
this.getToggleItem(
this.onToggleNightMode, this.onToggleNightMode,
'theme-light-dark', 'theme-light-dark',
i18n.t('settingsScreen.nightMode'), i18n.t('settingsScreen.nightMode'),
this.state.nightMode ? this.state.nightMode ?
i18n.t('settingsScreen.nightModeSubOn') : i18n.t('settingsScreen.nightModeSubOn') :
i18n.t('settingsScreen.nightModeSubOff') i18n.t('settingsScreen.nightModeSubOff'),
)} this.state.nightMode
) : null
}
<List.Accordion <List.Accordion
title={i18n.t('settingsScreen.startScreen')} title={i18n.t('settingsScreen.startScreen')}
description={i18n.t('settingsScreen.startScreenSub')} description={i18n.t('settingsScreen.startScreenSub')}

View file

@ -67,6 +67,7 @@
"nightMode": "Night Mode", "nightMode": "Night Mode",
"nightModeSubOn": "Your eyes are at peace", "nightModeSubOn": "Your eyes are at peace",
"nightModeSubOff": "Your eyes are burning", "nightModeSubOff": "Your eyes are burning",
"nightModeAuto": "Follow system dark mode",
"startScreen": "Start Screen", "startScreen": "Start Screen",
"startScreenSub": "Select which screen to start the app on", "startScreenSub": "Select which screen to start the app on",
"proxiwashNotifReminder": "Machine running reminder", "proxiwashNotifReminder": "Machine running reminder",

View file

@ -65,8 +65,9 @@
"settingsScreen": { "settingsScreen": {
"generalCard": "Général", "generalCard": "Général",
"nightMode": "Mode Nuit", "nightMode": "Mode Nuit",
"nightModeSubOn": "Vos yeux brulent", "nightModeSubOn": "Vos yeux vous remercient",
"nightModeSubOff": "Vos yeux vous remercient", "nightModeSubOff": "Vos yeux brulent",
"nightModeAuto": "Mode nuit système",
"startScreen": "Écran de démarrage", "startScreen": "Écran de démarrage",
"startScreenSub": "Choisissez l'écran utilisé au démarrage", "startScreenSub": "Choisissez l'écran utilisé au démarrage",
"proxiwashNotifReminder": "Rappel de machine en cours", "proxiwashNotifReminder": "Rappel de machine en cours",

View file

@ -44,6 +44,11 @@ export default class AsyncStorageManager {
default: '[]', default: '[]',
current: '', current: '',
}, },
nightModeFollowSystem: {
key: 'nightModeFollowSystem',
default: '1',
current: '',
},
nightMode: { nightMode: {
key: 'nightMode', key: 'nightMode',
default: '0', default: '0',

View file

@ -3,6 +3,9 @@
import AsyncStorageManager from "./AsyncStorageManager"; import AsyncStorageManager from "./AsyncStorageManager";
import {DarkTheme, DefaultTheme} from 'react-native-paper'; import {DarkTheme, DefaultTheme} from 'react-native-paper';
import AprilFoolsManager from "./AprilFoolsManager"; import AprilFoolsManager from "./AprilFoolsManager";
import { Appearance } from 'react-native-appearance';
const colorScheme = Appearance.getColorScheme();
/** /**
* Singleton class used to manage themes * Singleton class used to manage themes
@ -107,7 +110,8 @@ export default class ThemeManager {
* @returns {boolean} Night mode state * @returns {boolean} Night mode state
*/ */
static getNightMode(): boolean { static getNightMode(): boolean {
return AsyncStorageManager.getInstance().preferences.nightMode.current === '1'; return AsyncStorageManager.getInstance().preferences.nightMode.current === '1' ||
AsyncStorageManager.getInstance().preferences.nightModeFollowSystem.current === '1' && colorScheme === 'dark';
} }
/** /**