From 5eba4ab2ec04b7ecf60aba7271f9f99fa3dc83ff Mon Sep 17 00:00:00 2001 From: Akinwale Ariwodola Date: Mon, 30 Sep 2019 22:54:31 +0100 Subject: [PATCH 1/3] use shared state subscriber for preferences_set and preferences_get --- package-lock.json | 4 ++-- package.json | 2 +- src/index.js | 36 ++++++++++++++++++------------------ 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index 57c6435..1d0eb6f 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#23bcde0539a27fb19bf3a7d87683279194e02046", + "from": "github:lbryio/lbry-redux#23bcde0539a27fb19bf3a7d87683279194e02046", "requires": { "proxy-polyfill": "0.1.6", "reselect": "^3.0.0", diff --git a/package.json b/package.json index 40155f1..dba18fb 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "base-64": "^0.1.0", "@expo/vector-icons": "^8.1.0", "gfycat-style-urls": "^1.0.3", - "lbry-redux": "lbryio/lbry-redux#7ec72a737bcd336f000c5f5085891643110298c3", + "lbry-redux": "lbryio/lbry-redux#23bcde0539a27fb19bf3a7d87683279194e02046", "lbryinc": "lbryio/lbryinc#67bb3e215be3f13605c5e3f9f2b0e2fb880724cf", "lodash": ">=4.17.11", "merge": ">=1.2.1", diff --git a/src/index.js b/src/index.js index 4013fe2..252f85c 100644 --- a/src/index.js +++ b/src/index.js @@ -13,6 +13,7 @@ import { searchReducer, tagsReducer, walletReducer, + sharedStateSubscriber, } from 'lbry-redux'; import { Lbryio, @@ -83,7 +84,7 @@ const compressor = createCompressor(); const authFilter = createFilter('auth', ['authToken']); const contentFilter = createFilter('content', ['positions']); const saveClaimsFilter = createFilter('claims', ['claimsByUri']); -const subscriptionsFilter = createFilter('subscriptions', ['enabledChannelNotifications', 'subscriptions']); +const subscriptionsFilter = createFilter('subscriptions', ['enabledChannelNotifications', 'subscriptions', 'latest']); const settingsFilter = createFilter('settings', ['clientSettings']); const tagsFilter = createFilter('tags', ['followedTags']); const walletFilter = createFilter('wallet', ['receiveAddress']); @@ -147,25 +148,24 @@ 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, +const sharedStateCache = {}; +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, sharedStateCache); + } catch (e) { + // handle gracefully? } }); -- 2.45.2 From f42cbb90a063eec91f0ccb2489a67703b3a8be42 Mon Sep 17 00:00:00 2001 From: Akinwale Ariwodola Date: Wed, 2 Oct 2019 10:29:08 +0100 Subject: [PATCH 2/3] use doPreferenceGet for retrieving saved user state --- src/component/AppNavigator.js | 6 +++--- src/index.js | 8 ++++++-- src/page/splash/view.js | 7 ++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/component/AppNavigator.js b/src/component/AppNavigator.js index a5fb642..2d68083 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, @@ -308,8 +308,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)); }); }; diff --git a/src/index.js b/src/index.js index 252f85c..cea3631 100644 --- a/src/index.js +++ b/src/index.js @@ -148,7 +148,11 @@ const persistor = persistStore(store, persistOptions, err => { }); window.persistor = persistor; -const sharedStateCache = {}; +/** + * 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: { @@ -163,7 +167,7 @@ const sharedStateFilters = { store.subscribe(() => { try { const state = store.getState(); - sharedStateSubscriber(state, sharedStateFilters, sharedStateCache); + sharedStateSubscriber(state, sharedStateFilters, '0.1'); } catch (e) { // handle gracefully? } diff --git a/src/page/splash/view.js b/src/page/splash/view.js index 2a2a5c6..3eecfdc 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'; @@ -113,8 +113,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); }); }; -- 2.45.2 From 79c02825d187844d759514117c664f9426c641ca Mon Sep 17 00:00:00 2001 From: Akinwale Ariwodola Date: Fri, 11 Oct 2019 17:12:51 +0100 Subject: [PATCH 3/3] preferences sync and wallet sync updates --- package.json | 4 ++-- src/component/AppNavigator.js | 21 ++++++++++++++++++++- src/component/channelSelector/index.js | 2 ++ src/component/channelSelector/view.js | 7 +++++-- src/page/channelCreator/index.js | 2 ++ src/page/channelCreator/view.js | 13 ++++++++++++- src/page/splash/view.js | 11 ++--------- src/page/wallet/view.js | 4 +--- 8 files changed, 46 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index dba18fb..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#23bcde0539a27fb19bf3a7d87683279194e02046", - "lbryinc": "lbryio/lbryinc#67bb3e215be3f13605c5e3f9f2b0e2fb880724cf", + "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 2d68083..462d520 100644 --- a/src/component/AppNavigator.js +++ b/src/component/AppNavigator.js @@ -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 = () => { @@ -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/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/splash/view.js b/src/page/splash/view.js index 3eecfdc..b5ce480 100644 --- a/src/page/splash/view.js +++ b/src/page/splash/view.js @@ -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; @@ -140,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); }); } }; -- 2.45.2