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:
jessop 2020-07-10 17:04:36 -04:00 committed by Sean Yesmunt
parent e001906443
commit d9bf72a351
50 changed files with 287 additions and 191 deletions

View file

@ -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",

View file

@ -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--"
}

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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),

View file

@ -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';

View file

@ -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';

View file

@ -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,

View file

@ -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';

View file

@ -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 => ({

View file

@ -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();

View file

@ -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) {

View file

@ -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);

View file

@ -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);

View file

@ -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),

View file

@ -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';

View file

@ -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);

View file

@ -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')}

View file

@ -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';

View file

@ -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 => ({

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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;

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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:

View file

@ -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);

View file

@ -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;

View file

@ -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}

View file

@ -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>
);

View file

@ -1,4 +1,4 @@
import * as SETTINGS from 'constants/settings';
import { SETTINGS } from 'lbry-redux';
import { connect } from 'react-redux';
import {
selectUserInviteStatusFailed,

View file

@ -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';

View file

@ -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()),

View file

@ -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);

View file

@ -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"

View file

@ -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);
};
}

View file

@ -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,

View file

@ -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();

View file

@ -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,

View file

@ -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) => {

View file

@ -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);

View file

@ -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);
}

View file

@ -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
View 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);
}
};

View file

@ -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"