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