all settings constants come from redux
sync settings backout nav cases and anon preference key more robust backout header put notificationSettings under backout bar review changes
This commit is contained in:
parent
e001906443
commit
d9bf72a351
50 changed files with 287 additions and 191 deletions
|
@ -135,7 +135,7 @@
|
|||
"imagesloaded": "^4.1.4",
|
||||
"json-loader": "^0.5.4",
|
||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||
"lbry-redux": "lbryio/lbry-redux#5547f53f487dacf8c89202ad18f7d2123668be85",
|
||||
"lbry-redux": "lbryio/lbry-redux#52dd14bf9a22d06e34fdb4bf2004129041dbb949",
|
||||
"lbryinc": "lbryio/lbryinc#cff5dd60934c4c6080e135f47ebbece1548c658c",
|
||||
"lint-staged": "^7.0.2",
|
||||
"localforage": "^1.7.1",
|
||||
|
|
|
@ -1254,9 +1254,12 @@
|
|||
"Mature content blocked.": "Mature content blocked.",
|
||||
"Change this in your %content_settings%.": "Change this in your %content_settings%.",
|
||||
"content settings": "content settings",
|
||||
"Autoplay next in list": "Autoplay next in list",
|
||||
"Autoplay the next media file in the related list.": "Autoplay the next media file in the related list.",
|
||||
"There was an error with LBRY first publishing.": "There was an error with LBRY first publishing.",
|
||||
"Automagically upload to your youtube channel.": "Automagically upload to your youtube channel.",
|
||||
"Your file was published to LBRY, but the YouTube upload failed.": "Your file was published to LBRY, but the YouTube upload failed.",
|
||||
"Your servers were not available. Check your url and port, or switch back to defaults.": "Your servers were not available. Check your url and port, or switch back to defaults.",
|
||||
"LBRY Status": "LBRY Status",
|
||||
"Check the status of various LBRY services.": "Check the status of various LBRY services.",
|
||||
"Check Status": "Check Status",
|
||||
|
@ -1265,5 +1268,6 @@
|
|||
"View thumbnail": "View thumbnail",
|
||||
"These changes will appear shortly.": "These changes will appear shortly.",
|
||||
"Block Channel": "Block Channel",
|
||||
"Manage Notifications": "Manage Notifications",
|
||||
"--end--": "--end--"
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { hot } from 'react-hot-loader/root';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectGetSyncErrorMessage, selectUploadCount } from 'lbryinc';
|
||||
import { doFetchAccessToken, doUserSetReferrer } from 'redux/actions/user';
|
||||
import { selectUser, selectAccessToken, selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import { selectUnclaimedRewards } from 'redux/selectors/rewards';
|
||||
import { doFetchChannelListMine } from 'lbry-redux';
|
||||
import { doFetchChannelListMine, SETTINGS } from 'lbry-redux';
|
||||
import { makeSelectClientSetting, selectLoadedLanguages, selectThemePath } from 'redux/selectors/settings';
|
||||
import { selectIsUpgradeAvailable, selectAutoUpdateDownloaded } from 'redux/selectors/app';
|
||||
import { doSetLanguage } from 'redux/actions/settings';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { makeSelectClaimForUri } from 'lbry-redux';
|
||||
import { makeSelectClaimForUri, SETTINGS } from 'lbry-redux';
|
||||
import { withRouter } from 'react-router';
|
||||
import { makeSelectIsPlayerFloating, makeSelectNextUnplayedRecommended } from 'redux/selectors/content';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { PAGE_SIZE } from 'constants/claim';
|
||||
import {
|
||||
|
@ -7,6 +6,7 @@ import {
|
|||
makeSelectClaimIsMine,
|
||||
makeSelectTotalPagesInChannelSearch,
|
||||
makeSelectClaimForUri,
|
||||
SETTINGS,
|
||||
} from 'lbry-redux';
|
||||
import { selectChannelIsBlocked } from 'redux/selectors/blocked';
|
||||
import { withRouter } from 'react-router';
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { doSetClientSetting } from 'redux/actions/settings';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { selectEmailToVerify, selectUser } from 'redux/selectors/user';
|
||||
import FirstRunEmailCollection from './view';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
|
||||
const select = state => ({
|
||||
emailCollectionAcknowledged: makeSelectClientSetting(SETTINGS.EMAIL_COLLECTION_ACKNOWLEDGED)(state),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { makeSelectThumbnailForUri, doResolveUri, makeSelectClaimForUri } from 'lbry-redux';
|
||||
import { makeSelectThumbnailForUri, doResolveUri, makeSelectClaimForUri, SETTINGS } from 'lbry-redux';
|
||||
import { doFetchCostInfoForUri, makeSelectCostInfoForUri } from 'lbryinc';
|
||||
import { doSetFloatingUri, doPlayUri } from 'redux/actions/content';
|
||||
import { doAnaltyicsPurchaseEvent } from 'redux/actions/app';
|
||||
|
|
|
@ -5,8 +5,8 @@ import {
|
|||
makeSelectContentTypeForUri,
|
||||
makeSelectDownloadPathForUri,
|
||||
makeSelectStreamingUrlForUri,
|
||||
SETTINGS,
|
||||
} from 'lbry-redux';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { makeSelectFileRenderModeForUri, makeSelectFileExtensionForUri } from 'redux/selectors/content';
|
||||
import FileRender from './view';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { makeSelectFileInfoForUri, makeSelectTitleForUri, makeSelectStreamingUrlForUri } from 'lbry-redux';
|
||||
import { makeSelectFileInfoForUri, makeSelectTitleForUri, makeSelectStreamingUrlForUri, SETTINGS } from 'lbry-redux';
|
||||
import {
|
||||
makeSelectIsPlayerFloating,
|
||||
selectFloatingUri,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { doPlayUri, doSetPlayingUri } from 'redux/actions/content';
|
||||
import {
|
||||
|
@ -7,6 +6,7 @@ import {
|
|||
makeSelectClaimForUri,
|
||||
makeSelectStreamingUrlForUri,
|
||||
makeSelectClaimWasPurchased,
|
||||
SETTINGS,
|
||||
} from 'lbry-redux';
|
||||
import { makeSelectCostInfoForUri } from 'lbryinc';
|
||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectBalance, formatCredits } from 'lbry-redux';
|
||||
import { selectBalance, formatCredits, SETTINGS } from 'lbry-redux';
|
||||
import { selectGetSyncErrorMessage } from 'lbryinc';
|
||||
import { selectUserVerifiedEmail, selectUserEmail, selectEmailToVerify } from 'redux/selectors/user';
|
||||
import { doClearEmailEntry, doClearPasswordEntry } from 'redux/actions/user';
|
||||
|
@ -9,6 +8,7 @@ import { doSetClientSetting } from 'redux/actions/settings';
|
|||
import { doSignOut, doOpenModal } from 'redux/actions/app';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import Header from './view';
|
||||
import { selectHasNavigated } from 'redux/selectors/app';
|
||||
|
||||
const select = state => ({
|
||||
balance: selectBalance(state),
|
||||
|
@ -21,6 +21,7 @@ const select = state => ({
|
|||
email: selectUserEmail(state),
|
||||
syncError: selectGetSyncErrorMessage(state),
|
||||
emailToVerify: selectEmailToVerify(state),
|
||||
hasNavigated: selectHasNavigated(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
import * as ICONS from 'constants/icons';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
import * as PAGES from 'constants/pages';
|
||||
import React, { Fragment } from 'react';
|
||||
import { withRouter } from 'react-router';
|
||||
|
@ -31,6 +31,7 @@ type Props = {
|
|||
length: number,
|
||||
location: { pathname: string },
|
||||
push: string => void,
|
||||
replace: string => void,
|
||||
},
|
||||
currentTheme: string,
|
||||
automaticDarkModeEnabled: boolean,
|
||||
|
@ -40,7 +41,9 @@ type Props = {
|
|||
authenticated: boolean,
|
||||
authHeader: boolean,
|
||||
backout: {
|
||||
backFunction: () => void,
|
||||
backLabel?: string,
|
||||
backCB?: () => void,
|
||||
backNavDefault?: string,
|
||||
title: string,
|
||||
simpleTitle: string, // Just use the same value as `title` if `title` is already short (~< 10 chars), unless you have a better idea for title overlfow on mobile
|
||||
},
|
||||
|
@ -52,6 +55,7 @@ type Props = {
|
|||
openSignOutModal: () => void,
|
||||
clearEmailEntry: () => void,
|
||||
clearPasswordEntry: () => void,
|
||||
hasNavigated: boolean,
|
||||
};
|
||||
|
||||
const Header = (props: Props) => {
|
||||
|
@ -80,6 +84,8 @@ const Header = (props: Props) => {
|
|||
const isSignUpPage = history.location.pathname.includes(PAGES.AUTH);
|
||||
const isSignInPage = history.location.pathname.includes(PAGES.AUTH_SIGNIN);
|
||||
const isPwdResetPage = history.location.pathname.includes(PAGES.AUTH_PASSWORD_RESET);
|
||||
const hasBackout = Boolean(backout);
|
||||
const { backLabel, backCB, backNavDefault, title: backTitle, simpleTitle: simpleBackTitle } = backout || {};
|
||||
|
||||
// Sign out if they click the "x" when they are on the password prompt
|
||||
const authHeaderAction = syncError ? { onClick: signOut } : { navigate: '/' };
|
||||
|
@ -107,6 +113,32 @@ const Header = (props: Props) => {
|
|||
},
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (hasBackout) {
|
||||
window.addEventListener('popstate', onBackout);
|
||||
return () => window.removeEvenListener('popstate', onBackout);
|
||||
}
|
||||
}, [hasBackout]);
|
||||
|
||||
function onBackout(e) {
|
||||
const { history, hasNavigated } = props;
|
||||
const { goBack, replace } = history;
|
||||
|
||||
window.removeEventListener('popstate', onBackout);
|
||||
|
||||
if (backCB) {
|
||||
backCB();
|
||||
}
|
||||
if (e.type !== 'popstate') {
|
||||
// if not initiated by pop (back button)
|
||||
if (hasNavigated && !backNavDefault) {
|
||||
goBack();
|
||||
} else {
|
||||
replace(backNavDefault || `/`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleThemeToggle() {
|
||||
if (automaticDarkModeEnabled) {
|
||||
setClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, false);
|
||||
|
@ -149,15 +181,19 @@ const Header = (props: Props) => {
|
|||
<div className="header__contents">
|
||||
{!authHeader && backout ? (
|
||||
<div className="card__actions--between">
|
||||
<Button onClick={backout.backFunction} button="link" label={__('Cancel')} icon={ICONS.ARROW_LEFT} />
|
||||
{backout.title && (
|
||||
<h1 className={'card__title'}>{isMobile ? backout.simpleTitle || backout.title : backout.title}</h1>
|
||||
)}
|
||||
<Button
|
||||
onClick={onBackout}
|
||||
button="link"
|
||||
label={(backLabel && backLabel) || __('Cancel')}
|
||||
icon={ICONS.ARROW_LEFT}
|
||||
/>
|
||||
{backTitle && <h1 className={'card__title'}>{isMobile ? simpleBackTitle || backTitle : backTitle}</h1>}
|
||||
<Button
|
||||
aria-label={__('Your wallet')}
|
||||
navigate={`/$/${PAGES.WALLET}`}
|
||||
className="header__navigation-item menu__title header__navigation-item--balance"
|
||||
label={getWalletTitle()}
|
||||
disabled
|
||||
// @if TARGET='app'
|
||||
onDoubleClick={e => {
|
||||
e.stopPropagation();
|
||||
|
|
|
@ -19,7 +19,13 @@ type Props = {
|
|||
noHeader: boolean,
|
||||
noFooter: boolean,
|
||||
noSideNavigation: boolean,
|
||||
backout: { backFunction: () => void, backTitle: string },
|
||||
backout: {
|
||||
backLabel?: string,
|
||||
backCB?: () => void,
|
||||
backNavDefault?: string,
|
||||
title: string,
|
||||
simpleTitle: string, // Just use the same value as `title` if `title` is already short (~< 10 chars), unless you have a better idea for title overlfow on mobile
|
||||
},
|
||||
};
|
||||
|
||||
function Page(props: Props) {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import { selectScrollStartingPosition, selectWelcomeVersion } from 'redux/selectors/app';
|
||||
import { selectHasNavigated, selectScrollStartingPosition, selectWelcomeVersion } from 'redux/selectors/app';
|
||||
import Router from './view';
|
||||
import { normalizeURI, makeSelectTitleForUri } from 'lbry-redux';
|
||||
import { doSetHasNavigated } from 'redux/actions/app';
|
||||
|
||||
const select = state => {
|
||||
const { pathname, hash } = state.router.location;
|
||||
|
@ -27,7 +28,12 @@ const select = state => {
|
|||
currentScroll: selectScrollStartingPosition(state),
|
||||
isAuthenticated: selectUserVerifiedEmail(state),
|
||||
welcomeVersion: selectWelcomeVersion(state),
|
||||
hasNavigated: selectHasNavigated(state),
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(select)(Router);
|
||||
const perform = dispatch => ({
|
||||
setHasNavigated: () => dispatch(doSetHasNavigated()),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(Router);
|
||||
|
|
|
@ -89,10 +89,13 @@ type Props = {
|
|||
push: string => void,
|
||||
state: {},
|
||||
replaceState: ({}, string, string) => void,
|
||||
listen: any => () => void,
|
||||
},
|
||||
uri: string,
|
||||
title: string,
|
||||
welcomeVersion: number,
|
||||
hasNavigated: boolean,
|
||||
setHasNavigated: () => void,
|
||||
};
|
||||
|
||||
function AppRouter(props: Props) {
|
||||
|
@ -104,12 +107,24 @@ function AppRouter(props: Props) {
|
|||
uri,
|
||||
title,
|
||||
welcomeVersion,
|
||||
hasNavigated,
|
||||
setHasNavigated,
|
||||
} = props;
|
||||
const { entries } = history;
|
||||
const entryIndex = history.index;
|
||||
const urlParams = new URLSearchParams(search);
|
||||
const resetScroll = urlParams.get('reset_scroll');
|
||||
|
||||
// for people arriving at settings page from deeplinks, know whether they can "go back"
|
||||
useEffect(() => {
|
||||
const unlisten = history.listen((location, action) => {
|
||||
if (action === 'PUSH') {
|
||||
if (!hasNavigated && setHasNavigated) setHasNavigated();
|
||||
}
|
||||
});
|
||||
return unlisten;
|
||||
}, [hasNavigated, setHasNavigated]);
|
||||
|
||||
useEffect(() => {
|
||||
if (uri) {
|
||||
const { channelName, streamName } = parseURI(uri);
|
||||
|
|
|
@ -4,7 +4,7 @@ import { makeSelectClientSetting } from 'redux/selectors/settings';
|
|||
import { doUserPasswordSet, doClearPasswordEntry } from 'redux/actions/user';
|
||||
import { doToast } from 'redux/actions/notifications';
|
||||
import UserSignIn from './view';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
|
||||
const select = state => ({
|
||||
user: selectUser(state),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { connect } from 'react-redux';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
import { doSetAutoLaunch } from 'redux/actions/settings';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { doToast } from 'redux/actions/notifications';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { connect } from 'react-redux';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
import { doSetLanguage } from 'redux/actions/settings';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import SettingLanguage from './view';
|
||||
|
@ -12,7 +12,4 @@ const perform = dispatch => ({
|
|||
setLanguage: value => dispatch(doSetLanguage(value)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(SettingLanguage);
|
||||
export default connect(select, perform)(SettingLanguage);
|
||||
|
|
|
@ -6,6 +6,7 @@ import Button from 'component/button';
|
|||
import I18nMessage from 'component/i18nMessage';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import ServerInputRow from './internal/inputRow';
|
||||
import { stringifyServerParam } from 'util/sync-settings';
|
||||
|
||||
type StatusOfServer = {
|
||||
host: string,
|
||||
|
@ -84,13 +85,6 @@ function SettingWalletServer(props: Props) {
|
|||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
function makeServerParam(configList) {
|
||||
return configList.reduce((acc, cur) => {
|
||||
acc.push(`${cur[0]}:${cur[1]}`);
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function doClear() {
|
||||
setAdvancedMode(false);
|
||||
clearWalletServers();
|
||||
|
@ -110,7 +104,7 @@ function SettingWalletServer(props: Props) {
|
|||
|
||||
function updateServers(newConfig) {
|
||||
saveServerConfig(newConfig);
|
||||
setCustomWalletServers(makeServerParam(newConfig));
|
||||
setCustomWalletServers(stringifyServerParam(newConfig));
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -134,7 +128,7 @@ function SettingWalletServer(props: Props) {
|
|||
onChange={e => {
|
||||
setAdvancedMode(e.target.checked);
|
||||
if (e.target.checked && customWalletServers.length) {
|
||||
setCustomWalletServers(makeServerParam(customWalletServers));
|
||||
setCustomWalletServers(stringifyServerParam(customWalletServers));
|
||||
}
|
||||
}}
|
||||
label={__('Use custom wallet servers')}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||
import { selectFollowedTags, selectPurchaseUriSuccess, doClearPurchasedUriSuccess } from 'lbry-redux';
|
||||
import { selectFollowedTags, selectPurchaseUriSuccess, doClearPurchasedUriSuccess, SETTINGS } from 'lbry-redux';
|
||||
import { selectUploadCount } from 'lbryinc';
|
||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
|
|
|
@ -3,8 +3,7 @@ import { connect } from 'react-redux';
|
|||
import { selectDaemonVersionMatched, selectModal } from 'redux/selectors/app';
|
||||
import { doCheckDaemonVersion, doOpenModal, doHideModal } from 'redux/actions/app';
|
||||
import { doSetClientSetting, doClearDaemonSetting } from 'redux/actions/settings';
|
||||
import * as settings from 'constants/settings';
|
||||
import { DAEMON_SETTINGS } from 'lbry-redux';
|
||||
import { DAEMON_SETTINGS, SETTINGS } from 'lbry-redux';
|
||||
import { doToast } from 'redux/actions/notifications';
|
||||
import SplashScreen from './view';
|
||||
|
||||
|
@ -13,7 +12,7 @@ import { makeSelectClientSetting } from 'redux/selectors/settings';
|
|||
const select = state => ({
|
||||
modal: selectModal(state),
|
||||
daemonVersionMatched: selectDaemonVersionMatched(state),
|
||||
animationHidden: makeSelectClientSetting(settings.HIDE_SPLASH_ANIMATION)(state),
|
||||
animationHidden: makeSelectClientSetting(SETTINGS.HIDE_SPLASH_ANIMATION)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
// @flow
|
||||
import type { Node } from 'react';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
import { Lbry, SETTINGS } from 'lbry-redux';
|
||||
import Button from 'component/button';
|
||||
import ModalWalletUnlock from 'modal/modalWalletUnlock';
|
||||
import ModalIncompatibleDaemon from 'modal/modalIncompatibleDaemon';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import { selectGetSyncErrorMessage } from 'lbryinc';
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { doClearEmailEntry, doUserSignUp } from 'redux/actions/user';
|
||||
import {
|
||||
|
@ -7,7 +6,7 @@ import {
|
|||
selectEmailAlreadyExists,
|
||||
selectUser,
|
||||
} from 'redux/selectors/user';
|
||||
import { DAEMON_SETTINGS } from 'lbry-redux';
|
||||
import { DAEMON_SETTINGS, SETTINGS } from 'lbry-redux';
|
||||
import { doSetClientSetting, doSetDaemonSetting } from 'redux/actions/settings';
|
||||
import { makeSelectClientSetting, selectDaemonSettings } from 'redux/selectors/settings';
|
||||
import UserEmailNew from './view';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
import * as PAGES from 'constants/pages';
|
||||
import React, { useState } from 'react';
|
||||
import { FormField, Form } from 'component/common/form';
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import REWARD_TYPES from 'rewards';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectGetSyncIsPending, selectGetSyncErrorMessage, selectSyncHash } from 'lbryinc';
|
||||
|
@ -12,7 +11,13 @@ import {
|
|||
selectUser,
|
||||
selectAccessToken,
|
||||
} from 'redux/selectors/user';
|
||||
import { selectMyChannelClaims, selectBalance, selectFetchingMyChannels, selectCreatingChannel } from 'lbry-redux';
|
||||
import {
|
||||
selectMyChannelClaims,
|
||||
selectBalance,
|
||||
selectFetchingMyChannels,
|
||||
selectCreatingChannel,
|
||||
SETTINGS,
|
||||
} from 'lbry-redux';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import UserSignIn from './view';
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { makeSelectClaimForUri, makeSelectFileInfoForUri, makeSelectThumbnailForUri } from 'lbry-redux';
|
||||
import { makeSelectClaimForUri, makeSelectFileInfoForUri, makeSelectThumbnailForUri, SETTINGS } from 'lbry-redux';
|
||||
import { doChangeVolume, doChangeMute, doAnalyticsView } from 'redux/actions/app';
|
||||
import { selectVolume, selectMute } from 'redux/selectors/app';
|
||||
import { savePosition, clearPosition } from 'redux/actions/content';
|
||||
|
@ -8,7 +8,6 @@ import VideoViewer from './view';
|
|||
import { withRouter } from 'react-router';
|
||||
import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
|
||||
const select = (state, props) => {
|
||||
const { search } = props.location;
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
XXX_COMPLETE // if there is no fail case
|
||||
*/
|
||||
|
||||
// redux-persist
|
||||
export const REHYDRATE = 'persist/REHYDRATE';
|
||||
|
||||
// app
|
||||
export const WINDOW_FOCUSED = 'WINDOW_FOCUSED';
|
||||
export const DAEMON_READY = 'DAEMON_READY';
|
||||
export const DAEMON_VERSION_MATCH = 'DAEMON_VERSION_MATCH';
|
||||
|
@ -22,6 +26,7 @@ export const TOGGLE_SEARCH_EXPANDED = 'TOGGLE_SEARCH_EXPANDED';
|
|||
export const PASSWORD_SAVED = 'PASSWORD_SAVED';
|
||||
export const SET_WELCOME_VERSION = 'SET_WELCOME_VERSION';
|
||||
export const SET_ALLOW_ANALYTICS = 'SET_ALLOW_ANALYTICS';
|
||||
export const SET_HAS_NAVIGATED = 'SET_HAS_NAVIGATED';
|
||||
|
||||
// Navigation
|
||||
export const CHANGE_AFTER_AUTH_PATH = 'CHANGE_AFTER_AUTH_PATH';
|
||||
|
@ -120,6 +125,7 @@ export const CLIENT_SETTING_CHANGED = 'CLIENT_SETTING_CHANGED';
|
|||
export const UPDATE_IS_NIGHT = 'UPDATE_IS_NIGHT';
|
||||
export const FINDING_FFMPEG_STARTED = 'FINDING_FFMPEG_STARTED';
|
||||
export const FINDING_FFMPEG_COMPLETED = 'FINDING_FFMPEG_COMPLETED';
|
||||
export const SYNC_CLIENT_SETTINGS = 'SYNC_CLIENT_SETTINGS';
|
||||
|
||||
// User
|
||||
export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED';
|
||||
|
|
|
@ -9,7 +9,6 @@ export const AUTO_GENERATE_THUMBNAIL = 'auto_generate_thumbnail';
|
|||
export const AUTO_UPDATE_DOWNLOADED = 'auto_update_downloaded';
|
||||
export const ERROR = 'error';
|
||||
export const UPGRADE = 'upgrade';
|
||||
export const WELCOME = 'welcome';
|
||||
export const EMAIL_COLLECTION = 'email_collection';
|
||||
export const PHONE_COLLECTION = 'phone_collection';
|
||||
export const FIRST_REWARD = 'first_reward';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
import React from 'react';
|
||||
import { Modal } from 'modal/modal';
|
||||
import Card from 'component/common/card';
|
||||
|
|
|
@ -7,7 +7,6 @@ import ModalDownloading from 'modal/modalDownloading';
|
|||
import ModalAutoGenerateThumbnail from 'modal/modalAutoGenerateThumbnail';
|
||||
import ModalAutoUpdateDownloaded from 'modal/modalAutoUpdateDownloaded';
|
||||
import ModalUpgrade from 'modal/modalUpgrade';
|
||||
import ModalWelcome from 'modal/modalWelcome';
|
||||
import ModalFirstReward from 'modal/modalFirstReward';
|
||||
import ModalRemoveFile from 'modal/modalRemoveFile';
|
||||
import ModalTransactionFailed from 'modal/modalTransactionFailed';
|
||||
|
@ -80,8 +79,6 @@ function ModalRouter(props: Props) {
|
|||
return <ModalError {...modalProps} />;
|
||||
case MODALS.FILE_TIMEOUT:
|
||||
return <ModalFileTimeout {...modalProps} />;
|
||||
case MODALS.WELCOME:
|
||||
return <ModalWelcome {...modalProps} />;
|
||||
case MODALS.FIRST_REWARD:
|
||||
return <ModalFirstReward {...modalProps} />;
|
||||
case MODALS.TRANSACTION_FAILED:
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import * as settings from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { doHideModal } from 'redux/actions/app';
|
||||
import { doSetClientSetting } from 'redux/actions/settings';
|
||||
import ModalWelcome from './view';
|
||||
|
||||
const perform = dispatch => () => ({
|
||||
closeModal: () => {
|
||||
dispatch(doSetClientSetting(settings.NEW_USER_ACKNOWLEDGED, true));
|
||||
dispatch(doHideModal());
|
||||
},
|
||||
});
|
||||
|
||||
export default connect(
|
||||
null,
|
||||
perform
|
||||
)(ModalWelcome);
|
|
@ -1,28 +0,0 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { Modal } from 'modal/modal';
|
||||
import Button from 'component/button';
|
||||
|
||||
type Props = {
|
||||
closeModal: () => void,
|
||||
};
|
||||
|
||||
const ModalWelcome = (props: Props) => {
|
||||
const { closeModal } = props;
|
||||
|
||||
return (
|
||||
<Modal type="custom" isOpen contentLabel="Welcome to LBRY" title={__('Welcome to LBRY')}>
|
||||
<p>
|
||||
{__('Using LBRY is like dating a centaur. Totally normal up top, and')} <em>{__('way different')}</em>{' '}
|
||||
{__('underneath.')}
|
||||
</p>
|
||||
<p>{__('Up top, LBRY is similar to popular media sites.')}</p>
|
||||
<p>{__('Below, LBRY is controlled by users -- you -- via blockchain and decentralization.')}</p>
|
||||
<div className="card__actions">
|
||||
<Button button="primary" onClick={closeModal} label={__("I'm In")} />
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModalWelcome;
|
|
@ -69,8 +69,8 @@ function ChannelPage(props: Props) {
|
|||
const urlParams = new URLSearchParams(search);
|
||||
const currentView = urlParams.get(PAGE_VIEW_QUERY) || undefined;
|
||||
const editInUrl = urlParams.get(PAGE_VIEW_QUERY) === EDIT_PAGE;
|
||||
const [editing, setEditing] = React.useState(editInUrl);
|
||||
const [discussionWasMounted, setDiscussionWasMounted] = React.useState(false);
|
||||
const editing = urlParams.get(PAGE_VIEW_QUERY) === EDIT_PAGE;
|
||||
const { channelName } = parseURI(uri);
|
||||
const { permanent_url: permanentUrl } = claim;
|
||||
const claimId = claim.claim_id;
|
||||
|
@ -103,35 +103,12 @@ function ChannelPage(props: Props) {
|
|||
push(`${url}${search}`);
|
||||
}
|
||||
|
||||
function onDone() {
|
||||
setEditing(false);
|
||||
goBack();
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (currentView === DISCUSSION_PAGE) {
|
||||
setDiscussionWasMounted(true);
|
||||
}
|
||||
}, [currentView]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!channelIsMine && editing) {
|
||||
setEditing(false);
|
||||
}
|
||||
|
||||
if (channelIsMine && editing) {
|
||||
push(`?${PAGE_VIEW_QUERY}=${EDIT_PAGE}`);
|
||||
}
|
||||
}, [channelIsMine, editing, push]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (currentView === EDIT_PAGE) {
|
||||
setEditing(true);
|
||||
} else {
|
||||
setEditing(false);
|
||||
}
|
||||
}, [currentView, setEditing]);
|
||||
|
||||
React.useEffect(() => {
|
||||
fetchSubCount(claimId);
|
||||
}, [uri, fetchSubCount, claimId]);
|
||||
|
@ -142,12 +119,11 @@ function ChannelPage(props: Props) {
|
|||
noFooter
|
||||
noSideNavigation={editing}
|
||||
backout={{
|
||||
backFunction: onDone,
|
||||
title: __('Editing @%channel%', { channel: channelName }),
|
||||
simpleTitle: __('Editing'),
|
||||
}}
|
||||
>
|
||||
<ChannelEdit uri={uri} onDone={onDone} />
|
||||
<ChannelEdit uri={uri} onDone={() => goBack()} />
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
@ -190,7 +166,7 @@ function ChannelPage(props: Props) {
|
|||
<Button
|
||||
button="alt"
|
||||
title={__('Edit')}
|
||||
onClick={() => setEditing(!editing)}
|
||||
onClick={() => push(`?${PAGE_VIEW_QUERY}=${EDIT_PAGE}`)}
|
||||
icon={ICONS.EDIT}
|
||||
iconSize={18}
|
||||
disabled={pending}
|
||||
|
|
|
@ -12,11 +12,7 @@ type Props = {
|
|||
function ChannelNew(props: Props) {
|
||||
const { history } = props;
|
||||
return (
|
||||
<Page
|
||||
noSideNavigation
|
||||
backout={{ backFunction: () => history.goBack(), title: __('Create Channel') }}
|
||||
className="main--auth-page"
|
||||
>
|
||||
<Page noSideNavigation backout={{ title: __('Create Channel') }} className="main--auth-page">
|
||||
<ChannelEdit onDone={() => history.push(`/$/${PAGES.CHANNELS}`)} />
|
||||
</Page>
|
||||
);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
selectUserInviteStatusFailed,
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
import { connect } from 'react-redux';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { doSearch, selectIsSearching, makeSelectSearchUris, makeSelectQueryWithOptions, doToast } from 'lbry-redux';
|
||||
import {
|
||||
doSearch,
|
||||
selectIsSearching,
|
||||
makeSelectSearchUris,
|
||||
makeSelectQueryWithOptions,
|
||||
doToast,
|
||||
SETTINGS,
|
||||
} from 'lbry-redux';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import analytics from 'analytics';
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
doSetClientSetting,
|
||||
doSetDarkTime,
|
||||
doFindFFmpeg,
|
||||
doSyncClientSettings,
|
||||
} from 'redux/actions/settings';
|
||||
import { doSetPlayingUri } from 'redux/actions/content';
|
||||
import {
|
||||
|
@ -48,10 +49,12 @@ const select = state => ({
|
|||
ffmpegStatus: selectFfmpegStatus(state),
|
||||
findingFFmpeg: selectFindingFFmpeg(state),
|
||||
language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state),
|
||||
syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
setDaemonSetting: (key, value) => dispatch(doSetDaemonSetting(key, value)),
|
||||
syncSettings: () => dispatch(doSyncClientSettings()),
|
||||
clearDaemonSetting: key => dispatch(doClearDaemonSetting(key)),
|
||||
toggle3PAnalytics: allow => dispatch(doToggle3PAnalytics(allow)),
|
||||
clearCache: () => dispatch(doClearCache()),
|
||||
|
|
|
@ -22,6 +22,7 @@ import { getPasswordFromCookie } from 'util/saved-passwords';
|
|||
import Spinner from 'component/spinner';
|
||||
import SettingAccountPassword from 'component/settingAccountPassword';
|
||||
import { Lbryio } from 'lbryinc';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
// @if TARGET='app'
|
||||
export const IS_MAC = process.platform === 'darwin';
|
||||
|
@ -88,6 +89,9 @@ type Props = {
|
|||
findFFmpeg: () => void,
|
||||
openModal: string => void,
|
||||
language?: string,
|
||||
history: { goBack: () => void },
|
||||
syncEnabled: boolean,
|
||||
syncSettings: () => void,
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
@ -112,6 +116,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
(this: any).onAutomaticDarkModeChange = this.onAutomaticDarkModeChange.bind(this);
|
||||
(this: any).onChangeTime = this.onChangeTime.bind(this);
|
||||
(this: any).onConfirmForgetPassword = this.onConfirmForgetPassword.bind(this);
|
||||
(this: any).onDone = this.onDone.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -136,6 +141,14 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
onDone() {
|
||||
const { syncSettings } = this.props;
|
||||
|
||||
if (this.props.syncEnabled) {
|
||||
syncSettings();
|
||||
}
|
||||
}
|
||||
|
||||
onFFmpegFolder(path: string) {
|
||||
this.setDaemonSetting('ffmpeg_path', path);
|
||||
this.findFFmpeg();
|
||||
|
@ -262,7 +275,16 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
const endHours = ['5', '6', '7', '8'];
|
||||
|
||||
return (
|
||||
<Page className="card-stack">
|
||||
<Page
|
||||
noFooter
|
||||
noSideNavigation
|
||||
backout={{
|
||||
backCB: () => this.onDone(),
|
||||
title: __('Settings'),
|
||||
backLabel: __('Done'),
|
||||
}}
|
||||
className="card-stack"
|
||||
>
|
||||
{!IS_WEB && noDaemonSettings ? (
|
||||
<section className="card card--section">
|
||||
<div className="card__title card__title--deprecated">{__('Failed to load settings.')}</div>
|
||||
|
@ -820,4 +842,4 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
export default SettingsPage;
|
||||
export default withRouter(SettingsPage);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// @flow
|
||||
import * as ICONS from 'constants/icons';
|
||||
import * as PAGES from 'constants/pages';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import * as React from 'react';
|
||||
|
||||
import Page from 'component/page';
|
||||
|
@ -12,6 +11,7 @@ import { useHistory } from 'react-router';
|
|||
import { Redirect } from 'react-router-dom';
|
||||
import Yrbl from 'component/yrbl';
|
||||
import Button from 'component/button';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
|
||||
type Props = {
|
||||
osNotificationsEnabled: boolean,
|
||||
|
@ -94,7 +94,7 @@ export default function NotificationSettingsPage(props: Props) {
|
|||
}
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Page backout={{ title: __('Manage Notifications'), backLabel: __('Done') }} noFooter noSideNavigation>
|
||||
{error ? (
|
||||
<Yrbl
|
||||
type="sad"
|
||||
|
|
|
@ -19,14 +19,15 @@ import {
|
|||
doPreferenceGet,
|
||||
doClearSupport,
|
||||
selectFollowedTagsList,
|
||||
// SHARED_PREFERENCES,
|
||||
SHARED_PREFERENCES,
|
||||
DAEMON_SETTINGS,
|
||||
} from 'lbry-redux';
|
||||
import { doToast, doError, doNotificationList } from 'redux/actions/notifications';
|
||||
import Native from 'native';
|
||||
import {
|
||||
doFetchDaemonSettings,
|
||||
doSetAutoLaunch,
|
||||
// doSetDaemonSetting
|
||||
doSetDaemonSetting,
|
||||
doFindFFmpeg,
|
||||
doGetDaemonStatus,
|
||||
} from 'redux/actions/settings';
|
||||
|
@ -42,6 +43,7 @@ import {
|
|||
selectModal,
|
||||
selectAllowAnalytics,
|
||||
} from 'redux/selectors/app';
|
||||
import { selectDaemonSettings } from 'redux/selectors/settings';
|
||||
import { selectUser } from 'redux/selectors/user';
|
||||
// import { selectDaemonSettings } from 'redux/selectors/settings';
|
||||
import { doGetSync } from 'lbryinc';
|
||||
|
@ -50,6 +52,7 @@ import { lbrySettings as config, version as appVersion } from 'package.json';
|
|||
import analytics, { SHARE_INTERNAL } from 'analytics';
|
||||
import { doSignOutCleanup, deleteSavedPassword, getSavedPassword } from 'util/saved-passwords';
|
||||
import { doSocketConnect } from 'redux/actions/websocket';
|
||||
import { stringifyServerParam, shouldSetSetting } from 'util/sync-settings';
|
||||
|
||||
// @if TARGET='app'
|
||||
const { autoUpdater } = remote.require('electron-updater');
|
||||
|
@ -530,6 +533,13 @@ export function doSetWelcomeVersion(version) {
|
|||
};
|
||||
}
|
||||
|
||||
export function doSetHasNavigated() {
|
||||
return {
|
||||
type: ACTIONS.SET_HAS_NAVIGATED,
|
||||
data: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function doToggle3PAnalytics(allowParam, doNotDispatch) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
|
@ -546,33 +556,38 @@ export function doToggle3PAnalytics(allowParam, doNotDispatch) {
|
|||
}
|
||||
|
||||
export function doGetAndPopulatePreferences() {
|
||||
const { SDK_SYNC_KEYS } = SHARED_PREFERENCES;
|
||||
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
// @if TARGET='app'
|
||||
const preferenceKey = state.user && state.user.user && state.user.user.has_verified_email ? 'shared' : 'anon';
|
||||
// @endif
|
||||
// @if TARGET='web'
|
||||
const preferenceKey = 'shared';
|
||||
// @endif
|
||||
|
||||
function successCb(savedPreferences) {
|
||||
// const state = getState();
|
||||
// const daemonSettings = selectDaemonSettings(state);
|
||||
const successState = getState();
|
||||
const daemonSettings = selectDaemonSettings(successState);
|
||||
|
||||
if (savedPreferences !== null) {
|
||||
dispatch(doPopulateSharedUserState(savedPreferences));
|
||||
// @if TARGET='app'
|
||||
// const { settings, sharing_3P: sharing3P } = savedPreferences.value;
|
||||
// // apply daemonSettings (todo: separate function)
|
||||
// Object.entries(settings).forEach(([key, val]) => {
|
||||
// if (val !== null && daemonSettings[key] !== val) {
|
||||
// if (key === SHARED_PREFERENCES.WALLET_SERVERS) {
|
||||
// const hasSavedServers = Array.isArray(val) && val.length > 0;
|
||||
// if (hasSavedServers) {
|
||||
// // Ignore this key if there are no actual saved servers in the list
|
||||
// const servers = val.map(item => `${item[0]}:${item[1]}`);
|
||||
// dispatch(doSetDaemonSetting(key, servers, true));
|
||||
// }
|
||||
// } else {
|
||||
// dispatch(doSetDaemonSetting(key, val, true));
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// if (sharing3P !== undefined) {
|
||||
// doToggle3PAnalytics(sharing3P, true);
|
||||
// }
|
||||
|
||||
const { settings } = savedPreferences.value;
|
||||
Object.entries(settings).forEach(([key, val]) => {
|
||||
if (SDK_SYNC_KEYS.includes(key)) {
|
||||
if (shouldSetSetting(key, val, daemonSettings[key])) {
|
||||
if (key === DAEMON_SETTINGS.LBRYUM_SERVERS) {
|
||||
const servers = stringifyServerParam(val);
|
||||
dispatch(doSetDaemonSetting(key, servers, true));
|
||||
} else {
|
||||
dispatch(doSetDaemonSetting(key, val, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// @endif
|
||||
}
|
||||
}
|
||||
|
@ -588,7 +603,7 @@ export function doGetAndPopulatePreferences() {
|
|||
});
|
||||
}
|
||||
|
||||
doPreferenceGet('shared', successCb, failCb);
|
||||
doPreferenceGet(preferenceKey, successCb, failCb);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// @flow
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import * as NOTIFICATION_TYPES from 'constants/subscriptions';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
// @if TARGET='app'
|
||||
|
@ -12,6 +11,7 @@ import { doUpdateUnreadSubscriptions } from 'redux/actions/subscriptions';
|
|||
import { makeSelectUnreadByChannel } from 'redux/selectors/subscriptions';
|
||||
import {
|
||||
Lbry,
|
||||
SETTINGS,
|
||||
makeSelectFileInfoForUri,
|
||||
selectFileInfosByOutpoint,
|
||||
makeSelectChannelForClaimUri,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Lbry, ACTIONS, SHARED_PREFERENCES, doWalletReconnect, SETTINGS } from 'lbry-redux';
|
||||
import { Lbry, ACTIONS, SHARED_PREFERENCES, doWalletReconnect, SETTINGS, DAEMON_SETTINGS } from 'lbry-redux';
|
||||
import { doToast } from 'redux/actions/notifications';
|
||||
import * as LOCAL_ACTIONS from 'constants/action_types';
|
||||
import analytics from 'analytics';
|
||||
|
@ -6,6 +6,7 @@ import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
|||
import { launcher } from 'util/autoLaunch';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
const { DEFAULT_LANGUAGE } = require('config');
|
||||
const { SDK_SYNC_KEYS } = SHARED_PREFERENCES;
|
||||
|
||||
export const IS_MAC = process.platform === 'darwin';
|
||||
const UPDATE_IS_NIGHT_INTERVAL = 5 * 60 * 1000;
|
||||
|
@ -58,13 +59,13 @@ export function doClearDaemonSetting(key) {
|
|||
key,
|
||||
};
|
||||
Lbry.settings_clear(clearKey).then(defaultSettings => {
|
||||
if (Object.values(SHARED_PREFERENCES).includes(key)) {
|
||||
if (SDK_SYNC_KEYS.includes(key)) {
|
||||
dispatch({
|
||||
type: ACTIONS.SHARED_PREFERENCE_SET,
|
||||
data: { key: key, value: null },
|
||||
});
|
||||
}
|
||||
if (key === SHARED_PREFERENCES.WALLET_SERVERS) {
|
||||
if (key === DAEMON_SETTINGS.LBRYUM_SERVERS) {
|
||||
dispatch(doWalletReconnect());
|
||||
}
|
||||
});
|
||||
|
@ -87,14 +88,14 @@ export function doSetDaemonSetting(key, value, doNotDispatch = false) {
|
|||
value: !value && value !== false ? null : value,
|
||||
};
|
||||
Lbry.settings_set(newSettings).then(newSetting => {
|
||||
if (Object.values(SHARED_PREFERENCES).includes(key) && !doNotDispatch) {
|
||||
if (SDK_SYNC_KEYS.includes(key) && !doNotDispatch) {
|
||||
dispatch({
|
||||
type: ACTIONS.SHARED_PREFERENCE_SET,
|
||||
data: { key: key, value: newSetting[key] },
|
||||
});
|
||||
}
|
||||
// hardcoding this in lieu of a better solution
|
||||
if (key === SHARED_PREFERENCES.WALLET_SERVERS) {
|
||||
if (key === DAEMON_SETTINGS.LBRYUM_SERVERS) {
|
||||
dispatch(doWalletReconnect());
|
||||
// todo: add sdk reloadsettings() (or it happens automagically?)
|
||||
}
|
||||
|
@ -166,6 +167,12 @@ export function doSetDarkTime(value, options) {
|
|||
};
|
||||
}
|
||||
|
||||
export function doSyncClientSettings() {
|
||||
return {
|
||||
type: LOCAL_ACTIONS.SYNC_CLIENT_SETTINGS,
|
||||
};
|
||||
}
|
||||
|
||||
export function doFetchLanguage(language) {
|
||||
return (dispatch, getState) => {
|
||||
const { settings } = getState();
|
||||
|
|
|
@ -41,6 +41,7 @@ export type AppState = {
|
|||
isPasswordSaved: boolean,
|
||||
welcomeVersion: number,
|
||||
allowAnalytics: boolean,
|
||||
hasNavigated: boolean,
|
||||
};
|
||||
|
||||
const defaultState: AppState = {
|
||||
|
@ -74,6 +75,7 @@ const defaultState: AppState = {
|
|||
isPasswordSaved: false,
|
||||
welcomeVersion: 0.0,
|
||||
allowAnalytics: false,
|
||||
hasNavigated: false,
|
||||
};
|
||||
|
||||
// @@router comes from react-router
|
||||
|
@ -86,7 +88,6 @@ reducers['@@router/LOCATION_CHANGE'] = (state, action) => {
|
|||
const { currentScroll } = state;
|
||||
const scrollHistory = (state.scrollHistory && state.scrollHistory.slice()) || [];
|
||||
const { action: name } = action.payload;
|
||||
|
||||
let newCurrentScroll = currentScroll;
|
||||
if (name === 'PUSH') {
|
||||
scrollHistory.push(window.scrollY);
|
||||
|
@ -265,6 +266,11 @@ reducers[ACTIONS.SET_ALLOW_ANALYTICS] = (state, action) =>
|
|||
allowAnalytics: action.data,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.SET_HAS_NAVIGATED] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
hasNavigated: action.data,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.HIDE_MODAL] = state =>
|
||||
Object.assign({}, state, {
|
||||
modal: null,
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as APP_SETTINGS from 'constants/settings';
|
||||
import moment from 'moment';
|
||||
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
||||
import { ACTIONS as LBRY_REDUX_ACTIONS, SETTINGS } from 'lbry-redux';
|
||||
import { ACTIONS as LBRY_REDUX_ACTIONS, SETTINGS, SHARED_PREFERENCES } from 'lbry-redux';
|
||||
import { getSubsetFromKeysArray } from 'util/sync-settings';
|
||||
const { CLIENT_SYNC_KEYS } = SHARED_PREFERENCES;
|
||||
|
||||
const reducers = {};
|
||||
let settingLanguage = [];
|
||||
try {
|
||||
|
@ -22,7 +24,6 @@ const defaultState = {
|
|||
daemonStatus: { ffmpeg_status: {} },
|
||||
clientSettings: {
|
||||
// UX
|
||||
[SETTINGS.NEW_USER_ACKNOWLEDGED]: false,
|
||||
[SETTINGS.EMAIL_COLLECTION_ACKNOWLEDGED]: false,
|
||||
[SETTINGS.ENABLE_SYNC]: true,
|
||||
|
||||
|
@ -35,7 +36,7 @@ const defaultState = {
|
|||
[SETTINGS.OS_NOTIFICATIONS_ENABLED]: true,
|
||||
[SETTINGS.AUTOMATIC_DARK_MODE_ENABLED]: false,
|
||||
|
||||
[APP_SETTINGS.DARK_MODE_TIMES]: {
|
||||
[SETTINGS.DARK_MODE_TIMES]: {
|
||||
from: { hour: '21', min: '00', formattedTime: '21:00' },
|
||||
to: { hour: '8', min: '00', formattedTime: '8:00' },
|
||||
},
|
||||
|
@ -50,6 +51,7 @@ const defaultState = {
|
|||
// Content
|
||||
[SETTINGS.SHOW_MATURE]: false,
|
||||
[SETTINGS.AUTOPLAY]: true,
|
||||
[SETTINGS.AUTOPLAY_NEXT]: true,
|
||||
[SETTINGS.FLOATING_PLAYER]: true,
|
||||
[SETTINGS.AUTO_DOWNLOAD]: true,
|
||||
[SETTINGS.HIDE_REPOSTS]: false,
|
||||
|
@ -59,6 +61,25 @@ const defaultState = {
|
|||
},
|
||||
};
|
||||
|
||||
reducers[ACTIONS.REHYDRATE] = (state, action) => {
|
||||
const { clientSettings } = state;
|
||||
if (action && action.payload && action.payload.settings) {
|
||||
const persistedSettings = action.payload && action.payload.settings;
|
||||
const persistedClientSettings = persistedSettings.clientSettings;
|
||||
const newClientSettings = { ...clientSettings, ...persistedClientSettings };
|
||||
return Object.assign({}, state, { ...persistedSettings, clientSettings: newClientSettings });
|
||||
}
|
||||
return Object.assign({}, state, { clientSettings });
|
||||
};
|
||||
|
||||
reducers[ACTIONS.SYNC_CLIENT_SETTINGS] = state => {
|
||||
const { clientSettings } = state;
|
||||
const sharedPreferences = Object.assign({}, state.sharedPreferences);
|
||||
const selectedClientSettings = getSubsetFromKeysArray(clientSettings, CLIENT_SYNC_KEYS);
|
||||
const newSharedPreferences = { ...sharedPreferences, ...selectedClientSettings };
|
||||
return Object.assign({}, state, { sharedPreferences: newSharedPreferences });
|
||||
};
|
||||
|
||||
reducers[ACTIONS.FINDING_FFMPEG_STARTED] = state =>
|
||||
Object.assign({}, state, {
|
||||
findingFFmpeg: true,
|
||||
|
@ -91,7 +112,7 @@ reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => {
|
|||
};
|
||||
|
||||
reducers[ACTIONS.UPDATE_IS_NIGHT] = state => {
|
||||
const { from, to } = state.clientSettings[APP_SETTINGS.DARK_MODE_TIMES];
|
||||
const { from, to } = state.clientSettings[SETTINGS.DARK_MODE_TIMES];
|
||||
const momentNow = moment();
|
||||
const startNightMoment = moment(from.formattedTime, 'HH:mm');
|
||||
const endNightMoment = moment(to.formattedTime, 'HH:mm');
|
||||
|
@ -137,10 +158,14 @@ reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => {
|
|||
};
|
||||
|
||||
reducers[LBRY_REDUX_ACTIONS.USER_STATE_POPULATE] = (state, action) => {
|
||||
const { clientSettings: currentClientSettings } = state;
|
||||
const { settings: sharedPreferences } = action.data;
|
||||
// todo: populate sharedPreferences that match client settings constants
|
||||
|
||||
return Object.assign({}, state, { sharedPreferences });
|
||||
if (currentClientSettings[SETTINGS.ENABLE_SYNC]) {
|
||||
const selectedSettings = getSubsetFromKeysArray(sharedPreferences, CLIENT_SYNC_KEYS);
|
||||
const mergedClientSettings = { ...currentClientSettings, ...selectedSettings };
|
||||
return Object.assign({}, state, { sharedPreferences, clientSettings: mergedClientSettings });
|
||||
}
|
||||
return Object.assign({}, state, { sharedPreferences, clientSettings: currentClientSettings });
|
||||
};
|
||||
|
||||
reducers[LBRY_REDUX_ACTIONS.SAVE_CUSTOM_WALLET_SERVERS] = (state, action) => {
|
||||
|
|
|
@ -73,6 +73,8 @@ export const selectSearchOptionsExpanded = createSelector(selectState, state =>
|
|||
|
||||
export const selectWelcomeVersion = createSelector(selectState, state => state.welcomeVersion);
|
||||
|
||||
export const selectHasNavigated = createSelector(selectState, state => state.hasNavigated);
|
||||
|
||||
export const selectAllowAnalytics = createSelector(selectState, state => state.allowAnalytics);
|
||||
|
||||
export const selectScrollStartingPosition = createSelector(selectState, state => state.currentScroll);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { SHARED_PREFERENCES, SETTINGS as LBRY_REDUX_SETTINGS } from 'lbry-redux';
|
||||
import { SETTINGS, DAEMON_SETTINGS } from 'lbry-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
const selectState = state => state.settings || {};
|
||||
|
@ -20,10 +19,10 @@ export const makeSelectClientSetting = setting =>
|
|||
createSelector(selectClientSettings, settings => (settings ? settings[setting] : undefined));
|
||||
|
||||
// refactor me
|
||||
export const selectShowMatureContent = makeSelectClientSetting(LBRY_REDUX_SETTINGS.SHOW_MATURE);
|
||||
export const selectShowMatureContent = makeSelectClientSetting(SETTINGS.SHOW_MATURE);
|
||||
|
||||
// and me
|
||||
export const selectShowRepostedContent = makeSelectClientSetting(LBRY_REDUX_SETTINGS.HIDE_REPOSTS);
|
||||
export const selectShowRepostedContent = makeSelectClientSetting(SETTINGS.HIDE_REPOSTS);
|
||||
|
||||
export const selectTheme = makeSelectClientSetting(SETTINGS.THEME);
|
||||
export const selectAutomaticDarkModeEnabled = makeSelectClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED);
|
||||
|
@ -37,7 +36,7 @@ export const makeSelectSharedPreferencesForKey = key =>
|
|||
createSelector(selectSharedPreferences, prefs => (prefs ? prefs[key] : undefined));
|
||||
|
||||
export const selectHasWalletServerPrefs = createSelector(
|
||||
makeSelectSharedPreferencesForKey(SHARED_PREFERENCES.WALLET_SERVERS),
|
||||
makeSelectSharedPreferencesForKey(DAEMON_SETTINGS.LBRYUM_SERVERS),
|
||||
servers => {
|
||||
return !!(servers && servers.length);
|
||||
}
|
||||
|
|
|
@ -120,8 +120,9 @@ const triggerSharedStateActions = [
|
|||
ACTIONS.TOGGLE_BLOCK_CHANNEL,
|
||||
LBRY_REDUX_ACTIONS.TOGGLE_TAG_FOLLOW,
|
||||
LBRY_REDUX_ACTIONS.CREATE_CHANNEL_COMPLETED,
|
||||
ACTIONS.SYNC_CLIENT_SETTINGS,
|
||||
// Disabled until we can overwrite preferences
|
||||
// LBRY_REDUX_ACTIONS.SHARED_PREFERENCE_SET,
|
||||
LBRY_REDUX_ACTIONS.SHARED_PREFERENCE_SET,
|
||||
// ACTIONS.SET_WELCOME_VERSION,
|
||||
// ACTIONS.SET_ALLOW_ANALYTICS,
|
||||
];
|
||||
|
|
26
ui/util/sync-settings.js
Normal file
26
ui/util/sync-settings.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { DAEMON_SETTINGS } from 'lbry-redux';
|
||||
import isEqual from 'util/deep-equal';
|
||||
|
||||
export function stringifyServerParam(configList) {
|
||||
return configList.reduce((acc, cur) => {
|
||||
acc.push(`${cur[0]}:${cur[1]}`);
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
export const getSubsetFromKeysArray = (obj, keys) =>
|
||||
Object.keys(obj)
|
||||
.filter(i => keys.includes(i))
|
||||
.reduce((acc, key) => {
|
||||
acc[key] = obj[key];
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
export const shouldSetSetting = (key, val, current) => {
|
||||
switch (key) {
|
||||
case DAEMON_SETTINGS.LBRYUM_SERVERS:
|
||||
return val !== null && Array.isArray(val) && val.length && !isEqual(val, current);
|
||||
default:
|
||||
return !isEqual(val, current);
|
||||
}
|
||||
};
|
|
@ -6385,9 +6385,9 @@ lazy-val@^1.0.4:
|
|||
yargs "^13.2.2"
|
||||
zstd-codec "^0.1.1"
|
||||
|
||||
lbry-redux@lbryio/lbry-redux#5547f53f487dacf8c89202ad18f7d2123668be85:
|
||||
lbry-redux@lbryio/lbry-redux#52dd14bf9a22d06e34fdb4bf2004129041dbb949:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/5547f53f487dacf8c89202ad18f7d2123668be85"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/52dd14bf9a22d06e34fdb4bf2004129041dbb949"
|
||||
dependencies:
|
||||
proxy-polyfill "0.1.6"
|
||||
reselect "^3.0.0"
|
||||
|
|
Loading…
Reference in a new issue