diff --git a/package-lock.json b/package-lock.json index 0b63958..b742d5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5640,8 +5640,8 @@ } }, "lbry-redux": { - "version": "github:lbryio/lbry-redux#7ec72a737bcd336f000c5f5085891643110298c3", - "from": "github:lbryio/lbry-redux#7ec72a737bcd336f000c5f5085891643110298c3", + "version": "github:lbryio/lbry-redux#f06e1e64a8587a183bd7333f628fca821fe81fa4", + "from": "github:lbryio/lbry-redux#f06e1e64a8587a183bd7333f628fca821fe81fa4", "requires": { "proxy-polyfill": "0.1.6", "reselect": "^3.0.0", @@ -5649,8 +5649,8 @@ } }, "lbryinc": { - "version": "github:lbryio/lbryinc#c55a2c98ab92c72149c824ee5906aed4404fd89b", - "from": "github:lbryio/lbryinc#c55a2c98ab92c72149c824ee5906aed4404fd89b", + "version": "github:lbryio/lbryinc#02d8571cd7fafd00d1a60f133d884eb8c5f1a306", + "from": "github:lbryio/lbryinc#02d8571cd7fafd00d1a60f133d884eb8c5f1a306", "requires": { "reselect": "^3.0.0" } diff --git a/package.json b/package.json index 4e3f28b..3c44f78 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "base-64": "^0.1.0", "@expo/vector-icons": "^8.1.0", "gfycat-style-urls": "^1.0.3", - "lbry-redux": "lbryio/lbry-redux#7ec72a737bcd336f000c5f5085891643110298c3", - "lbryinc": "lbryio/lbryinc#c55a2c98ab92c72149c824ee5906aed4404fd89b", + "lbry-redux": "lbryio/lbry-redux#f06e1e64a8587a183bd7333f628fca821fe81fa4", + "lbryinc": "lbryio/lbryinc#02d8571cd7fafd00d1a60f133d884eb8c5f1a306", "lodash": ">=4.17.11", "merge": ">=1.2.1", "moment": "^2.22.1", diff --git a/src/component/AppNavigator.js b/src/component/AppNavigator.js index a5fb642..462d520 100644 --- a/src/component/AppNavigator.js +++ b/src/component/AppNavigator.js @@ -29,7 +29,7 @@ import { import { connect } from 'react-redux'; import { AppState, BackHandler, Linking, NativeModules, TextInput, ToastAndroid } from 'react-native'; import { selectDrawerStack } from 'redux/selectors/drawer'; -import { SETTINGS, doDismissToast, doPopulateSharedUserState, doToast, selectToast } from 'lbry-redux'; +import { SETTINGS, doDismissToast, doPopulateSharedUserState, doPreferenceGet, doToast, selectToast } from 'lbry-redux'; import { Lbryio, doGetSync, @@ -39,6 +39,7 @@ import { selectEmailToVerify, selectEmailVerifyIsPending, selectEmailVerifyErrorMessage, + selectHashChanged, selectUser, } from 'lbryinc'; import { makeSelectClientSetting } from 'redux/selectors/settings'; @@ -53,6 +54,8 @@ import discoverStyle from 'styles/discover'; import searchStyle from 'styles/search'; import SearchRightHeaderIcon from 'component/searchRightHeaderIcon'; +const SYNC_GET_INTERVAL = 1000 * 60 * 5; // every 5 minutes + const menuNavigationButton = navigation => ( this.checkEmailVerification(), 5000); Linking.addEventListener('url', this._handleUrl); + + // call /sync/get with interval + setInterval(() => { + this.setState({ syncHashChanged: false }); // reset local state + NativeModules.UtilityModule.getSecureValue(Constants.KEY_FIRST_RUN_PASSWORD).then(walletPassword => { + dispatch(doGetSync(walletPassword)); + }); + }, SYNC_GET_INTERVAL); } checkEmailVerification = () => { @@ -308,8 +321,8 @@ class AppWithNavigationState extends React.Component { getUserSettings = () => { const { dispatch } = this.props; - Lbryio.call('user_settings', 'get').then(settings => { - dispatch(doPopulateSharedUserState(settings)); + doPreferenceGet('shared', null, null, preference => { + dispatch(doPopulateSharedUserState(preference)); }); }; @@ -320,7 +333,7 @@ class AppWithNavigationState extends React.Component { } componentDidUpdate() { - const { dispatch, user } = this.props; + const { dispatch, user, hashChanged } = this.props; if (this.state.verifyPending && this.emailVerifyCheckInterval > 0 && user && user.has_verified_email) { clearInterval(this.emailVerifyCheckInterval); AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'false'); @@ -332,6 +345,11 @@ class AppWithNavigationState extends React.Component { // get user settings after email verification this.getUserSettings(); } + + if (hashChanged && !this.state.syncHashChanged) { + this.setState({ syncHashChanged: true }); + this.getUserSettings(); + } } componentWillUpdate(nextProps) { @@ -438,6 +456,7 @@ class AppWithNavigationState extends React.Component { const mapStateToProps = state => ({ backgroundPlayEnabled: makeSelectClientSetting(SETTINGS.BACKGROUND_PLAY_ENABLED)(state), + hashChanged: selectHashChanged(state), keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state), nav: state.nav, toast: selectToast(state), diff --git a/src/component/channelSelector/index.js b/src/component/channelSelector/index.js index daee8c7..eb9bae9 100644 --- a/src/component/channelSelector/index.js +++ b/src/component/channelSelector/index.js @@ -7,6 +7,7 @@ import { doCreateChannel, doToast, } from 'lbry-redux'; +import { doGetSync } from 'lbryinc'; import ChannelSelector from './view'; const select = state => ({ @@ -19,6 +20,7 @@ const perform = dispatch => ({ notify: data => dispatch(doToast(data)), createChannel: (name, amount) => dispatch(doCreateChannel(name, amount)), fetchChannelListMine: () => dispatch(doFetchChannelListMine()), + getSync: password => dispatch(doGetSync(password)), }); export default connect( diff --git a/src/component/channelSelector/view.js b/src/component/channelSelector/view.js index bd5cfbe..a4e6388 100644 --- a/src/component/channelSelector/view.js +++ b/src/component/channelSelector/view.js @@ -1,6 +1,6 @@ import React from 'react'; import { CLAIM_VALUES, isNameValid } from 'lbry-redux'; -import { ActivityIndicator, Picker, Text, TextInput, TouchableOpacity, View } from 'react-native'; +import { ActivityIndicator, NativeModules, Picker, Text, TextInput, TouchableOpacity, View } from 'react-native'; import Button from 'component/button'; import Colors from 'styles/colors'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api @@ -117,7 +117,7 @@ export default class ChannelSelector extends React.PureComponent { }; handleCreateChannelClick = () => { - const { balance, createChannel, onChannelChange, notify } = this.props; + const { balance, createChannel, getSync, onChannelChange, notify } = this.props; const { newChannelBid, newChannelName } = this.state; if (newChannelName.trim().length === 0 || !isNameValid(newChannelName.substr(1), false)) { @@ -153,6 +153,9 @@ export default class ChannelSelector extends React.PureComponent { if (onChannelChange) { onChannelChange(channelName); } + + // sync wallet + NativeModules.UtilityModule.getSecureValue(Constants.KEY_FIRST_RUN_PASSWORD).then(password => getSync(password)); }; const failure = () => { diff --git a/src/index.js b/src/index.js index 4b470b0..cea3631 100644 --- a/src/index.js +++ b/src/index.js @@ -13,6 +13,7 @@ import { searchReducer, tagsReducer, walletReducer, + sharedStateSubscriber, } from 'lbry-redux'; import { Lbryio, @@ -147,25 +148,28 @@ const persistor = persistStore(store, persistOptions, err => { }); window.persistor = persistor; -let currentPayload; -store.subscribe(() => { - const state = store.getState(); - const subscriptions = state.subscriptions.subscriptions.map(({ uri }) => uri); - const tags = state.tags.followedTags; - - const newPayload = { - version: '0.1', - shared: { - subscriptions, - tags, +/** + * source: the reducer name + * property: the property in the reducer-specific state + * transform: optional method to modify the value to be stored + */ +const sharedStateFilters = { + tags: { source: 'tags', property: 'followedTags' }, + subscriptions: { + source: 'subscriptions', + property: 'subscriptions', + transform: function(value) { + return value.map(({ uri }) => uri); }, - }; + }, +}; - if (!isEqual(newPayload, currentPayload)) { - currentPayload = newPayload; - if (Lbryio.authToken) { - Lbryio.call('user_settings', 'set', { settings: JSON.stringify(newPayload) }); - } +store.subscribe(() => { + try { + const state = store.getState(); + sharedStateSubscriber(state, sharedStateFilters, '0.1'); + } catch (e) { + // handle gracefully? } }); diff --git a/src/page/channelCreator/index.js b/src/page/channelCreator/index.js index b58c369..085cf2a 100644 --- a/src/page/channelCreator/index.js +++ b/src/page/channelCreator/index.js @@ -12,6 +12,7 @@ import { doUpdateChannel, doToast, } from 'lbry-redux'; +import { doGetSync } from 'lbryinc'; import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doUpdateChannelFormState, doClearChannelFormState } from 'redux/actions/form'; import { selectDrawerStack } from 'redux/selectors/drawer'; @@ -37,6 +38,7 @@ const perform = dispatch => ({ clearChannelFormState: () => dispatch(doClearChannelFormState()), createChannel: (name, amount, optionalParams) => dispatch(doCreateChannel(name, amount, optionalParams)), fetchChannelListMine: () => dispatch(doFetchChannelListMine()), + getSync: password => dispatch(doGetSync(password)), updateChannel: params => dispatch(doUpdateChannel(params)), updateChannelFormState: data => dispatch(doUpdateChannelFormState(data)), pushDrawerStack: (routeName, params) => dispatch(doPushDrawerStack(routeName, params)), diff --git a/src/page/channelCreator/view.js b/src/page/channelCreator/view.js index 17a90d7..506a7aa 100644 --- a/src/page/channelCreator/view.js +++ b/src/page/channelCreator/view.js @@ -376,7 +376,15 @@ export default class ChannelCreator extends React.PureComponent { }; handleCreateChannelClick = () => { - const { balance, clearChannelFormState, createChannel, onChannelChange, notify, updateChannel } = this.props; + const { + balance, + clearChannelFormState, + createChannel, + onChannelChange, + getSync, + notify, + updateChannel, + } = this.props; const { claimId, coverImageUrl, @@ -439,6 +447,9 @@ export default class ChannelCreator extends React.PureComponent { clearChannelFormState(); notify({ message: 'The channel was successfully created.' }); this.showChannelList(); + + // sync wallet + NativeModules.UtilityModule.getSecureValue(Constants.KEY_FIRST_RUN_PASSWORD).then(password => getSync(password)); }; const failure = () => { diff --git a/src/page/firstRun/internal/skip-account-page.js b/src/page/firstRun/internal/skip-account-page.js index 0bbce1e..4fa20b3 100644 --- a/src/page/firstRun/internal/skip-account-page.js +++ b/src/page/firstRun/internal/skip-account-page.js @@ -12,7 +12,7 @@ import { View, } from 'react-native'; import Colors from 'styles/colors'; -import Constants from 'constants'; +import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import Icon from 'react-native-vector-icons/FontAwesome5'; import firstRunStyle from 'styles/firstRun'; @@ -45,8 +45,8 @@ class SkipAccountPage extends React.PureComponent { /> - I understand that by uninstalling LBRY I will lose any balances or published content with no recovery - option if it is not backed up manually (see wallet page) + I understand that by uninstalling LBRY I will lose any balances or published content with no recovery option + if it is not backed up manually (see wallet page) diff --git a/src/page/splash/view.js b/src/page/splash/view.js index 2a2a5c6..b5ce480 100644 --- a/src/page/splash/view.js +++ b/src/page/splash/view.js @@ -1,5 +1,5 @@ import React from 'react'; -import { Lbry } from 'lbry-redux'; +import { Lbry, doPreferenceGet } from 'lbry-redux'; import { Lbryio } from 'lbryinc'; import { ActivityIndicator, Linking, NativeModules, Platform, Text, View } from 'react-native'; import { NavigationActions, StackActions } from 'react-navigation'; @@ -16,8 +16,6 @@ import splashStyle from 'styles/splash'; const BLOCK_HEIGHT_INTERVAL = 1000 * 60 * 2.5; // every 2.5 minutes -const SETTINGS_GET_INTERVAL = 1000 * 60 * 5; // every 5 minutes - const testingNetwork = 'Testing network'; const waitingForResolution = 'Waiting for name resolution'; @@ -98,9 +96,7 @@ class SplashScreen extends React.PureComponent { // user is authenticated, navigate to the main view if (user.has_verified_email) { NativeModules.UtilityModule.getSecureValue(Constants.KEY_FIRST_RUN_PASSWORD).then(walletPassword => { - if (walletPassword) { - getSync(walletPassword); - } + getSync(walletPassword); this.navigateToMain(); }); return; @@ -113,8 +109,9 @@ class SplashScreen extends React.PureComponent { getUserSettings = () => { const { populateSharedUserState } = this.props; - Lbryio.call('user_settings', 'get').then(settings => { - populateSharedUserState(settings); + + doPreferenceGet('shared', null, null, preference => { + populateSharedUserState(preference); }); }; @@ -139,14 +136,11 @@ class SplashScreen extends React.PureComponent { // get user settings interval this.getUserSettings(); - setInterval(() => this.getUserSettings(), SETTINGS_GET_INTERVAL); if (user && user.id && user.has_verified_email) { // user already authenticated NativeModules.UtilityModule.getSecureValue(Constants.KEY_FIRST_RUN_PASSWORD).then(walletPassword => { - if (walletPassword) { - getSync(walletPassword); - } + getSync(walletPassword); this.navigateToMain(); }); } else { diff --git a/src/page/wallet/view.js b/src/page/wallet/view.js index df6c5f5..491ef88 100644 --- a/src/page/wallet/view.js +++ b/src/page/wallet/view.js @@ -47,9 +47,7 @@ class WalletPage extends React.PureComponent { const { deviceWalletSynced, getSync, user } = this.props; if (deviceWalletSynced && user && user.has_verified_email) { NativeModules.UtilityModule.getSecureValue(Constants.KEY_FIRST_RUN_PASSWORD).then(walletPassword => { - if (walletPassword) { - getSync(walletPassword); - } + getSync(walletPassword); }); } };