fix sync clean wallet bug
remove previous changes,keep syncpref in wallet, change anon wallet pref key to local sync choices wip dont relocate syncenable setting bump no prefs on web unauth bugfix redux bump pull after sync change bump
This commit is contained in:
parent
2ad7088553
commit
3b23f09bed
25 changed files with 402 additions and 105 deletions
|
@ -136,7 +136,7 @@
|
|||
"imagesloaded": "^4.1.4",
|
||||
"json-loader": "^0.5.4",
|
||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||
"lbry-redux": "lbryio/lbry-redux#437c54f164b4132c0d5c6ede60c7b02703f1e9d5",
|
||||
"lbry-redux": "lbryio/lbry-redux#e10295b5ec2ef42426755ed9fd50bd250b0d76dd",
|
||||
"lbryinc": "lbryio/lbryinc#9440717a00d2fbb2e3226aaa2388f4698f324be2",
|
||||
"lint-staged": "^7.0.2",
|
||||
"localforage": "^1.7.1",
|
||||
|
|
|
@ -1292,5 +1292,20 @@
|
|||
"%comment_count% comments - %comment_count_change% this week": "%comment_count% comments - %comment_count_change% this week",
|
||||
"Invite": "Invite",
|
||||
"Remove File": "Remove File",
|
||||
"You are currently following %followingCount% tag": "You are currently following %followingCount% tag",
|
||||
"DO a thing": "DO a thing",
|
||||
"DO IT": "DO IT",
|
||||
"Not Yet": "Not Yet",
|
||||
"I understand": "I understand",
|
||||
"Enabling Sync": "Enabling Sync",
|
||||
"Enable Sync": "Enable Sync",
|
||||
"Bring my stuff!": "Bring my stuff!",
|
||||
"Disable Sync": "Disable Sync",
|
||||
"Enable": "Enable",
|
||||
"Continuing will import the profile in your cloud wallet into your local wallet.": "Continuing will import the profile in your cloud wallet into your local wallet.",
|
||||
"": "",
|
||||
"Getting your profiles...": "Getting your profiles...",
|
||||
"Enabling sync will switch to your cloud profile.": "Enabling sync will switch to your cloud profile.",
|
||||
"Disabling sync will switch to your local profile.": "Disabling sync will switch to your local profile.",
|
||||
"--end--": "--end--"
|
||||
}
|
||||
|
|
|
@ -5,14 +5,9 @@ import { doFetchAccessToken, doUserSetReferrer } from 'redux/actions/user';
|
|||
import { selectUser, selectAccessToken, selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import { selectUnclaimedRewards } from 'redux/selectors/rewards';
|
||||
import { doFetchChannelListMine, SETTINGS } from 'lbry-redux';
|
||||
import {
|
||||
makeSelectClientSetting,
|
||||
selectLoadedLanguages,
|
||||
selectSyncSigninPref,
|
||||
selectThemePath,
|
||||
} from 'redux/selectors/settings';
|
||||
import { makeSelectClientSetting, selectLoadedLanguages, selectThemePath } from 'redux/selectors/settings';
|
||||
import { selectIsUpgradeAvailable, selectAutoUpdateDownloaded } from 'redux/selectors/app';
|
||||
import { doSetLanguage, doUpdateSyncPrefIfFalse } from 'redux/actions/settings';
|
||||
import { doGetWalletSyncPreference, doSetLanguage } from 'redux/actions/settings';
|
||||
import { doSyncSubscribe } from 'redux/actions/syncwrapper';
|
||||
import {
|
||||
doDownloadUpgradeRequested,
|
||||
|
@ -35,7 +30,6 @@ const select = state => ({
|
|||
uploadCount: selectUploadCount(state),
|
||||
rewards: selectUnclaimedRewards(state),
|
||||
isAuthenticated: selectUserVerifiedEmail(state),
|
||||
signInSyncPref: selectSyncSigninPref(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
@ -46,7 +40,7 @@ const perform = dispatch => ({
|
|||
signIn: () => dispatch(doSignIn()),
|
||||
requestDownloadUpgrade: () => dispatch(doDownloadUpgradeRequested()),
|
||||
updatePreferences: () => dispatch(doGetAndPopulatePreferences()),
|
||||
pushPrefsIfSyncFalse: () => dispatch(doUpdateSyncPrefIfFalse()),
|
||||
getWalletSyncPref: () => dispatch(doGetWalletSyncPreference()),
|
||||
syncSubscribe: () => dispatch(doSyncSubscribe()),
|
||||
setReferrer: (referrer, doClaim) => dispatch(doUserSetReferrer(referrer, doClaim)),
|
||||
});
|
||||
|
|
|
@ -67,7 +67,7 @@ type Props = {
|
|||
isUpgradeAvailable: boolean,
|
||||
autoUpdateDownloaded: boolean,
|
||||
updatePreferences: () => Promise<any>,
|
||||
pushPrefsIfSyncFalse: () => void,
|
||||
getWalletSyncPref: () => Promise<any>,
|
||||
uploadCount: number,
|
||||
balance: ?number,
|
||||
syncError: ?string,
|
||||
|
@ -79,7 +79,6 @@ type Props = {
|
|||
socketConnect: () => void,
|
||||
syncSubscribe: () => void,
|
||||
syncEnabled: boolean,
|
||||
signInSyncPref: boolean,
|
||||
};
|
||||
|
||||
function App(props: Props) {
|
||||
|
@ -99,12 +98,11 @@ function App(props: Props) {
|
|||
languages,
|
||||
setLanguage,
|
||||
updatePreferences,
|
||||
pushPrefsIfSyncFalse,
|
||||
getWalletSyncPref,
|
||||
rewards,
|
||||
setReferrer,
|
||||
isAuthenticated,
|
||||
syncSubscribe,
|
||||
signInSyncPref,
|
||||
} = props;
|
||||
|
||||
const appRef = useRef();
|
||||
|
@ -112,7 +110,7 @@ function App(props: Props) {
|
|||
const [hasSignedIn, setHasSignedIn] = useState(false);
|
||||
const [readyForSync, setReadyForSync] = useState(false);
|
||||
const [readyForPrefs, setReadyForPrefs] = useState(false);
|
||||
const hasVerifiedEmail = user && user.has_verified_email;
|
||||
const hasVerifiedEmail = user && Boolean(user.has_verified_email);
|
||||
const isRewardApproved = user && user.is_reward_approved;
|
||||
const previousHasVerifiedEmail = usePrevious(hasVerifiedEmail);
|
||||
const previousRewardApproved = usePrevious(isRewardApproved);
|
||||
|
@ -235,34 +233,26 @@ function App(props: Props) {
|
|||
|
||||
// @if TARGET='app'
|
||||
useEffect(() => {
|
||||
if (updatePreferences && readyForPrefs) {
|
||||
updatePreferences().then(() => {
|
||||
// will pull and U_S_P; usp will make sure prefBox applied if false
|
||||
setReadyForSync(true);
|
||||
});
|
||||
if (updatePreferences && getWalletSyncPref && readyForPrefs) {
|
||||
getWalletSyncPref()
|
||||
.then(() => updatePreferences())
|
||||
.then(() => {
|
||||
setReadyForSync(true);
|
||||
});
|
||||
}
|
||||
}, [updatePreferences, setReadyForSync, readyForPrefs, hasVerifiedEmail]);
|
||||
}, [updatePreferences, getWalletSyncPref, setReadyForSync, readyForPrefs, hasVerifiedEmail]);
|
||||
// @endif
|
||||
|
||||
// ready for sync syncs, however after signin when hasVerifiedEmail, that syncs too.
|
||||
useEffect(() => {
|
||||
// signInSyncPref is cleared after sharedState loop.
|
||||
if (readyForSync && hasVerifiedEmail && signInSyncPref === undefined) {
|
||||
// On sign-in, we get and apply all the information on whether to sync
|
||||
// the checkbox, previous wallet settings, store rehydrate, etc
|
||||
// Our app is up to date with the wallet
|
||||
// Because the checkbox is applied last, make sure the wallet remembers if false:
|
||||
// @if TARGET='app'
|
||||
pushPrefsIfSyncFalse();
|
||||
// @endif
|
||||
|
||||
// And try this in case we are syncing.
|
||||
if (readyForSync && hasVerifiedEmail) {
|
||||
// In case we are syncing.
|
||||
syncSubscribe();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [readyForSync, hasVerifiedEmail, signInSyncPref, pushPrefsIfSyncFalse, syncSubscribe]);
|
||||
}, [readyForSync, hasVerifiedEmail, syncSubscribe]);
|
||||
|
||||
// We know someone is logging in or not when we get their user object {}
|
||||
// We know someone is logging in or not when we get their user object
|
||||
// We'll use this to determine when it's time to pull preferences
|
||||
// This will no longer work if desktop users no longer get a user object from lbryinc
|
||||
useEffect(() => {
|
||||
|
|
34
ui/component/syncEnableFlow/index.js
Normal file
34
ui/component/syncEnableFlow/index.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { SETTINGS } from 'lbry-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import {
|
||||
selectGetSyncErrorMessage,
|
||||
selectHasSyncedWallet,
|
||||
selectGetSyncIsPending,
|
||||
selectHashChanged,
|
||||
doCheckSync,
|
||||
doGetSync,
|
||||
} from 'lbryinc';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { doSetWalletSyncPreference } from 'redux/actions/settings';
|
||||
import SyncToggle from './view';
|
||||
import { doGetAndPopulatePreferences } from 'redux/actions/app';
|
||||
|
||||
const select = state => ({
|
||||
syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state),
|
||||
hasSyncedWallet: selectHasSyncedWallet(state),
|
||||
hasSyncChanged: selectHashChanged(state),
|
||||
verifiedEmail: selectUserVerifiedEmail(state),
|
||||
getSyncError: selectGetSyncErrorMessage(state),
|
||||
getSyncPending: selectGetSyncIsPending(state),
|
||||
language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
setSyncEnabled: value => dispatch(doSetWalletSyncPreference(value)),
|
||||
checkSync: () => dispatch(doCheckSync()),
|
||||
getSync: (pw, cb) => dispatch(doGetSync(pw, cb)),
|
||||
updatePreferences: () => dispatch(doGetAndPopulatePreferences()),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(SyncToggle);
|
234
ui/component/syncEnableFlow/view.jsx
Normal file
234
ui/component/syncEnableFlow/view.jsx
Normal file
|
@ -0,0 +1,234 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import Button from 'component/button';
|
||||
import { getSavedPassword } from 'util/saved-passwords';
|
||||
import Card from 'component/common/card';
|
||||
import { withRouter } from 'react-router';
|
||||
import Spinner from 'component/spinner';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
import ErrorText from 'component/common/error-text';
|
||||
|
||||
type Props = {
|
||||
setSyncEnabled: boolean => void,
|
||||
syncEnabled: boolean,
|
||||
getSyncError: ?string,
|
||||
getSyncPending: boolean,
|
||||
getSync: (pw: string, cb: () => void) => void,
|
||||
checkSync: () => void,
|
||||
closeModal: () => void,
|
||||
updatePreferences: () => void,
|
||||
mode: string,
|
||||
};
|
||||
|
||||
const ENABLE_MODE = 'enable';
|
||||
|
||||
// steps
|
||||
const FETCH_FOR_ENABLE = 'fetch-for-enable';
|
||||
const FETCH_FOR_DISABLE = 'fetch-for-disable';
|
||||
const CONFIRM = 'confirm';
|
||||
const INITIAL = 'initial';
|
||||
const ERROR = 'error';
|
||||
|
||||
const SHARED_KEY = 'shared';
|
||||
const LOCAL_KEY = 'local';
|
||||
|
||||
function SyncEnableFlow(props: Props) {
|
||||
const {
|
||||
setSyncEnabled,
|
||||
getSyncError,
|
||||
getSyncPending,
|
||||
getSync,
|
||||
checkSync,
|
||||
mode,
|
||||
closeModal,
|
||||
updatePreferences,
|
||||
} = props;
|
||||
|
||||
const [step, setStep] = React.useState(INITIAL);
|
||||
const [prefDict, setPrefDict]: [any, (any) => void] = React.useState();
|
||||
const [password, setPassword] = React.useState('');
|
||||
const [error, setError] = React.useState();
|
||||
|
||||
const handleSyncToggle = async () => {
|
||||
const shared = prefDict.shared;
|
||||
const local = prefDict.local;
|
||||
let finalPrefs;
|
||||
if (shared && local) {
|
||||
if (mode === ENABLE_MODE) {
|
||||
finalPrefs = makeMergedPrefs(local, shared);
|
||||
} else {
|
||||
finalPrefs = makeMergedPrefs(shared, local);
|
||||
}
|
||||
} else {
|
||||
finalPrefs = local || shared || null;
|
||||
}
|
||||
|
||||
// set busy (disable button)
|
||||
if (finalPrefs) {
|
||||
await Lbry.preference_set({ key: mode === ENABLE_MODE ? SHARED_KEY : LOCAL_KEY, value: finalPrefs });
|
||||
}
|
||||
await setSyncEnabled(mode === ENABLE_MODE);
|
||||
await updatePreferences();
|
||||
closeModal();
|
||||
};
|
||||
|
||||
const makeMergedPrefs = (from, to) => {
|
||||
const mergedTo = to;
|
||||
const toPrefs = to.value;
|
||||
const fromPrefs = from.value;
|
||||
if (!fromPrefs) {
|
||||
return to;
|
||||
}
|
||||
|
||||
const mergedBlockListSet = new Set(toPrefs.blocked || []);
|
||||
const mergedSubscriptionsSet = new Set(toPrefs.subscriptions || []);
|
||||
const mergedTagsSet = new Set(toPrefs.tags || []);
|
||||
|
||||
const fromBlocklist = fromPrefs.blocked || [];
|
||||
const fromSubscriptions = fromPrefs.subscriptions || [];
|
||||
const fromTags = fromPrefs.tags || [];
|
||||
|
||||
if (fromBlocklist.length) {
|
||||
fromBlocklist.forEach(el => mergedBlockListSet.add(el));
|
||||
}
|
||||
if (fromSubscriptions.length) {
|
||||
fromSubscriptions.forEach(el => mergedSubscriptionsSet.add(el));
|
||||
}
|
||||
if (fromTags.length) {
|
||||
fromTags.forEach(el => mergedTagsSet.add(el));
|
||||
}
|
||||
|
||||
toPrefs.blocked = Array.from(mergedBlockListSet);
|
||||
toPrefs.subscriptions = Array.from(mergedSubscriptionsSet);
|
||||
toPrefs.tags = Array.from(mergedTagsSet);
|
||||
mergedTo.value = toPrefs;
|
||||
return mergedTo;
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (mode) {
|
||||
checkSync();
|
||||
if (mode === ENABLE_MODE) {
|
||||
setStep(FETCH_FOR_ENABLE);
|
||||
} else {
|
||||
setStep(FETCH_FOR_DISABLE);
|
||||
}
|
||||
}
|
||||
}, [mode]);
|
||||
|
||||
React.useEffect(() => {
|
||||
getSavedPassword()
|
||||
.then(pw => setPassword(pw || ''))
|
||||
.catch(e => {
|
||||
setError(e && e.message ? e.message : e);
|
||||
});
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (step === FETCH_FOR_ENABLE) {
|
||||
getSync(password, (e, hasChanged) => {
|
||||
if (e) {
|
||||
setStep(ERROR);
|
||||
setError(e && e.message ? e.message : e);
|
||||
} else {
|
||||
Lbry.preference_get().then(result => {
|
||||
const prefs = {};
|
||||
if (result[SHARED_KEY]) prefs[SHARED_KEY] = result[SHARED_KEY];
|
||||
if (result[LOCAL_KEY]) prefs[LOCAL_KEY] = result[LOCAL_KEY];
|
||||
setPrefDict(prefs);
|
||||
setStep(CONFIRM);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if (step === FETCH_FOR_DISABLE) {
|
||||
Lbry.preference_get().then(result => {
|
||||
const prefs = {};
|
||||
if (result[SHARED_KEY]) prefs[SHARED_KEY] = result[SHARED_KEY];
|
||||
if (result[LOCAL_KEY]) prefs[LOCAL_KEY] = result[LOCAL_KEY];
|
||||
setPrefDict(prefs);
|
||||
setStep(CONFIRM);
|
||||
});
|
||||
}
|
||||
}, [step, setPrefDict, setStep, password]);
|
||||
|
||||
if (getSyncPending) {
|
||||
return (
|
||||
<div>
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Card
|
||||
title={mode === ENABLE_MODE ? 'Enable Sync' : 'Disable Sync'}
|
||||
body={
|
||||
<div>
|
||||
{step === INITIAL && (
|
||||
<>
|
||||
<h1>{__(`Please wait...`)}</h1>
|
||||
<Spinner />
|
||||
</>
|
||||
)}
|
||||
{(step === FETCH_FOR_ENABLE || step === FETCH_FOR_DISABLE) && (
|
||||
<>
|
||||
<h1>{__(`Getting your profiles...`)}</h1>
|
||||
<Spinner />
|
||||
</>
|
||||
)}
|
||||
{step === CONFIRM && mode === ENABLE_MODE && (
|
||||
<>
|
||||
<h1>{__(`Enabling sync will switch to your cloud profile.`)}</h1>
|
||||
</>
|
||||
)}
|
||||
{step === CONFIRM && mode !== ENABLE_MODE && (
|
||||
<>
|
||||
<h1>{__(`Disabling sync will switch to your local profile.`)}</h1>
|
||||
</>
|
||||
)}
|
||||
{(error || getSyncError) && (
|
||||
<>
|
||||
<h1>{__(`Something went wrong...`)}</h1>
|
||||
<ErrorText>{error || (getSyncError && String(getSyncError)) || __('Unknown error')}</ErrorText>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
actions={
|
||||
<>
|
||||
{step === CONFIRM && (
|
||||
<div className={'card__actions'}>
|
||||
<Button
|
||||
button="primary"
|
||||
name={'syncbutton'}
|
||||
label={mode === ENABLE_MODE ? __('Enable Sync') : __('Disable Sync')}
|
||||
onClick={() => handleSyncToggle()}
|
||||
/>
|
||||
<Button button="link" name={'cancel'} label={__('Cancel')} onClick={() => closeModal()} />
|
||||
</div>
|
||||
)}
|
||||
{(step === FETCH_FOR_ENABLE || step === FETCH_FOR_DISABLE) && (
|
||||
<div className={'card__actions'}>
|
||||
<Button
|
||||
button="primary"
|
||||
name={'syncbutton'}
|
||||
label={mode === ENABLE_MODE ? __('Enable Sync') : __('Disable Sync')}
|
||||
onClick={() => handleSyncToggle()}
|
||||
disabled
|
||||
/>
|
||||
<Button button="link" name={'cancel'} label={__('Cancel')} onClick={() => closeModal()} />
|
||||
</div>
|
||||
)}
|
||||
{(error || getSyncError) && (
|
||||
<div className={'card__actions'}>
|
||||
<Button button="primary" name={'cancel'} label={__('Close')} onClick={() => closeModal()} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default withRouter(SyncEnableFlow);
|
|
@ -3,7 +3,8 @@ import { connect } from 'react-redux';
|
|||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import { selectGetSyncErrorMessage } from 'lbryinc';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { doSetClientSetting } from 'redux/actions/settings';
|
||||
import { doSetWalletSyncPreference } from 'redux/actions/settings';
|
||||
import { doOpenModal } from 'redux/actions/app';
|
||||
import SyncToggle from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -14,7 +15,8 @@ const select = state => ({
|
|||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
setSyncEnabled: value => dispatch(doSetClientSetting(SETTINGS.ENABLE_SYNC, value)),
|
||||
setSyncEnabled: value => dispatch(doSetWalletSyncPreference(value)),
|
||||
openModal: (id, props) => dispatch(doOpenModal(id, props)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(SyncToggle);
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
// @flow
|
||||
import * as PAGES from 'constants/pages';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import React from 'react';
|
||||
import Button from 'component/button';
|
||||
import { FormField } from 'component/common/form';
|
||||
import { withRouter } from 'react-router';
|
||||
import { FormField } from 'component/common/form';
|
||||
|
||||
type Props = {
|
||||
setSyncEnabled: boolean => void,
|
||||
|
@ -13,23 +14,20 @@ type Props = {
|
|||
location: UrlLocation,
|
||||
getSyncError: ?string,
|
||||
disabled: boolean,
|
||||
openModal: (string, any) => void,
|
||||
};
|
||||
|
||||
function SyncToggle(props: Props) {
|
||||
const {
|
||||
setSyncEnabled,
|
||||
syncEnabled,
|
||||
verifiedEmail,
|
||||
getSyncError,
|
||||
history,
|
||||
location: { pathname },
|
||||
disabled = false,
|
||||
openModal,
|
||||
syncEnabled,
|
||||
disabled,
|
||||
} = props;
|
||||
|
||||
function handleChange() {
|
||||
setSyncEnabled(!syncEnabled);
|
||||
}
|
||||
|
||||
if (getSyncError) {
|
||||
history.push(`/$/${PAGES.AUTH}?redirect=${pathname}&immediate=true`);
|
||||
return null;
|
||||
|
@ -48,7 +46,7 @@ function SyncToggle(props: Props) {
|
|||
name="sync_toggle"
|
||||
label={__('Sync your balance and preferences across devices.')}
|
||||
checked={syncEnabled}
|
||||
onChange={handleChange}
|
||||
onChange={() => openModal(MODALS.SYNC_ENABLE, { mode: syncEnabled ? 'disable' : 'enable' })}
|
||||
disabled={disabled}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -7,8 +7,8 @@ import {
|
|||
selectUser,
|
||||
} from 'redux/selectors/user';
|
||||
import { DAEMON_SETTINGS, SETTINGS } from 'lbry-redux';
|
||||
import { doSetSyncPref, doSetDaemonSetting } from 'redux/actions/settings';
|
||||
import { makeSelectClientSetting, selectDaemonSettings } from 'redux/selectors/settings';
|
||||
import { doSetWalletSyncPreference, doSetDaemonSetting } from 'redux/actions/settings';
|
||||
import { selectDaemonSettings, makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import UserEmailNew from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -21,7 +21,7 @@ const select = state => ({
|
|||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
setSync: value => dispatch(doSetSyncPref(value)),
|
||||
setSync: value => dispatch(doSetWalletSyncPreference(value)),
|
||||
setShareDiagnosticData: shouldShareData =>
|
||||
dispatch(doSetDaemonSetting(DAEMON_SETTINGS.SHARE_USAGE_DATA, shouldShareData)),
|
||||
doSignUp: (email, password) => dispatch(doUserSignUp(email, password)),
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
selectEmailNewIsPending,
|
||||
} from 'redux/selectors/user';
|
||||
import { doUserCheckIfEmailExists, doClearEmailEntry } from 'redux/actions/user';
|
||||
import { doSetSyncPref } from 'redux/actions/settings';
|
||||
import { doSetWalletSyncPreference } from 'redux/actions/settings';
|
||||
import UserEmailReturning from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -23,5 +23,5 @@ const select = state => ({
|
|||
export default connect(select, {
|
||||
doUserCheckIfEmailExists,
|
||||
doClearEmailEntry,
|
||||
doSetSyncPref,
|
||||
doSetWalletSyncPreference,
|
||||
})(UserEmailReturning);
|
||||
|
|
|
@ -17,7 +17,7 @@ type Props = {
|
|||
doClearEmailEntry: () => void,
|
||||
doUserSignIn: (string, ?string) => void,
|
||||
doUserCheckIfEmailExists: string => void,
|
||||
doSetSyncPref: boolean => void,
|
||||
doSetWalletSyncPreference: boolean => void,
|
||||
doSetClientSetting: (string, boolean, ?boolean) => void,
|
||||
isPending: boolean,
|
||||
};
|
||||
|
@ -30,7 +30,7 @@ function UserEmailReturning(props: Props) {
|
|||
emailToVerify,
|
||||
doClearEmailEntry,
|
||||
emailDoesNotExist,
|
||||
doSetSyncPref,
|
||||
doSetWalletSyncPreference,
|
||||
isPending,
|
||||
} = props;
|
||||
const { push, location } = useHistory();
|
||||
|
@ -48,7 +48,7 @@ function UserEmailReturning(props: Props) {
|
|||
|
||||
function handleSubmit() {
|
||||
// @if TARGET='app'
|
||||
doSetSyncPref(syncEnabled);
|
||||
doSetWalletSyncPreference(syncEnabled);
|
||||
// @endif
|
||||
doUserCheckIfEmailExists(email);
|
||||
}
|
||||
|
|
|
@ -133,7 +133,6 @@ 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';
|
||||
export const SYNC_PREFERENCE_CHANGED = 'SYNC_PREFERENCE_CHANGED';
|
||||
|
||||
// User
|
||||
export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED';
|
||||
|
|
|
@ -39,5 +39,6 @@ export const REPOST = 'repost';
|
|||
export const SIGN_OUT = 'sign_out';
|
||||
export const LIQUIDATE_SUPPORTS = 'liquidate_supports';
|
||||
export const CONFIRM_AGE = 'confirm_age';
|
||||
export const SYNC_ENABLE = 'SYNC_ENABLE';
|
||||
export const REMOVE_BLOCKED = 'remove_blocked';
|
||||
export const IMAGE_UPLOAD = 'image_upload';
|
||||
|
|
|
@ -38,6 +38,7 @@ import ModalSignOut from 'modal/modalSignOut';
|
|||
import ModalSupportsLiquidate from 'modal/modalSupportsLiquidate';
|
||||
import ModalConfirmAge from 'modal/modalConfirmAge';
|
||||
import ModalFileSelection from 'modal/modalFileSelection';
|
||||
import ModalSyncEnable from 'modal/modalSyncEnable';
|
||||
import ModalImageUpload from 'modal/modalImageUpload';
|
||||
|
||||
type Props = {
|
||||
|
@ -140,6 +141,8 @@ function ModalRouter(props: Props) {
|
|||
return <ModalRemoveBlocked {...modalProps} />;
|
||||
case MODALS.IMAGE_UPLOAD:
|
||||
return <ModalImageUpload {...modalProps} />;
|
||||
case MODALS.SYNC_ENABLE:
|
||||
return <ModalSyncEnable {...modalProps} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
11
ui/modal/modalSyncEnable/index.js
Normal file
11
ui/modal/modalSyncEnable/index.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doHideModal } from 'redux/actions/app';
|
||||
import ModalSyncEnable from './view';
|
||||
|
||||
const perform = dispatch => () => ({
|
||||
closeModal: () => {
|
||||
dispatch(doHideModal());
|
||||
},
|
||||
});
|
||||
|
||||
export default connect(null, perform)(ModalSyncEnable);
|
21
ui/modal/modalSyncEnable/view.jsx
Normal file
21
ui/modal/modalSyncEnable/view.jsx
Normal file
|
@ -0,0 +1,21 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { Modal } from 'modal/modal';
|
||||
import SyncToggleFlow from 'component/syncEnableFlow';
|
||||
|
||||
type Props = {
|
||||
closeModal: () => void,
|
||||
mode: string,
|
||||
};
|
||||
|
||||
const ModalSyncEnable = (props: Props) => {
|
||||
const { closeModal, mode } = props;
|
||||
|
||||
return (
|
||||
<Modal isOpen type="card" onAborted={closeModal}>
|
||||
<SyncToggleFlow closeModal={closeModal} mode={mode} />
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModalSyncEnable;
|
|
@ -33,7 +33,6 @@ const select = state => ({
|
|||
hideReposts: makeSelectClientSetting(SETTINGS.HIDE_REPOSTS)(state),
|
||||
darkModeTimes: makeSelectClientSetting(SETTINGS.DARK_MODE_TIMES)(state),
|
||||
language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state),
|
||||
syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
|
|
@ -64,7 +64,6 @@ type Props = {
|
|||
setDarkTime: (string, {}) => void,
|
||||
openModal: string => void,
|
||||
language?: string,
|
||||
syncEnabled: boolean,
|
||||
enterSettings: () => void,
|
||||
exitSettings: () => void,
|
||||
};
|
||||
|
|
|
@ -53,7 +53,6 @@ type Props = {
|
|||
findingFFmpeg: boolean,
|
||||
findFFmpeg: () => void,
|
||||
language?: string,
|
||||
syncEnabled: boolean,
|
||||
syncSettings: () => void,
|
||||
enterSettings: () => void,
|
||||
exitSettings: () => void,
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
selectFollowedTagsList,
|
||||
SHARED_PREFERENCES,
|
||||
DAEMON_SETTINGS,
|
||||
SETTINGS,
|
||||
} from 'lbry-redux';
|
||||
import { doToast, doError, doNotificationList } from 'redux/actions/notifications';
|
||||
import Native from 'native';
|
||||
|
@ -43,7 +44,7 @@ import {
|
|||
selectModal,
|
||||
selectAllowAnalytics,
|
||||
} from 'redux/selectors/app';
|
||||
import { selectDaemonSettings } from 'redux/selectors/settings';
|
||||
import { selectDaemonSettings, makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { selectUser } from 'redux/selectors/user';
|
||||
// import { selectDaemonSettings } from 'redux/selectors/settings';
|
||||
import { doSyncSubscribe } from 'redux/actions/syncwrapper';
|
||||
|
@ -596,9 +597,11 @@ export function doGetAndPopulatePreferences() {
|
|||
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
|
||||
const hasVerifiedEmail = state.user && state.user.user && state.user.user.has_verified_email;
|
||||
let preferenceKey;
|
||||
// @if TARGET='app'
|
||||
preferenceKey = state.user && state.user.user && state.user.user.has_verified_email ? 'shared' : 'anon';
|
||||
preferenceKey = syncEnabled && hasVerifiedEmail ? 'shared' : 'local';
|
||||
// @endif
|
||||
// @if TARGET='web'
|
||||
preferenceKey = 'shared';
|
||||
|
|
|
@ -131,34 +131,12 @@ export function doSetClientSetting(key, value, pushPrefs) {
|
|||
value,
|
||||
},
|
||||
});
|
||||
|
||||
if (pushPrefs) {
|
||||
dispatch(doPushSettingsToPrefs());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function doUpdateSyncPrefIfFalse() {
|
||||
// This is only called after manual signin to update the wallet
|
||||
// that the sync preference is false
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
|
||||
if (syncEnabled === false) {
|
||||
dispatch(doPushSettingsToPrefs());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function doSetSyncPref(isEnabled) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: LOCAL_ACTIONS.SYNC_PREFERENCE_CHANGED,
|
||||
data: isEnabled,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doUpdateIsNight() {
|
||||
return {
|
||||
type: ACTIONS.UPDATE_IS_NIGHT,
|
||||
|
@ -195,6 +173,32 @@ export function doSetDarkTime(value, options) {
|
|||
};
|
||||
}
|
||||
|
||||
export function doGetWalletSyncPreference() {
|
||||
const SYNC_KEY = 'enable-sync';
|
||||
return dispatch => {
|
||||
return Lbry.preference_get({ key: SYNC_KEY }).then(result => {
|
||||
const enabled = result && result[SYNC_KEY];
|
||||
if (enabled !== null) {
|
||||
dispatch(doSetClientSetting(SETTINGS.ENABLE_SYNC, enabled));
|
||||
}
|
||||
return enabled;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doSetWalletSyncPreference(pref) {
|
||||
const SYNC_KEY = 'enable-sync';
|
||||
return dispatch => {
|
||||
return Lbry.preference_set({ key: SYNC_KEY, value: pref }).then(result => {
|
||||
const enabled = result && result[SYNC_KEY];
|
||||
if (enabled !== null) {
|
||||
dispatch(doSetClientSetting(SETTINGS.ENABLE_SYNC, enabled));
|
||||
}
|
||||
return enabled;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doPushSettingsToPrefs() {
|
||||
return dispatch => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -211,6 +215,9 @@ export function doEnterSettingsPage() {
|
|||
const state = getState();
|
||||
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
|
||||
const hasVerifiedEmail = state.user && state.user.user && state.user.user.has_verified_email;
|
||||
if (IS_WEB && !hasVerifiedEmail) {
|
||||
return;
|
||||
}
|
||||
dispatch(doSyncUnsubscribe());
|
||||
if (syncEnabled && hasVerifiedEmail) {
|
||||
await dispatch(doGetSyncDesktop());
|
||||
|
@ -223,6 +230,11 @@ export function doEnterSettingsPage() {
|
|||
|
||||
export function doExitSettingsPage() {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const hasVerifiedEmail = state.user && state.user.user && state.user.user.has_verified_email;
|
||||
if (IS_WEB && !hasVerifiedEmail) {
|
||||
return;
|
||||
}
|
||||
dispatch(doSetSyncLock(false));
|
||||
dispatch(doPushSettingsToPrefs());
|
||||
// syncSubscribe is restarted in store.js sharedStateCB if necessary
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// @flow
|
||||
import { doGetSync, selectGetSyncIsPending, selectSetSyncIsPending } from 'lbryinc';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
import { makeSelectClientSetting, selectSyncSigninPref } from 'redux/selectors/settings';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { getSavedPassword } from 'util/saved-passwords';
|
||||
import { doAnalyticsTagSync, doHandleSyncComplete } from 'redux/actions/app';
|
||||
import { selectSyncIsLocked } from 'redux/selectors/app';
|
||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
|
||||
let syncTimer = null;
|
||||
const SYNC_INTERVAL = 1000 * 60 * 5; // 5 minutes
|
||||
|
@ -31,10 +31,9 @@ export function doSyncSubscribe() {
|
|||
if (syncTimer) clearInterval(syncTimer);
|
||||
const state = getState();
|
||||
const hasVerifiedEmail = selectUserVerifiedEmail(state);
|
||||
const signInSyncPref = selectSyncSigninPref(state);
|
||||
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
|
||||
const syncLocked = selectSyncIsLocked(state);
|
||||
if (hasVerifiedEmail && syncEnabled && !syncLocked && signInSyncPref !== false) {
|
||||
if (hasVerifiedEmail && syncEnabled && !syncLocked) {
|
||||
dispatch(doGetSyncDesktop((error, hasNewData) => dispatch(doHandleSyncComplete(error, hasNewData))));
|
||||
dispatch(doAnalyticsTagSync());
|
||||
syncTimer = setInterval(() => {
|
||||
|
|
|
@ -24,7 +24,6 @@ const defaultState = {
|
|||
findingFFmpeg: false,
|
||||
loadedLanguages: [...Object.keys(window.i18n_messages), 'en'] || ['en'],
|
||||
customWalletServers: [],
|
||||
syncEnabledPref: undefined, // set this during sign in, copy it to clientSettings immediately after prefGet after signedin but before sync
|
||||
sharedPreferences: {},
|
||||
daemonSettings: {},
|
||||
daemonStatus: { ffmpeg_status: {} },
|
||||
|
@ -153,28 +152,15 @@ reducers[ACTIONS.SYNC_CLIENT_SETTINGS] = state => {
|
|||
return Object.assign({}, state, { sharedPreferences: newSharedPreferences });
|
||||
};
|
||||
|
||||
reducers[ACTIONS.SYNC_PREFERENCE_CHANGED] = (state, action) => {
|
||||
return Object.assign({}, state, {
|
||||
syncEnabledPref: action.data,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[LBRY_REDUX_ACTIONS.USER_STATE_POPULATE] = (state, action) => {
|
||||
const { clientSettings: currentClientSettings, syncEnabledPref } = state;
|
||||
const { clientSettings: currentClientSettings } = state;
|
||||
const { settings: sharedPreferences } = action.data;
|
||||
// we have to update the signin sync checkbox in here
|
||||
// where we can simulataneously set the checkbox temp value to undefined, and
|
||||
// update the sync setting before sync happens
|
||||
// temp box must be undefined to trigger the items in the syncSubscribe effect
|
||||
const syncSettingOrEmpty = syncEnabledPref !== undefined ? { enable_sync: syncEnabledPref } : {};
|
||||
|
||||
const selectedSettings = sharedPreferences ? getSubsetFromKeysArray(sharedPreferences, clientSyncKeys) : {};
|
||||
const mergedClientSettings = { ...currentClientSettings, ...selectedSettings, ...syncSettingOrEmpty };
|
||||
const mergedClientSettings = { ...currentClientSettings, ...selectedSettings };
|
||||
const newSharedPreferences = sharedPreferences || {};
|
||||
return Object.assign({}, state, {
|
||||
sharedPreferences: newSharedPreferences,
|
||||
clientSettings: mergedClientSettings,
|
||||
syncEnabledPref: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@ export const selectFfmpegStatus = createSelector(selectDaemonStatus, status => s
|
|||
|
||||
export const selectFindingFFmpeg = createSelector(selectState, state => state.findingFFmpeg || false);
|
||||
|
||||
export const selectSyncSigninPref = createSelector(selectState, state => state.syncEnabledPref);
|
||||
|
||||
export const selectClientSettings = createSelector(selectState, state => state.clientSettings || {});
|
||||
|
||||
export const selectLoadedLanguages = createSelector(selectState, state => state.loadedLanguages || {});
|
||||
|
|
|
@ -6411,9 +6411,9 @@ lazy-val@^1.0.4:
|
|||
yargs "^13.2.2"
|
||||
zstd-codec "^0.1.1"
|
||||
|
||||
lbry-redux@lbryio/lbry-redux#437c54f164b4132c0d5c6ede60c7b02703f1e9d5:
|
||||
lbry-redux@lbryio/lbry-redux#e10295b5ec2ef42426755ed9fd50bd250b0d76dd:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/437c54f164b4132c0d5c6ede60c7b02703f1e9d5"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/e10295b5ec2ef42426755ed9fd50bd250b0d76dd"
|
||||
dependencies:
|
||||
proxy-polyfill "0.1.6"
|
||||
reselect "^3.0.0"
|
||||
|
|
Loading…
Reference in a new issue