sync changes

This commit is contained in:
jessop 2020-09-04 11:02:30 -04:00 committed by Sean Yesmunt
parent bb9bde1c19
commit 6c4842a111
29 changed files with 270 additions and 170 deletions

View file

@ -136,8 +136,8 @@
"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#210bb80f2c49f6a166a8adc602a68b7490d5d23a", "lbry-redux": "lbryio/lbry-redux#760623f99c90407ca3f1d06f1cdd2506fb2e443a",
"lbryinc": "lbryio/lbryinc#cff5dd60934c4c6080e135f47ebbece1548c658c", "lbryinc": "lbryio/lbryinc#35df87d1e69e435e25fc12832b6b1b788f76baaa",
"lint-staged": "^7.0.2", "lint-staged": "^7.0.2",
"localforage": "^1.7.1", "localforage": "^1.7.1",
"lodash-es": "^4.17.14", "lodash-es": "^4.17.14",

View file

@ -5,13 +5,18 @@ 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, SETTINGS } from 'lbry-redux'; import { doFetchChannelListMine, SETTINGS } from 'lbry-redux';
import { makeSelectClientSetting, selectLoadedLanguages, selectThemePath } from 'redux/selectors/settings'; import {
makeSelectClientSetting,
selectLoadedLanguages,
selectSyncSigninPref,
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, doUpdateSyncPref } from 'redux/actions/settings';
import { doSyncSubscribe } from 'redux/actions/syncwrapper';
import { import {
doDownloadUpgradeRequested, doDownloadUpgradeRequested,
doSignIn, doSignIn,
doSyncWithPreferences,
doGetAndPopulatePreferences, doGetAndPopulatePreferences,
doAnalyticsTagSync, doAnalyticsTagSync,
} from 'redux/actions/app'; } from 'redux/actions/app';
@ -22,14 +27,15 @@ const select = state => ({
accessToken: selectAccessToken(state), accessToken: selectAccessToken(state),
theme: selectThemePath(state), theme: selectThemePath(state),
language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state),
syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state),
languages: selectLoadedLanguages(state), languages: selectLoadedLanguages(state),
autoUpdateDownloaded: selectAutoUpdateDownloaded(state), autoUpdateDownloaded: selectAutoUpdateDownloaded(state),
isUpgradeAvailable: selectIsUpgradeAvailable(state), isUpgradeAvailable: selectIsUpgradeAvailable(state),
syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state),
syncError: selectGetSyncErrorMessage(state), syncError: selectGetSyncErrorMessage(state),
uploadCount: selectUploadCount(state), uploadCount: selectUploadCount(state),
rewards: selectUnclaimedRewards(state), rewards: selectUnclaimedRewards(state),
isAuthenticated: selectUserVerifiedEmail(state), isAuthenticated: selectUserVerifiedEmail(state),
signInSyncPref: selectSyncSigninPref(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({
@ -39,8 +45,9 @@ const perform = dispatch => ({
setLanguage: language => dispatch(doSetLanguage(language)), setLanguage: language => dispatch(doSetLanguage(language)),
signIn: () => dispatch(doSignIn()), signIn: () => dispatch(doSignIn()),
requestDownloadUpgrade: () => dispatch(doDownloadUpgradeRequested()), requestDownloadUpgrade: () => dispatch(doDownloadUpgradeRequested()),
checkSync: () => dispatch(doSyncWithPreferences()),
updatePreferences: () => dispatch(doGetAndPopulatePreferences()), updatePreferences: () => dispatch(doGetAndPopulatePreferences()),
updateSyncPref: () => dispatch(doUpdateSyncPref()),
syncSubscribe: () => dispatch(doSyncSubscribe()),
setReferrer: (referrer, doClaim) => dispatch(doUserSetReferrer(referrer, doClaim)), setReferrer: (referrer, doClaim) => dispatch(doUserSetReferrer(referrer, doClaim)),
}); });

View file

@ -38,7 +38,6 @@ export const MAIN_WRAPPER_CLASS = 'main-wrapper';
// @if TARGET='app' // @if TARGET='app'
export const IS_MAC = process.platform === 'darwin'; export const IS_MAC = process.platform === 'darwin';
// @endif // @endif
const SYNC_INTERVAL = 1000 * 60 * 5; // 5 minutes
// button numbers pulled from https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button // button numbers pulled from https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
const MOUSE_BACK_BTN = 3; const MOUSE_BACK_BTN = 3;
@ -67,17 +66,20 @@ type Props = {
setLanguage: string => void, setLanguage: string => void,
isUpgradeAvailable: boolean, isUpgradeAvailable: boolean,
autoUpdateDownloaded: boolean, autoUpdateDownloaded: boolean,
checkSync: () => void, updatePreferences: () => Promise<any>,
updatePreferences: () => void, updateSyncPref: () => void,
syncEnabled: boolean,
uploadCount: number, uploadCount: number,
balance: ?number, balance: ?number,
syncError: ?string, syncError: ?string,
syncEnabled: boolean,
rewards: Array<Reward>, rewards: Array<Reward>,
setReferrer: (string, boolean) => void, setReferrer: (string, boolean) => void,
analyticsTagSync: () => void, analyticsTagSync: () => void,
isAuthenticated: boolean, isAuthenticated: boolean,
socketConnect: () => void, socketConnect: () => void,
syncSubscribe: () => void,
syncEnabled: boolean,
signInSyncPref: boolean,
}; };
function App(props: Props) { function App(props: Props) {
@ -90,8 +92,6 @@ function App(props: Props) {
autoUpdateDownloaded, autoUpdateDownloaded,
isUpgradeAvailable, isUpgradeAvailable,
requestDownloadUpgrade, requestDownloadUpgrade,
syncEnabled,
checkSync,
uploadCount, uploadCount,
history, history,
syncError, syncError,
@ -99,15 +99,19 @@ function App(props: Props) {
languages, languages,
setLanguage, setLanguage,
updatePreferences, updatePreferences,
updateSyncPref,
rewards, rewards,
setReferrer, setReferrer,
analyticsTagSync,
isAuthenticated, isAuthenticated,
syncSubscribe,
signInSyncPref,
} = props; } = props;
const appRef = useRef(); const appRef = useRef();
const isEnhancedLayout = useKonamiListener(); const isEnhancedLayout = useKonamiListener();
const [hasSignedIn, setHasSignedIn] = useState(false); 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 && user.has_verified_email;
const isRewardApproved = user && user.is_reward_approved; const isRewardApproved = user && user.is_reward_approved;
const previousHasVerifiedEmail = usePrevious(hasVerifiedEmail); const previousHasVerifiedEmail = usePrevious(hasVerifiedEmail);
@ -229,35 +233,40 @@ function App(props: Props) {
} }
}, [previousRewardApproved, isRewardApproved]); }, [previousRewardApproved, isRewardApproved]);
// Keep this at the end to ensure initial setup effects are run first
useEffect(() => {
if (!hasSignedIn && hasVerifiedEmail) {
signIn();
setHasSignedIn(true);
}
}, [hasVerifiedEmail, signIn, hasSignedIn]);
// @if TARGET='app' // @if TARGET='app'
useEffect(() => { useEffect(() => {
updatePreferences(); if (updatePreferences && readyForPrefs) {
// eslint-disable-next-line react-hooks/exhaustive-deps updatePreferences().then(() => {
}, []); setReadyForSync(true);
});
}
}, [updatePreferences, setReadyForSync, readyForPrefs, hasVerifiedEmail]);
// @endif // @endif
// ready for sync syncs, however after signin when hasVerifiedEmail, that syncs too.
useEffect(() => { useEffect(() => {
if (hasVerifiedEmail && syncEnabled) { if (readyForSync && hasVerifiedEmail) {
checkSync(); // Copy sync checkbox to settings and push to preferences
analyticsTagSync(); // before sync if false, after sync if true so as not to change timestamp.
let syncInterval = setInterval(() => { if (signInSyncPref === false) {
checkSync(); updateSyncPref();
}, SYNC_INTERVAL); }
syncSubscribe();
return () => { if (signInSyncPref === true) {
clearInterval(syncInterval); updateSyncPref();
}; }
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [hasVerifiedEmail, syncEnabled, checkSync]); }, [readyForSync, hasVerifiedEmail, signInSyncPref, updateSyncPref, syncSubscribe]);
// 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(() => {
if (user) {
setReadyForPrefs(true);
}
}, [user, setReadyForPrefs]);
useEffect(() => { useEffect(() => {
if (syncError && isAuthenticated) { if (syncError && isAuthenticated) {
@ -266,6 +275,15 @@ function App(props: Props) {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [syncError, pathname, isAuthenticated]); }, [syncError, pathname, isAuthenticated]);
// Keep this at the end to ensure initial setup effects are run first
useEffect(() => {
if (!hasSignedIn && hasVerifiedEmail) {
signIn();
setHasSignedIn(true);
if (IS_WEB) setReadyForSync(true);
}
}, [hasVerifiedEmail, signIn, hasSignedIn]);
// @if TARGET='web' // @if TARGET='web'
useDegradedPerformance(setLbryTvApiStatus); useDegradedPerformance(setLbryTvApiStatus);
// @endif // @endif

View file

@ -4,7 +4,7 @@ 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';
import { doSetClientSetting, doSyncClientSettings } from 'redux/actions/settings'; 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';
@ -25,8 +25,7 @@ const select = state => ({
}); });
const perform = dispatch => ({ const perform = dispatch => ({
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), setClientSetting: (key, value, push) => dispatch(doSetClientSetting(key, value, push)),
syncSettings: () => dispatch(doSyncClientSettings()),
signOut: () => dispatch(doSignOut()), signOut: () => dispatch(doSignOut()),
openChannelCreate: () => dispatch(doOpenModal(MODALS.CREATE_CHANNEL)), openChannelCreate: () => dispatch(doOpenModal(MODALS.CREATE_CHANNEL)),
openSignOutModal: () => dispatch(doOpenModal(MODALS.SIGN_OUT)), openSignOutModal: () => dispatch(doOpenModal(MODALS.SIGN_OUT)),

View file

@ -37,7 +37,7 @@ type Props = {
}, },
currentTheme: string, currentTheme: string,
automaticDarkModeEnabled: boolean, automaticDarkModeEnabled: boolean,
setClientSetting: (string, boolean | string) => void, setClientSetting: (string, boolean | string, ?boolean) => void,
hideBalance: boolean, hideBalance: boolean,
email: ?string, email: ?string,
authenticated: boolean, authenticated: boolean,
@ -56,7 +56,6 @@ type Props = {
clearEmailEntry: () => void, clearEmailEntry: () => void,
clearPasswordEntry: () => void, clearPasswordEntry: () => void,
hasNavigated: boolean, hasNavigated: boolean,
syncSettings: () => void,
sidebarOpen: boolean, sidebarOpen: boolean,
setSidebarOpen: boolean => void, setSidebarOpen: boolean => void,
isAbsoluteSideNavHidden: boolean, isAbsoluteSideNavHidden: boolean,
@ -80,7 +79,6 @@ const Header = (props: Props) => {
clearPasswordEntry, clearPasswordEntry,
emailToVerify, emailToVerify,
backout, backout,
syncSettings,
sidebarOpen, sidebarOpen,
setSidebarOpen, setSidebarOpen,
isAbsoluteSideNavHidden, isAbsoluteSideNavHidden,
@ -149,11 +147,10 @@ const Header = (props: Props) => {
} }
if (currentTheme === 'dark') { if (currentTheme === 'dark') {
setClientSetting(SETTINGS.THEME, 'light'); setClientSetting(SETTINGS.THEME, 'light', true);
} else { } else {
setClientSetting(SETTINGS.THEME, 'dark'); setClientSetting(SETTINGS.THEME, 'dark', true);
} }
syncSettings();
} }
function getWalletTitle() { function getWalletTitle() {

View file

@ -1,8 +1,8 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectPublishFormValues, doUpdatePublishForm } from 'lbry-redux'; import { selectPublishFormValues, doUpdatePublishForm } from 'lbry-redux';
import PublishPage from './view'; import PublishPage from './view';
import { selectUser, selectAccessToken } from '../../redux/selectors/user'; import { selectUser, selectAccessToken } from 'redux/selectors/user';
import {doFetchAccessToken} from '../../redux/actions/user'; import { doFetchAccessToken } from 'redux/actions/user';
const select = state => ({ const select = state => ({
...selectPublishFormValues(state), ...selectPublishFormValues(state),

View file

@ -3,8 +3,7 @@ import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectHasNavigated, 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, doSyncWithPreferences } from 'redux/actions/app'; import { doSetHasNavigated } from 'redux/actions/app';
import { doSyncClientSettings } from 'redux/actions/settings';
const select = state => { const select = state => {
const { pathname, hash } = state.router.location; const { pathname, hash } = state.router.location;
const urlPath = pathname + hash; const urlPath = pathname + hash;
@ -34,8 +33,6 @@ const select = state => {
const perform = dispatch => ({ const perform = dispatch => ({
setHasNavigated: () => dispatch(doSetHasNavigated()), setHasNavigated: () => dispatch(doSetHasNavigated()),
syncSettings: () => dispatch(doSyncClientSettings()),
checkSync: () => dispatch(doSyncWithPreferences()),
}); });
export default connect(select, perform)(Router); export default connect(select, perform)(Router);

View file

@ -97,8 +97,6 @@ type Props = {
welcomeVersion: number, welcomeVersion: number,
hasNavigated: boolean, hasNavigated: boolean,
setHasNavigated: () => void, setHasNavigated: () => void,
syncSettings: () => void,
checkSync: () => void,
}; };
function AppRouter(props: Props) { function AppRouter(props: Props) {
@ -112,14 +110,11 @@ function AppRouter(props: Props) {
welcomeVersion, welcomeVersion,
hasNavigated, hasNavigated,
setHasNavigated, setHasNavigated,
syncSettings,
checkSync,
} = 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');
const [prevPath, setPrevPath] = React.useState(pathname);
// For people arriving at settings page from deeplinks, know whether they can "go back" // For people arriving at settings page from deeplinks, know whether they can "go back"
useEffect(() => { useEffect(() => {
@ -131,27 +126,6 @@ function AppRouter(props: Props) {
return unlisten; return unlisten;
}, [hasNavigated, setHasNavigated]); }, [hasNavigated, setHasNavigated]);
// Sync when no longer on a settings page, or when entering settings pages
useEffect(() => {
const unlisten = history.listen(location => {
if (!location.pathname.includes(PAGES.SETTINGS) && prevPath.includes(PAGES.SETTINGS)) {
syncSettings();
} else if (location.pathname.includes(PAGES.SETTINGS) && !prevPath.includes(PAGES.SETTINGS)) {
checkSync();
}
});
return unlisten;
}, [prevPath, syncSettings, checkSync]);
useEffect(() => {
const unlisten = history.listen(location => {
if (prevPath !== location.pathname && setPrevPath) {
setPrevPath(location.pathname);
}
});
return unlisten;
}, [prevPath, setPrevPath]);
useEffect(() => { useEffect(() => {
if (uri) { if (uri) {
const { channelName, streamName } = parseURI(uri); const { channelName, streamName } = parseURI(uri);

View file

@ -1,5 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doGetSync, selectGetSyncIsPending, selectSyncApplyPasswordError } from 'lbryinc'; import { selectGetSyncIsPending, selectSyncApplyPasswordError } from 'lbryinc';
import { doGetSyncDesktop } from 'redux/actions/syncwrapper';
import { selectUserEmail } from 'redux/selectors/user'; import { selectUserEmail } from 'redux/selectors/user';
import { doSetClientSetting } from 'redux/actions/settings'; import { doSetClientSetting } from 'redux/actions/settings';
import { doSignOut, doHandleSyncComplete } from 'redux/actions/app'; import { doSignOut, doHandleSyncComplete } from 'redux/actions/app';
@ -12,7 +13,7 @@ const select = state => ({
}); });
const perform = dispatch => ({ const perform = dispatch => ({
getSync: (password, cb) => dispatch(doGetSync(password, cb)), getSync: (cb, password) => dispatch(doGetSyncDesktop(cb, password)),
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
handleSyncComplete: (error, hasDataChanged) => dispatch(doHandleSyncComplete(error, hasDataChanged)), handleSyncComplete: (error, hasDataChanged) => dispatch(doHandleSyncComplete(error, hasDataChanged)),
signOut: () => dispatch(doSignOut()), signOut: () => dispatch(doSignOut()),

View file

@ -8,7 +8,7 @@ import usePersistedState from 'effects/use-persisted-state';
import I18nMessage from 'component/i18nMessage'; import I18nMessage from 'component/i18nMessage';
type Props = { type Props = {
getSync: (?string, (any, boolean) => void) => void, getSync: ((any, boolean) => void, ?string) => void,
getSyncIsPending: boolean, getSyncIsPending: boolean,
email: string, email: string,
passwordError: boolean, passwordError: boolean,
@ -22,13 +22,13 @@ function SyncPassword(props: Props) {
const [rememberPassword, setRememberPassword] = usePersistedState(true); const [rememberPassword, setRememberPassword] = usePersistedState(true);
function handleSubmit() { function handleSubmit() {
getSync(password, (error, hasDataChanged) => { getSync((error, hasDataChanged) => {
handleSyncComplete(error, hasDataChanged); handleSyncComplete(error, hasDataChanged);
if (!error) { if (!error) {
setSavedPassword(password, rememberPassword); setSavedPassword(password, rememberPassword);
} }
}); }, password);
} }
return ( return (

View file

@ -7,7 +7,7 @@ import {
selectUser, selectUser,
} from 'redux/selectors/user'; } from 'redux/selectors/user';
import { DAEMON_SETTINGS, SETTINGS } from 'lbry-redux'; import { DAEMON_SETTINGS, SETTINGS } from 'lbry-redux';
import { doSetClientSetting, doSetDaemonSetting } from 'redux/actions/settings'; import { doSetSyncPref, 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';
@ -21,7 +21,7 @@ const select = state => ({
}); });
const perform = dispatch => ({ const perform = dispatch => ({
setSync: value => dispatch(doSetClientSetting(SETTINGS.ENABLE_SYNC, value)), setSync: value => dispatch(doSetSyncPref(value)),
setShareDiagnosticData: shouldShareData => setShareDiagnosticData: shouldShareData =>
dispatch(doSetDaemonSetting(DAEMON_SETTINGS.SHARE_USAGE_DATA, shouldShareData)), dispatch(doSetDaemonSetting(DAEMON_SETTINGS.SHARE_USAGE_DATA, shouldShareData)),
doSignUp: (email, password) => dispatch(doUserSignUp(email, password)), doSignUp: (email, password) => dispatch(doUserSignUp(email, password)),

View file

@ -8,7 +8,7 @@ import {
selectEmailNewIsPending, selectEmailNewIsPending,
} from 'redux/selectors/user'; } from 'redux/selectors/user';
import { doUserCheckIfEmailExists, doClearEmailEntry } from 'redux/actions/user'; import { doUserCheckIfEmailExists, doClearEmailEntry } from 'redux/actions/user';
import { doSetClientSetting } from 'redux/actions/settings'; import { doSetSyncPref } from 'redux/actions/settings';
import UserEmailReturning from './view'; import UserEmailReturning from './view';
const select = state => ({ const select = state => ({
@ -23,5 +23,5 @@ const select = state => ({
export default connect(select, { export default connect(select, {
doUserCheckIfEmailExists, doUserCheckIfEmailExists,
doClearEmailEntry, doClearEmailEntry,
doSetClientSetting, doSetSyncPref,
})(UserEmailReturning); })(UserEmailReturning);

View file

@ -1,5 +1,4 @@
// @flow // @flow
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';
@ -18,7 +17,8 @@ type Props = {
doClearEmailEntry: () => void, doClearEmailEntry: () => void,
doUserSignIn: (string, ?string) => void, doUserSignIn: (string, ?string) => void,
doUserCheckIfEmailExists: string => void, doUserCheckIfEmailExists: string => void,
doSetClientSetting: (string, boolean) => void, doSetSyncPref: boolean => void,
doSetClientSetting: (string, boolean, ?boolean) => void,
isPending: boolean, isPending: boolean,
}; };
@ -30,7 +30,7 @@ function UserEmailReturning(props: Props) {
emailToVerify, emailToVerify,
doClearEmailEntry, doClearEmailEntry,
emailDoesNotExist, emailDoesNotExist,
doSetClientSetting, doSetSyncPref,
isPending, isPending,
} = props; } = props;
const { push, location } = useHistory(); const { push, location } = useHistory();
@ -48,7 +48,7 @@ function UserEmailReturning(props: Props) {
function handleSubmit() { function handleSubmit() {
// @if TARGET='app' // @if TARGET='app'
doSetClientSetting(SETTINGS.ENABLE_SYNC, syncEnabled); doSetSyncPref(syncEnabled);
// @endif // @endif
doUserCheckIfEmailExists(email); doUserCheckIfEmailExists(email);
} }

View file

@ -7,7 +7,7 @@ import Spinner from 'component/spinner';
type Props = { type Props = {
user: ?User, user: ?User,
history: { push: string => void }, history: { push: string => void, replace: string => void },
location: { search: string }, location: { search: string },
userFetchPending: boolean, userFetchPending: boolean,
doUserSignIn: string => void, doUserSignIn: string => void,
@ -28,7 +28,7 @@ function UserSignIn(props: Props) {
React.useEffect(() => { React.useEffect(() => {
if (hasVerifiedEmail || (!showEmail && !showPassword && !showLoading)) { if (hasVerifiedEmail || (!showEmail && !showPassword && !showLoading)) {
history.push(redirect || '/'); history.replace(redirect || '/');
} }
}, [showEmail, showPassword, showLoading, hasVerifiedEmail]); }, [showEmail, showPassword, showLoading, hasVerifiedEmail]);

View file

@ -27,6 +27,7 @@ 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'; export const SET_HAS_NAVIGATED = 'SET_HAS_NAVIGATED';
export const SET_SYNC_LOCK = 'SET_SYNC_LOCK';
// Navigation // Navigation
export const CHANGE_AFTER_AUTH_PATH = 'CHANGE_AFTER_AUTH_PATH'; export const CHANGE_AFTER_AUTH_PATH = 'CHANGE_AFTER_AUTH_PATH';
@ -132,6 +133,7 @@ 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'; export const SYNC_CLIENT_SETTINGS = 'SYNC_CLIENT_SETTINGS';
export const SYNC_PREFERENCE_CHANGED = 'SYNC_PREFERENCE_CHANGED';
// User // User
export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED'; export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED';

View file

@ -117,30 +117,10 @@ doAuthTokenRefresh();
// We keep a local variable for authToken because `ipcRenderer.send` does not // We keep a local variable for authToken because `ipcRenderer.send` does not
// contain a response, so there is no way to know when it's been set // contain a response, so there is no way to know when it's been set
let authToken; let authToken;
Lbryio.setOverride( Lbryio.setOverride('setAuthToken', authToken => {
'setAuthToken', setAuthToken(authToken);
status => return authToken;
new Promise(resolve => { });
Lbryio.call(
'user',
'new',
{
auth_token: '',
language: DEFAULT_LANGUAGE,
app_id: status.installation_id,
},
'post'
).then(response => {
if (!response.auth_token) {
throw new Error(__('auth_token is missing from response'));
}
authToken = response.auth_token;
setAuthToken(authToken);
resolve(authToken);
});
})
);
Lbryio.setOverride( Lbryio.setOverride(
'getAuthToken', 'getAuthToken',

View file

@ -6,7 +6,8 @@ import {
doClearDaemonSetting, doClearDaemonSetting,
doSetClientSetting, doSetClientSetting,
doSetDarkTime, doSetDarkTime,
doSyncClientSettings, doEnterSettingsPage,
doExitSettingsPage,
} from 'redux/actions/settings'; } from 'redux/actions/settings';
import { doSetPlayingUri } from 'redux/actions/content'; import { doSetPlayingUri } from 'redux/actions/content';
import { makeSelectClientSetting, selectDaemonSettings } from 'redux/selectors/settings'; import { makeSelectClientSetting, selectDaemonSettings } from 'redux/selectors/settings';
@ -37,7 +38,6 @@ const select = 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()),
@ -47,6 +47,8 @@ const perform = dispatch => ({
clearPlayingUri: () => dispatch(doSetPlayingUri(null)), clearPlayingUri: () => dispatch(doSetPlayingUri(null)),
setDarkTime: (time, options) => dispatch(doSetDarkTime(time, options)), setDarkTime: (time, options) => dispatch(doSetDarkTime(time, options)),
openModal: (id, params) => dispatch(doOpenModal(id, params)), openModal: (id, params) => dispatch(doOpenModal(id, params)),
enterSettings: () => dispatch(doEnterSettingsPage()),
exitSettings: () => dispatch(doExitSettingsPage()),
}); });
export default connect(select, perform)(SettingsPage); export default connect(select, perform)(SettingsPage);

View file

@ -4,7 +4,6 @@ import * as MODALS from 'constants/modal_types';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import * as React from 'react'; import * as React from 'react';
import { SETTINGS } from 'lbry-redux'; import { SETTINGS } from 'lbry-redux';
import { FormField } from 'component/common/form'; import { FormField } from 'component/common/form';
import Button from 'component/button'; import Button from 'component/button';
import Page from 'component/page'; import Page from 'component/page';
@ -66,6 +65,8 @@ type Props = {
openModal: string => void, openModal: string => void,
language?: string, language?: string,
syncEnabled: boolean, syncEnabled: boolean,
enterSettings: () => void,
exitSettings: () => void,
}; };
type State = { type State = {
@ -89,7 +90,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
} }
componentDidMount() { componentDidMount() {
const { isAuthenticated } = this.props; const { isAuthenticated, enterSettings } = this.props;
if (isAuthenticated || !IS_WEB) { if (isAuthenticated || !IS_WEB) {
this.props.updateWalletStatus(); this.props.updateWalletStatus();
@ -99,6 +100,12 @@ class SettingsPage extends React.PureComponent<Props, State> {
} }
}); });
} }
enterSettings();
}
componentWillUnmount() {
const { exitSettings } = this.props;
exitSettings();
} }
onThemeChange(event: SyntheticInputEvent<*>) { onThemeChange(event: SyntheticInputEvent<*>) {
@ -211,11 +218,11 @@ class SettingsPage extends React.PureComponent<Props, State> {
<Card <Card
title={__('Sync')} title={__('Sync')}
subtitle={ subtitle={
walletEncrypted && !storedPassword walletEncrypted && !storedPassword && storedPassword !== ''
? __("To enable this feature, check 'Save Password' the next time you start the app.") ? __("To enable Sync, close LBRY completely and check 'Remember Password' during wallet unlock.")
: null : null
} }
actions={<SyncToggle disabled={walletEncrypted && !storedPassword} />} actions={<SyncToggle disabled={walletEncrypted && !storedPassword && storedPassword !== ''} />}
/> />
{/* @endif */} {/* @endif */}

View file

@ -6,7 +6,8 @@ import {
doClearDaemonSetting, doClearDaemonSetting,
doSetClientSetting, doSetClientSetting,
doFindFFmpeg, doFindFFmpeg,
doSyncClientSettings, doEnterSettingsPage,
doExitSettingsPage,
} from 'redux/actions/settings'; } from 'redux/actions/settings';
import { import {
makeSelectClientSetting, makeSelectClientSetting,
@ -34,7 +35,6 @@ const select = 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)),
clearCache: () => dispatch(doClearCache()), clearCache: () => dispatch(doClearCache()),
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
@ -43,6 +43,8 @@ const perform = dispatch => ({
updateWalletStatus: () => dispatch(doWalletStatus()), updateWalletStatus: () => dispatch(doWalletStatus()),
confirmForgetPassword: modalProps => dispatch(doNotifyForgetPassword(modalProps)), confirmForgetPassword: modalProps => dispatch(doNotifyForgetPassword(modalProps)),
findFFmpeg: () => dispatch(doFindFFmpeg()), findFFmpeg: () => dispatch(doFindFFmpeg()),
enterSettings: () => dispatch(doEnterSettingsPage()),
exitSettings: () => dispatch(doExitSettingsPage()),
}); });
export default connect(select, perform)(SettingsPage); export default connect(select, perform)(SettingsPage);

View file

@ -55,6 +55,8 @@ type Props = {
language?: string, language?: string,
syncEnabled: boolean, syncEnabled: boolean,
syncSettings: () => void, syncSettings: () => void,
enterSettings: () => void,
exitSettings: () => void,
}; };
type State = { type State = {
@ -81,7 +83,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
} }
componentDidMount() { componentDidMount() {
const { isAuthenticated, ffmpegStatus, daemonSettings, findFFmpeg } = this.props; const { isAuthenticated, ffmpegStatus, daemonSettings, findFFmpeg, enterSettings } = this.props;
// @if TARGET='app' // @if TARGET='app'
const { available } = ffmpegStatus; const { available } = ffmpegStatus;
@ -102,6 +104,12 @@ class SettingsPage extends React.PureComponent<Props, State> {
} }
}); });
} }
enterSettings();
}
componentWillUnmount() {
const { exitSettings } = this.props;
exitSettings();
} }
onFFmpegFolder(path: string) { onFFmpegFolder(path: string) {

View file

@ -46,11 +46,11 @@ import {
import { selectDaemonSettings } from 'redux/selectors/settings'; 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 { doSyncSubscribe } from 'redux/actions/syncwrapper';
import { doAuthenticate } from 'redux/actions/user'; import { doAuthenticate } from 'redux/actions/user';
import { lbrySettings as config, version as appVersion } from 'package.json'; 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 } from 'util/saved-passwords';
import { doSocketConnect } from 'redux/actions/websocket'; import { doSocketConnect } from 'redux/actions/websocket';
import { stringifyServerParam, shouldSetSetting } from 'util/sync-settings'; import { stringifyServerParam, shouldSetSetting } from 'util/sync-settings';
import sha256 from 'crypto-js/sha256'; import sha256 from 'crypto-js/sha256';
@ -89,6 +89,13 @@ export function doUpdateDownloadProgress(percent) {
}; };
} }
export function doSetSyncLock(lock) {
return {
type: ACTIONS.SET_SYNC_LOCK,
data: lock,
};
}
export function doSkipUpgrade() { export function doSkipUpgrade() {
return { return {
type: ACTIONS.SKIP_UPGRADE, type: ACTIONS.SKIP_UPGRADE,
@ -622,6 +629,7 @@ export function doGetAndPopulatePreferences() {
} }
// @endif // @endif
} }
return true;
} }
function failCb() { function failCb() {
@ -633,9 +641,10 @@ export function doGetAndPopulatePreferences() {
}) })
); );
}); });
return false;
} }
doPreferenceGet(preferenceKey, successCb, failCb); return doPreferenceGet(preferenceKey, successCb, failCb);
}; };
} }
@ -653,11 +662,5 @@ export function doHandleSyncComplete(error, hasNewData) {
} }
export function doSyncWithPreferences() { export function doSyncWithPreferences() {
return dispatch => { return dispatch => dispatch(doSyncSubscribe());
return getSavedPassword().then(password => {
const passwordArgument = password === null ? '' : password;
dispatch(doGetSync(passwordArgument, (error, hasNewData) => dispatch(doHandleSyncComplete(error, hasNewData))));
});
};
} }

View file

@ -5,6 +5,9 @@ import analytics from 'analytics';
import SUPPORTED_LANGUAGES from 'constants/supported_languages'; 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';
import { doGetSyncDesktop, doSyncUnsubscribe } from 'redux/actions/syncwrapper';
import { doGetAndPopulatePreferences, doSetSyncLock } from 'redux/actions/app';
const { DEFAULT_LANGUAGE } = require('config'); const { DEFAULT_LANGUAGE } = require('config');
const { SDK_SYNC_KEYS } = SHARED_PREFERENCES; const { SDK_SYNC_KEYS } = SHARED_PREFERENCES;
@ -119,7 +122,7 @@ export function doSaveCustomWalletServers(servers) {
}; };
} }
export function doSetClientSetting(key, value) { export function doSetClientSetting(key, value, pushPrefs) {
return dispatch => { return dispatch => {
dispatch({ dispatch({
type: ACTIONS.CLIENT_SETTING_CHANGED, type: ACTIONS.CLIENT_SETTING_CHANGED,
@ -128,6 +131,30 @@ export function doSetClientSetting(key, value) {
value, value,
}, },
}); });
if (pushPrefs) {
dispatch(doPushSettingsToPrefs());
}
};
}
export function doUpdateSyncPref() {
return (dispatch, getState) => {
const { settings } = getState();
const { syncEnabledPref } = settings || {};
if (syncEnabledPref !== undefined) {
dispatch(doSetClientSetting(SETTINGS.ENABLE_SYNC, syncEnabledPref, true));
dispatch(doSetSyncPref(undefined));
}
};
}
export function doSetSyncPref(isEnabled) {
return dispatch => {
dispatch({
type: LOCAL_ACTIONS.SYNC_PREFERENCE_CHANGED,
data: isEnabled,
});
}; };
} }
@ -167,15 +194,36 @@ export function doSetDarkTime(value, options) {
}; };
} }
export function doSyncClientSettings() { export function doPushSettingsToPrefs() {
return (dispatch, getState) => { return dispatch => {
const state = getState(); return new Promise((resolve, reject) => {
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
if (syncEnabled) {
dispatch({ dispatch({
type: LOCAL_ACTIONS.SYNC_CLIENT_SETTINGS, type: LOCAL_ACTIONS.SYNC_CLIENT_SETTINGS,
}); });
resolve();
});
};
}
export function doEnterSettingsPage() {
return async (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;
dispatch(doSyncUnsubscribe());
if (syncEnabled && hasVerifiedEmail) {
await dispatch(doGetSyncDesktop());
} else {
await dispatch(doGetAndPopulatePreferences());
} }
dispatch(doSetSyncLock(true));
};
}
export function doExitSettingsPage() {
return (dispatch, getState) => {
dispatch(doSetSyncLock(false));
dispatch(doPushSettingsToPrefs());
}; };
} }

View file

@ -0,0 +1,57 @@
// @flow
import { doGetSync, selectGetSyncIsPending, selectSetSyncIsPending } from 'lbryinc';
import { SETTINGS } from 'lbry-redux';
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';
let syncTimer = null;
const SYNC_INTERVAL = 1000 * 60 * 5; // 5 minutes
export const doGetSyncDesktop = (cb?: () => void, password?: string) => (dispatch: Dispatch, getState: GetState) => {
const state = getState();
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
const getSyncPending = selectGetSyncIsPending(state);
const setSyncPending = selectSetSyncIsPending(state);
const syncLocked = selectSyncIsLocked(state);
return getSavedPassword().then(savedPassword => {
const passwordArgument = password || password === '' ? password : savedPassword === null ? '' : savedPassword;
if (syncEnabled && !getSyncPending && !setSyncPending && !syncLocked) {
return dispatch(doGetSync(passwordArgument, cb));
}
});
};
export function doSyncSubscribe() {
return (dispatch: Dispatch, getState: GetState) => {
if (syncTimer) clearInterval(syncTimer);
const state = getState();
const hasVerifiedEmail = selectUserVerifiedEmail(state);
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
const syncLocked = selectSyncIsLocked(state);
if (hasVerifiedEmail && syncEnabled && !syncLocked) {
dispatch(doGetSyncDesktop((error, hasNewData) => dispatch(doHandleSyncComplete(error, hasNewData))));
dispatch(doAnalyticsTagSync());
syncTimer = setInterval(() => {
const state = getState();
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
if (syncEnabled) {
dispatch(doGetSyncDesktop((error, hasNewData) => dispatch(doHandleSyncComplete(error, hasNewData))));
dispatch(doAnalyticsTagSync());
}
}, SYNC_INTERVAL);
}
};
}
export function doSyncUnsubscribe() {
return (dispatch: Dispatch) => {
if (syncTimer) {
clearInterval(syncTimer);
}
};
}

View file

@ -42,6 +42,7 @@ export type AppState = {
welcomeVersion: number, welcomeVersion: number,
allowAnalytics: boolean, allowAnalytics: boolean,
hasNavigated: boolean, hasNavigated: boolean,
syncLocked: boolean,
}; };
const defaultState: AppState = { const defaultState: AppState = {
@ -76,6 +77,7 @@ const defaultState: AppState = {
welcomeVersion: 0.0, welcomeVersion: 0.0,
allowAnalytics: false, allowAnalytics: false,
hasNavigated: false, hasNavigated: false,
syncLocked: false,
}; };
// @@router comes from react-router // @@router comes from react-router
@ -109,6 +111,11 @@ reducers[ACTIONS.DAEMON_READY] = state =>
daemonReady: true, daemonReady: true,
}); });
reducers[ACTIONS.SET_SYNC_LOCK] = (state, action) =>
Object.assign({}, state, {
syncLocked: action.data,
});
reducers[ACTIONS.PASSWORD_SAVED] = (state, action) => reducers[ACTIONS.PASSWORD_SAVED] = (state, action) =>
Object.assign({}, state, { Object.assign({}, state, {
isPasswordSaved: action.data, isPasswordSaved: action.data,

View file

@ -24,6 +24,7 @@ const defaultState = {
findingFFmpeg: false, findingFFmpeg: false,
loadedLanguages: [...Object.keys(window.i18n_messages), 'en'] || ['en'], loadedLanguages: [...Object.keys(window.i18n_messages), 'en'] || ['en'],
customWalletServers: [], customWalletServers: [],
syncEnabledPref: undefined, // set this during sign in, copy it to clientSettings immediately after prefGet after signedin but before sync
sharedPreferences: {}, sharedPreferences: {},
daemonSettings: {}, daemonSettings: {},
daemonStatus: { ffmpeg_status: {} }, daemonStatus: { ffmpeg_status: {} },
@ -144,17 +145,6 @@ reducers[LBRY_REDUX_ACTIONS.SHARED_PREFERENCE_SET] = (state, action) => {
}); });
}; };
reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => {
const { key, value } = action.data;
const clientSettings = Object.assign({}, state.clientSettings);
clientSettings[key] = value;
return Object.assign({}, state, {
clientSettings,
});
};
reducers[ACTIONS.SYNC_CLIENT_SETTINGS] = state => { reducers[ACTIONS.SYNC_CLIENT_SETTINGS] = state => {
const { clientSettings } = state; const { clientSettings } = state;
const sharedPreferences = Object.assign({}, state.sharedPreferences); const sharedPreferences = Object.assign({}, state.sharedPreferences);
@ -163,6 +153,12 @@ reducers[ACTIONS.SYNC_CLIENT_SETTINGS] = state => {
return Object.assign({}, state, { sharedPreferences: newSharedPreferences }); 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) => { reducers[LBRY_REDUX_ACTIONS.USER_STATE_POPULATE] = (state, action) => {
const { clientSettings: currentClientSettings } = state; const { clientSettings: currentClientSettings } = state;
const { settings: sharedPreferences } = action.data; const { settings: sharedPreferences } = action.data;

View file

@ -80,3 +80,5 @@ export const selectAllowAnalytics = createSelector(selectState, state => state.a
export const selectScrollStartingPosition = createSelector(selectState, state => state.currentScroll); export const selectScrollStartingPosition = createSelector(selectState, state => state.currentScroll);
export const selectIsPasswordSaved = createSelector(selectState, state => state.isPasswordSaved); export const selectIsPasswordSaved = createSelector(selectState, state => state.isPasswordSaved);
export const selectSyncIsLocked = createSelector(selectState, state => state.syncLocked);

View file

@ -11,6 +11,8 @@ export const selectFfmpegStatus = createSelector(selectDaemonStatus, status => s
export const selectFindingFFmpeg = createSelector(selectState, state => state.findingFFmpeg || false); export const selectFindingFFmpeg = createSelector(selectState, state => state.findingFFmpeg || false);
export const selectSyncSigninPref = createSelector(selectState, state => state.syncEnabledPref || undefined);
export const selectClientSettings = createSelector(selectState, state => state.clientSettings || {}); export const selectClientSettings = createSelector(selectState, state => state.clientSettings || {});
export const selectLoadedLanguages = createSelector(selectState, state => state.loadedLanguages || {}); export const selectLoadedLanguages = createSelector(selectState, state => state.loadedLanguages || {});

View file

@ -9,11 +9,9 @@ import thunk from 'redux-thunk';
import { createMemoryHistory, createBrowserHistory } from 'history'; import { createMemoryHistory, createBrowserHistory } from 'history';
import { routerMiddleware } from 'connected-react-router'; import { routerMiddleware } from 'connected-react-router';
import createRootReducer from './reducers'; import createRootReducer from './reducers';
import { Lbry, buildSharedStateMiddleware, ACTIONS as LBRY_REDUX_ACTIONS, SETTINGS } from 'lbry-redux'; import { Lbry, buildSharedStateMiddleware, ACTIONS as LBRY_REDUX_ACTIONS } from 'lbry-redux';
import { doGetSync } from 'lbryinc'; import { doSyncSubscribe } from 'redux/actions/syncwrapper';
import { selectUserVerifiedEmail } from 'redux/selectors/user'; import { getAuthToken } from 'util/saved-passwords';
import { getSavedPassword, getAuthToken } from 'util/saved-passwords';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { generateInitialUrl } from 'util/url'; import { generateInitialUrl } from 'util/url';
import { X_LBRY_AUTH_TOKEN } from 'constants/token'; import { X_LBRY_AUTH_TOKEN } from 'constants/token';
@ -152,14 +150,7 @@ const sharedStateFilters = {
}; };
const sharedStateCb = ({ dispatch, getState }) => { const sharedStateCb = ({ dispatch, getState }) => {
const state = getState(); dispatch(doSyncSubscribe());
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
const emailVerified = selectUserVerifiedEmail(state);
if (syncEnabled && emailVerified) {
getSavedPassword().then(savedPassword => {
dispatch(doGetSync(savedPassword));
});
}
}; };
const populateAuthTokenHeader = () => { const populateAuthTokenHeader = () => {

View file

@ -6411,17 +6411,17 @@ 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#210bb80f2c49f6a166a8adc602a68b7490d5d23a: lbry-redux@lbryio/lbry-redux#760623f99c90407ca3f1d06f1cdd2506fb2e443a:
version "0.0.1" version "0.0.1"
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/210bb80f2c49f6a166a8adc602a68b7490d5d23a" resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/760623f99c90407ca3f1d06f1cdd2506fb2e443a"
dependencies: dependencies:
proxy-polyfill "0.1.6" proxy-polyfill "0.1.6"
reselect "^3.0.0" reselect "^3.0.0"
uuid "^3.3.2" uuid "^3.3.2"
lbryinc@lbryio/lbryinc#cff5dd60934c4c6080e135f47ebbece1548c658c: lbryinc@lbryio/lbryinc#35df87d1e69e435e25fc12832b6b1b788f76baaa:
version "0.0.1" version "0.0.1"
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/cff5dd60934c4c6080e135f47ebbece1548c658c" resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/35df87d1e69e435e25fc12832b6b1b788f76baaa"
dependencies: dependencies:
reselect "^3.0.0" reselect "^3.0.0"