Merge pull request #2747 from nestordominguez/issue-1922

Choose times for Automatic Dark Mode
This commit is contained in:
Sean Yesmunt 2019-08-19 12:12:49 -04:00 committed by GitHub
commit 69003c6079
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 138 additions and 46 deletions

View file

@ -47,7 +47,6 @@ export class FormFieldPrice extends React.PureComponent<Props> {
return ( return (
<fieldset-group class="fieldset-group--smushed"> <fieldset-group class="fieldset-group--smushed">
<fieldset-section>
<FormField <FormField
name={`${name}_amount`} name={`${name}_amount`}
label={__('Price')} label={__('Price')}
@ -60,8 +59,6 @@ export class FormFieldPrice extends React.PureComponent<Props> {
disabled={disabled} disabled={disabled}
step={step || 'any'} step={step || 'any'}
/> />
</fieldset-section>
<fieldset-section>
<FormField <FormField
label={__('Currency')} label={__('Currency')}
name={`${name}_currency`} name={`${name}_currency`}
@ -75,7 +72,6 @@ export class FormFieldPrice extends React.PureComponent<Props> {
<option value="LBC">{__('LBRY Credits (LBC)')}</option> <option value="LBC">{__('LBRY Credits (LBC)')}</option>
<option value="USD">{__('US Dollars')}</option> <option value="USD">{__('US Dollars')}</option>
</FormField> </FormField>
</fieldset-section>
</fieldset-group> </fieldset-group>
); );
} }

View file

@ -20,3 +20,4 @@ export const SUPPORT_OPTION = 'supportOption';
export const HIDE_BALANCE = 'hideBalance'; export const HIDE_BALANCE = 'hideBalance';
export const HIDE_SPLASH_ANIMATION = 'hideSplashAnimation'; export const HIDE_SPLASH_ANIMATION = 'hideSplashAnimation';
export const FLOATING_PLAYER = 'floatingPlayer'; export const FLOATING_PLAYER = 'floatingPlayer';
export const DARK_MODE_TIMES = 'darkModeTimes';

View file

@ -1,7 +1,13 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import * as settings from 'constants/settings'; import * as settings from 'constants/settings';
import { doClearCache, doNotifyEncryptWallet, doNotifyDecryptWallet } from 'redux/actions/app'; import { doClearCache, doNotifyEncryptWallet, doNotifyDecryptWallet } from 'redux/actions/app';
import { doSetDaemonSetting, doSetClientSetting, doGetThemes, doChangeLanguage } from 'redux/actions/settings'; import {
doSetDaemonSetting,
doSetClientSetting,
doGetThemes,
doChangeLanguage,
doSetDarkTime,
} from 'redux/actions/settings';
import { doSetPlayingUri } from 'redux/actions/content'; import { doSetPlayingUri } from 'redux/actions/content';
import { import {
makeSelectClientSetting, makeSelectClientSetting,
@ -30,6 +36,7 @@ const select = state => ({
userBlockedChannelsCount: selectBlockedChannelsCount(state), userBlockedChannelsCount: selectBlockedChannelsCount(state),
hideBalance: makeSelectClientSetting(settings.HIDE_BALANCE)(state), hideBalance: makeSelectClientSetting(settings.HIDE_BALANCE)(state),
floatingPlayer: makeSelectClientSetting(settings.FLOATING_PLAYER)(state), floatingPlayer: makeSelectClientSetting(settings.FLOATING_PLAYER)(state),
darkModeTimes: makeSelectClientSetting(settings.DARK_MODE_TIMES)(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({
@ -42,6 +49,7 @@ const perform = dispatch => ({
decryptWallet: () => dispatch(doNotifyDecryptWallet()), decryptWallet: () => dispatch(doNotifyDecryptWallet()),
updateWalletStatus: () => dispatch(doWalletStatus()), updateWalletStatus: () => dispatch(doWalletStatus()),
clearPlayingUri: () => dispatch(doSetPlayingUri(null)), clearPlayingUri: () => dispatch(doSetPlayingUri(null)),
setDarkTime: (time, options) => dispatch(doSetDarkTime(time, options)),
}); });
export default connect( export default connect(

View file

@ -16,6 +16,16 @@ type Price = {
type SetDaemonSettingArg = boolean | string | number | Price; type SetDaemonSettingArg = boolean | string | number | Price;
type DarkModeTimes = {
from: { hour: string, min: string, formattedTime: string },
to: { hour: string, min: string, formattedTime: string },
};
type OptionTimes = {
fromTo: string,
time: string,
};
type DaemonSettings = { type DaemonSettings = {
download_dir: string, download_dir: string,
share_usage_data: boolean, share_usage_data: boolean,
@ -52,6 +62,8 @@ type Props = {
hideBalance: boolean, hideBalance: boolean,
floatingPlayer: boolean, floatingPlayer: boolean,
clearPlayingUri: () => void, clearPlayingUri: () => void,
darkModeTimes: DarkModeTimes,
setDarkTime: (string, {}) => void,
}; };
type State = { type State = {
@ -74,6 +86,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
(this: any).onAutomaticDarkModeChange = this.onAutomaticDarkModeChange.bind(this); (this: any).onAutomaticDarkModeChange = this.onAutomaticDarkModeChange.bind(this);
(this: any).onLanguageChange = this.onLanguageChange.bind(this); (this: any).onLanguageChange = this.onLanguageChange.bind(this);
(this: any).clearCache = this.clearCache.bind(this); (this: any).clearCache = this.clearCache.bind(this);
(this: any).onChangeTime = this.onChangeTime.bind(this);
} }
componentDidMount() { componentDidMount() {
@ -130,6 +143,20 @@ class SettingsPage extends React.PureComponent<Props, State> {
} }
} }
onChangeTime(event: SyntheticInputEvent<*>, options: OptionTimes) {
const { value } = event.target;
this.props.setDarkTime(value, options);
}
to12Hour(time: string) {
const now = new Date(0, 0, 0, Number(time));
const hour = now.toLocaleTimeString('en-US', { hour12: true, hour: '2-digit' });
return hour;
}
setDaemonSetting(name: string, value: ?SetDaemonSettingArg): void { setDaemonSetting(name: string, value: ?SetDaemonSettingArg): void {
this.props.setDaemonSetting(name, value); this.props.setDaemonSetting(name, value);
} }
@ -169,6 +196,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
userBlockedChannelsCount, userBlockedChannelsCount,
floatingPlayer, floatingPlayer,
clearPlayingUri, clearPlayingUri,
darkModeTimes,
} = this.props; } = this.props;
const noDaemonSettings = !daemonSettings || Object.keys(daemonSettings).length === 0; const noDaemonSettings = !daemonSettings || Object.keys(daemonSettings).length === 0;
@ -177,6 +205,8 @@ class SettingsPage extends React.PureComponent<Props, State> {
const disableMaxKeyFee = !(daemonSettings && daemonSettings.max_key_fee); const disableMaxKeyFee = !(daemonSettings && daemonSettings.max_key_fee);
const connectionOptions = [1, 2, 4, 6, 10, 20]; const connectionOptions = [1, 2, 4, 6, 10, 20];
const startHours = ['18', '19', '20', '21'];
const endHours = ['5', '6', '7', '8'];
return ( return (
<Page> <Page>
@ -420,8 +450,38 @@ class SettingsPage extends React.PureComponent<Props, State> {
name="automatic_dark_mode" name="automatic_dark_mode"
onChange={() => this.onAutomaticDarkModeChange(!automaticDarkModeEnabled)} onChange={() => this.onAutomaticDarkModeChange(!automaticDarkModeEnabled)}
checked={automaticDarkModeEnabled} checked={automaticDarkModeEnabled}
label={__('Automatic dark mode (9pm to 8am)')} label={__('Automatic dark mode')}
/> />
{automaticDarkModeEnabled && (
<fieldset-group class="fieldset-group--smushed">
<FormField
type="select"
name="automatic_dark_mode_range"
onChange={value => this.onChangeTime(value, { fromTo: 'from', time: 'hour' })}
value={darkModeTimes.from.hour}
label={__('From')}
>
{startHours.map(time => (
<option key={time} value={time}>
{this.to12Hour(time)}
</option>
))}
</FormField>
<FormField
type="select"
name="automatic_dark_mode_range"
label={__('To')}
onChange={value => this.onChangeTime(value, { fromTo: 'to', time: 'hour' })}
value={darkModeTimes.to.hour}
>
{endHours.map(time => (
<option key={time} value={time}>
{this.to12Hour(time)}
</option>
))}
</FormField>
</fieldset-group>
)}
</fieldset-section> </fieldset-section>
</Form> </Form>
</section> </section>

View file

@ -3,11 +3,11 @@ import fs from 'fs';
import http from 'http'; import http from 'http';
// @endif // @endif
import { Lbry, ACTIONS, SETTINGS } from 'lbry-redux'; import { Lbry, ACTIONS, SETTINGS } from 'lbry-redux';
import * as DESKTOP_SETTINGS from 'constants/settings';
import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings';
import moment from 'moment';
import analytics from 'analytics'; import analytics from 'analytics';
const UPDATE_IS_NIGHT_INTERVAL = 10 * 60 * 1000; const UPDATE_IS_NIGHT_INTERVAL = 5 * 60 * 1000;
export function doFetchDaemonSettings() { export function doFetchDaemonSettings() {
return dispatch => { return dispatch => {
@ -60,16 +60,8 @@ export function doGetThemes() {
} }
export function doUpdateIsNight() { export function doUpdateIsNight() {
const momentNow = moment();
return { return {
type: ACTIONS.UPDATE_IS_NIGHT, type: ACTIONS.UPDATE_IS_NIGHT,
data: {
isNight: (() => {
const startNightMoment = moment('21:00', 'HH:mm');
const endNightMoment = moment('8:00', 'HH:mm');
return !(momentNow.isAfter(endNightMoment) && momentNow.isBefore(startNightMoment));
})(),
},
}; };
} }
@ -147,3 +139,25 @@ export function doChangeLanguage(language) {
i18n.setLocale(language); i18n.setLocale(language);
}; };
} }
export function doSetDarkTime(value, options) {
const { fromTo, time } = options;
return (dispatch, getState) => {
const state = getState();
const { darkModeTimes } = state.settings.clientSettings;
const { hour, min } = darkModeTimes[fromTo];
const newHour = time === 'hour' ? value : hour;
const newMin = time === 'min' ? value : min;
const modifiedTimes = {
[fromTo]: {
hour: newHour,
min: newMin,
formattedTime: newHour + ':' + newMin,
},
};
const mergedTimes = { ...darkModeTimes, ...modifiedTimes };
dispatch(doSetClientSetting(DESKTOP_SETTINGS.DARK_MODE_TIMES, mergedTimes));
dispatch(doUpdateIsNight());
};
}

View file

@ -1,6 +1,7 @@
import * as ACTIONS from 'constants/action_types'; import * as ACTIONS from 'constants/action_types';
import LANGUAGES from 'constants/languages'; import LANGUAGES from 'constants/languages';
import * as SETTINGS from 'constants/settings'; import * as SETTINGS from 'constants/settings';
import moment from 'moment';
function getLocalStorageSetting(setting, fallback) { function getLocalStorageSetting(setting, fallback) {
const localStorageVal = localStorage.getItem(`setting_${setting}`); const localStorageVal = localStorage.getItem(`setting_${setting}`);
@ -32,6 +33,10 @@ const defaultState = {
[SETTINGS.HIDE_BALANCE]: Boolean(getLocalStorageSetting(SETTINGS.HIDE_BALANCE, false)), [SETTINGS.HIDE_BALANCE]: Boolean(getLocalStorageSetting(SETTINGS.HIDE_BALANCE, false)),
[SETTINGS.HIDE_SPLASH_ANIMATION]: Boolean(getLocalStorageSetting(SETTINGS.HIDE_SPLASH_ANIMATION, false)), [SETTINGS.HIDE_SPLASH_ANIMATION]: Boolean(getLocalStorageSetting(SETTINGS.HIDE_SPLASH_ANIMATION, false)),
[SETTINGS.FLOATING_PLAYER]: Boolean(getLocalStorageSetting(SETTINGS.FLOATING_PLAYER, true)), [SETTINGS.FLOATING_PLAYER]: Boolean(getLocalStorageSetting(SETTINGS.FLOATING_PLAYER, true)),
[SETTINGS.DARK_MODE_TIMES]: getLocalStorageSetting(SETTINGS.DARK_MODE_TIMES, {
from: { hour: '21', min: '00', formattedTime: '21:00' },
to: { hour: '8', min: '00', formattedTime: '8:00' },
}),
}, },
isNight: false, isNight: false,
languages: { en: 'English', pl: 'Polish', id: 'Bahasa Indonesia' }, // temporarily hard code these so we can advance i18n testing languages: { en: 'English', pl: 'Polish', id: 'Bahasa Indonesia' }, // temporarily hard code these so we can advance i18n testing
@ -59,10 +64,17 @@ reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => {
}); });
}; };
reducers[ACTIONS.UPDATE_IS_NIGHT] = (state, action) => reducers[ACTIONS.UPDATE_IS_NIGHT] = state => {
Object.assign({}, state, { const { from, to } = state.clientSettings.darkModeTimes;
isNight: action.data.isNight, const momentNow = moment();
const startNightMoment = moment(from.formattedTime, 'HH:mm');
const endNightMoment = moment(to.formattedTime, 'HH:mm');
const isNight = !(momentNow.isAfter(endNightMoment) && momentNow.isBefore(startNightMoment));
return Object.assign({}, state, {
isNight,
}); });
};
reducers[ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED] = (state, action) => { reducers[ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED] = (state, action) => {
const languages = Object.assign({}, state.languages); const languages = Object.assign({}, state.languages);

View file

@ -118,8 +118,9 @@ fieldset-group {
width: auto; width: auto;
margin-bottom: 0; margin-bottom: 0;
&:first-of-type { &:first-child {
input { input,
select {
border-right: none; border-right: none;
border-top-right-radius: 0; border-top-right-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;