add basic feature

This commit is contained in:
Arrowana 2018-01-14 20:14:15 +11:00
parent 431c155932
commit 8eb7f58988
9 changed files with 66 additions and 3 deletions

View file

@ -41,6 +41,7 @@
"jshashes": "^1.0.7", "jshashes": "^1.0.7",
"keytar": "^4.0.3", "keytar": "^4.0.3",
"localforage": "^1.5.0", "localforage": "^1.5.0",
"moment": "^2.20.1",
"npm": "^5.5.1", "npm": "^5.5.1",
"qrcode.react": "^0.7.2", "qrcode.react": "^0.7.2",
"rc-progress": "^2.0.6", "rc-progress": "^2.0.6",

View file

@ -95,6 +95,7 @@ export const SEARCH_CANCELLED = 'SEARCH_CANCELLED';
// Settings // Settings
export const DAEMON_SETTINGS_RECEIVED = 'DAEMON_SETTINGS_RECEIVED'; export const DAEMON_SETTINGS_RECEIVED = 'DAEMON_SETTINGS_RECEIVED';
export const CLIENT_SETTING_CHANGED = 'CLIENT_SETTING_CHANGED'; export const CLIENT_SETTING_CHANGED = 'CLIENT_SETTING_CHANGED';
export const UPDATE_IS_NIGHT = 'UPDATE_IS_NIGHT';
// User // User
export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED'; export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED';

View file

@ -11,3 +11,4 @@ export const INSTANT_PURCHASE_ENABLED = 'instantPurchaseEnabled';
export const INSTANT_PURCHASE_MAX = 'instantPurchaseMax'; export const INSTANT_PURCHASE_MAX = 'instantPurchaseMax';
export const THEME = 'theme'; export const THEME = 'theme';
export const THEMES = 'themes'; export const THEMES = 'themes';
export const AUTOMATIC_DARK_MODE_ENABLED = 'automaticDarkModeEnabled';

View file

@ -10,6 +10,7 @@ import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { doConditionalAuthNavigate, doDaemonReady, doShowSnackBar } from 'redux/actions/app'; import { doConditionalAuthNavigate, doDaemonReady, doShowSnackBar } from 'redux/actions/app';
import { doUpdateIsNightAsync } from 'redux/actions/settings';
import { doNavigate } from 'redux/actions/navigation'; import { doNavigate } from 'redux/actions/navigation';
import { doDownloadLanguages } from 'redux/actions/settings'; import { doDownloadLanguages } from 'redux/actions/settings';
import { doUserEmailVerify } from 'redux/actions/user'; import { doUserEmailVerify } from 'redux/actions/user';
@ -97,6 +98,7 @@ document.addEventListener('click', event => {
}); });
const init = () => { const init = () => {
app.store.dispatch(doUpdateIsNightAsync());
app.store.dispatch(doDownloadLanguages()); app.store.dispatch(doDownloadLanguages());
function onDaemonReady() { function onDaemonReady() {

View file

@ -28,6 +28,7 @@ const select = state => ({
themes: makeSelectClientSetting(settings.THEMES)(state), themes: makeSelectClientSetting(settings.THEMES)(state),
language: selectCurrentLanguage(state), language: selectCurrentLanguage(state),
languages: selectLanguages(state), languages: selectLanguages(state),
automaticDarkModeEnabled: makeSelectClientSetting(settings.AUTOMATIC_DARK_MODE_ENABLED)(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({

View file

@ -65,6 +65,10 @@ class SettingsPage extends React.PureComponent {
this.props.setClientSetting(settings.THEME, value); this.props.setClientSetting(settings.THEME, value);
} }
onAutomaticDarkModeChange(event) {
this.props.setClientSetting(settings.AUTOMATIC_DARK_MODE_ENABLED, event.target.checked);
}
onInstantPurchaseEnabledChange(enabled) { onInstantPurchaseEnabledChange(enabled) {
this.props.setClientSetting(settings.INSTANT_PURCHASE_ENABLED, enabled); this.props.setClientSetting(settings.INSTANT_PURCHASE_ENABLED, enabled);
} }
@ -129,6 +133,7 @@ class SettingsPage extends React.PureComponent {
showUnavailable, showUnavailable,
theme, theme,
themes, themes,
automaticDarkModeEnabled,
} = this.props; } = this.props;
if (!daemonSettings || Object.keys(daemonSettings).length === 0) { if (!daemonSettings || Object.keys(daemonSettings).length === 0) {
@ -317,6 +322,13 @@ class SettingsPage extends React.PureComponent {
</option> </option>
))} ))}
</FormField> </FormField>
<FormRow
type="checkbox"
onChange={this.onAutomaticDarkModeChange.bind(this)}
defaultChecked={automaticDarkModeEnabled}
label={__('Automatic dark mode (switch to dark theme between 9pm and 8am)')}
/>
</div> </div>
</section> </section>

View file

@ -4,6 +4,9 @@ import Fs from 'fs';
import Http from 'http'; import Http from 'http';
import Lbry from 'lbry'; import Lbry from 'lbry';
import moment from 'moment';
const UPDATE_IS_NIGHT_INTERVAL = 10 * 1000;
export function doFetchDaemonSettings() { export function doFetchDaemonSettings() {
return dispatch => { return dispatch => {
@ -51,6 +54,29 @@ export function doGetThemes() {
}; };
} }
export function doUpdateIsNightAsync() {
return dispatch => {
const updateIsNightInterval = setInterval(
() => dispatch(doUpdateIsNight()),
UPDATE_IS_NIGHT_INTERVAL
);
};
}
function isNight() {
const startNightMoment = moment('19:00', 'HH:mm');
const endNightTime = moment('8:00', 'HH:mm');
const momentNow = moment();
return momentNow.isAfter(endNightTime) && momentNow.isBefore(startNightMoment) ? false : true;
}
export function doUpdateIsNight() {
return {
type: ACTIONS.UPDATE_IS_NIGHT,
data: { isNight: isNight() },
};
}
export function doDownloadLanguage(langFile) { export function doDownloadLanguage(langFile) {
return dispatch => { return dispatch => {
const destinationPath = `${app.i18n.directory}/${langFile}`; const destinationPath = `${app.i18n.directory}/${langFile}`;

View file

@ -23,7 +23,9 @@ const defaultState = {
language: getLocalStorageSetting(SETTINGS.LANGUAGE, 'en'), language: getLocalStorageSetting(SETTINGS.LANGUAGE, 'en'),
theme: getLocalStorageSetting(SETTINGS.THEME, 'light'), theme: getLocalStorageSetting(SETTINGS.THEME, 'light'),
themes: getLocalStorageSetting(SETTINGS.THEMES, []), themes: getLocalStorageSetting(SETTINGS.THEMES, []),
automaticDarkModeEnabled: getLocalStorageSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, false),
}, },
isNight: true,
languages: {}, languages: {},
}; };
@ -46,6 +48,11 @@ reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => {
}); });
}; };
reducers[ACTIONS.UPDATE_IS_NIGHT] = (state, action) =>
Object.assign({}, state, {
isNight: action.data.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);
const { language } = action.data; const { language } = action.data;

View file

@ -1,5 +1,6 @@
import * as SETTINGS from 'constants/settings'; import * as SETTINGS from 'constants/settings';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import moment from 'moment';
const selectState = state => state.settings || {}; const selectState = state => state.settings || {};
@ -18,7 +19,18 @@ export const selectShowNsfw = makeSelectClientSetting(SETTINGS.SHOW_NSFW);
export const selectLanguages = createSelector(selectState, state => state.languages || {}); export const selectLanguages = createSelector(selectState, state => state.languages || {});
export const selectThemePath = createSelector( export const selectTheme = makeSelectClientSetting(SETTINGS.THEME);
makeSelectClientSetting(SETTINGS.THEME), export const selectAutomaticDarkModeEnabled = makeSelectClientSetting(
theme => `${staticResourcesPath}/themes/${theme || 'light'}.css` SETTINGS.AUTOMATIC_DARK_MODE_ENABLED
);
export const selectIsNight = createSelector(selectState, state => state.isNight);
export const selectThemePath = createSelector(
selectTheme,
selectAutomaticDarkModeEnabled,
selectIsNight,
(theme, automaticDarkModeEnabled, isNight) => {
const dynamicTheme = automaticDarkModeEnabled && isNight ? 'dark' : theme;
return `${staticResourcesPath}/themes/${dynamicTheme || 'light'}.css`;
}
); );