diff --git a/package-lock.json b/package-lock.json
index 81cc5c6..0cc3e74 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5640,8 +5640,8 @@
}
},
"lbry-redux": {
- "version": "github:lbryio/lbry-redux#123efacf4d45289ebda9dc291976d475de227a55",
- "from": "github:lbryio/lbry-redux#123efacf4d45289ebda9dc291976d475de227a55",
+ "version": "github:lbryio/lbry-redux#d44cd9ca56dee784dba42c0cc13061ae75cbd46c",
+ "from": "github:lbryio/lbry-redux#d44cd9ca56dee784dba42c0cc13061ae75cbd46c",
"requires": {
"proxy-polyfill": "0.1.6",
"reselect": "^3.0.0",
@@ -5649,8 +5649,8 @@
}
},
"lbryinc": {
- "version": "github:lbryio/lbryinc#b9f354ae50bd57691765a7d042c5054167878bf4",
- "from": "github:lbryio/lbryinc#b9f354ae50bd57691765a7d042c5054167878bf4",
+ "version": "github:lbryio/lbryinc#d250096a6fc5df16be4f82812ecce28d6e558b6e",
+ "from": "github:lbryio/lbryinc#d250096a6fc5df16be4f82812ecce28d6e558b6e",
"requires": {
"reselect": "^3.0.0"
}
diff --git a/package.json b/package.json
index 57d482b..9a434c5 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#123efacf4d45289ebda9dc291976d475de227a55",
- "lbryinc": "lbryio/lbryinc#b9f354ae50bd57691765a7d042c5054167878bf4",
+ "lbry-redux": "lbryio/lbry-redux#d44cd9ca56dee784dba42c0cc13061ae75cbd46c",
+ "lbryinc": "lbryio/lbryinc#d250096a6fc5df16be4f82812ecce28d6e558b6e",
"lodash": ">=4.17.11",
"merge": ">=1.2.1",
"moment": "^2.22.1",
diff --git a/src/assets/gerbil-happy.png b/src/assets/gerbil-happy.png
new file mode 100644
index 0000000..4247f83
Binary files /dev/null and b/src/assets/gerbil-happy.png differ
diff --git a/src/assets/gerbil-sad.png b/src/assets/gerbil-sad.png
new file mode 100644
index 0000000..153d4ad
Binary files /dev/null and b/src/assets/gerbil-sad.png differ
diff --git a/src/component/AppNavigator.js b/src/component/AppNavigator.js
index db24edb..a5fb642 100644
--- a/src/component/AppNavigator.js
+++ b/src/component/AppNavigator.js
@@ -29,8 +29,9 @@ 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, doToast, selectToast } from 'lbry-redux';
+import { SETTINGS, doDismissToast, doPopulateSharedUserState, doToast, selectToast } from 'lbry-redux';
import {
+ Lbryio,
doGetSync,
doUserCheckEmailVerified,
doUserEmailVerify,
@@ -305,6 +306,13 @@ class AppWithNavigationState extends React.Component {
});
};
+ getUserSettings = () => {
+ const { dispatch } = this.props;
+ Lbryio.call('user_settings', 'get').then(settings => {
+ dispatch(doPopulateSharedUserState(settings));
+ });
+ };
+
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
BackHandler.removeEventListener('hardwareBackPress');
@@ -321,12 +329,8 @@ class AppWithNavigationState extends React.Component {
NativeModules.Firebase.track('email_verified', { email: user.primary_email });
ToastAndroid.show('Your email address was successfully verified.', ToastAndroid.LONG);
- // upon successful email verification, do wallet sync (if password has been set)
- NativeModules.UtilityModule.getSecureValue(Constants.KEY_FIRST_RUN_PASSWORD).then(walletPassword => {
- if (walletPassword && walletPassword.trim().length > 0) {
- dispatch(doGetSync(walletPassword));
- }
- });
+ // get user settings after email verification
+ this.getUserSettings();
}
}
diff --git a/src/component/channelSelector/view.js b/src/component/channelSelector/view.js
index e5e8c29..b8d81a8 100644
--- a/src/component/channelSelector/view.js
+++ b/src/component/channelSelector/view.js
@@ -26,8 +26,8 @@ export default class ChannelSelector extends React.PureComponent {
}
componentDidMount() {
- const { channels, channelName, fetchChannelListMine, fetchingChannels } = this.props;
- if (!channels.length && !fetchingChannels) {
+ const { channels = [], channelName, fetchChannelListMine, fetchingChannels } = this.props;
+ if ((!channels || channels.length === 0) && !fetchingChannels) {
fetchChannelListMine();
}
this.setState({ currentSelectedValue: channelName });
@@ -37,7 +37,7 @@ export default class ChannelSelector extends React.PureComponent {
const { channels: prevChannels = [], channelName } = this.props;
const { channels = [] } = nextProps;
- if (channels.length !== prevChannels.length && channelName !== this.state.currentSelectedValue) {
+ if (channels && channels.length !== prevChannels.length && channelName !== this.state.currentSelectedValue) {
this.setState({ currentSelectedValue: channelName });
}
}
@@ -182,7 +182,9 @@ export default class ChannelSelector extends React.PureComponent {
render() {
const channel = this.state.addingChannel ? 'new' : this.props.channel;
const { enabled, fetchingChannels, channels = [] } = this.props;
- const pickerItems = [Constants.ITEM_ANONYMOUS, Constants.ITEM_CREATE_A_CHANNEL].concat(channels.map(ch => ch.name));
+ const pickerItems = [Constants.ITEM_ANONYMOUS, Constants.ITEM_CREATE_A_CHANNEL].concat(
+ channels ? channels.map(ch => ch.name) : []
+ );
const {
newChannelName,
diff --git a/src/component/emptyStateView/index.js b/src/component/emptyStateView/index.js
new file mode 100644
index 0000000..53e1c84
--- /dev/null
+++ b/src/component/emptyStateView/index.js
@@ -0,0 +1,4 @@
+import { connect } from 'react-redux';
+import EmptyStateView from './view';
+
+export default connect()(EmptyStateView);
diff --git a/src/component/emptyStateView/view.js b/src/component/emptyStateView/view.js
new file mode 100644
index 0000000..e69ceda
--- /dev/null
+++ b/src/component/emptyStateView/view.js
@@ -0,0 +1,26 @@
+import React from 'react';
+import { NativeModules, Text, View, Image, TouchableOpacity } from 'react-native';
+import Button from '../button';
+import emptyStateStyle from 'styles/emptyState';
+
+class EmptyStateView extends React.PureComponent {
+ render() {
+ const { message, buttonText, inner, onButtonPress } = this.props;
+
+ return (
+
+
+ {message}
+ {buttonText && (
+
+
+
+ )}
+
+ );
+ }
+}
+
+export default EmptyStateView;
diff --git a/src/component/rewardCard/view.js b/src/component/rewardCard/view.js
index e5faaca..8db4147 100644
--- a/src/component/rewardCard/view.js
+++ b/src/component/rewardCard/view.js
@@ -59,7 +59,8 @@ class RewardCard extends React.PureComponent {
getDisplayAmount = () => {
const { reward } = this.props;
if (reward) {
- if (reward.reward_range && reward.reward_range.includes('-')) {
+ const claimed = !!reward.transaction_id;
+ if (!claimed && reward.reward_range && reward.reward_range.includes('-')) {
return reward.reward_range.split('-')[0] + '+'; // ex: 5+
} else if (reward.reward_amount > 0) {
return reward.reward_amount;
diff --git a/src/index.js b/src/index.js
index 9b92508..4013fe2 100644
--- a/src/index.js
+++ b/src/index.js
@@ -15,6 +15,7 @@ import {
walletReducer,
} from 'lbry-redux';
import {
+ Lbryio,
authReducer,
blacklistReducer,
costInfoReducer,
@@ -41,6 +42,7 @@ import formReducer from 'redux/reducers/form';
import drawerReducer from 'redux/reducers/drawer';
import settingsReducer from 'redux/reducers/settings';
import thunk from 'redux-thunk';
+import isEqual from 'utils/deep-equal';
const globalExceptionHandler = (error, isFatal) => {
if (error && NativeModules.Firebase) {
@@ -145,22 +147,27 @@ const persistor = persistStore(store, persistOptions, err => {
});
window.persistor = persistor;
-/*
-const persistFilter = {
- 'auth': ['authToken'],
- 'claims': ['byId', 'claimsByUri'],
- 'content': ['positions'],
- 'subscriptions': ['enabledChannelNotifications', 'subscriptions'],
- 'settings': ['clientSettings'],
- 'tags': ['followedTags'],
- 'wallet': ['receiveAddress']
-};
-
+let currentPayload;
store.subscribe(() => {
- const state = (({ auth, claims, content, subscriptions, settings, tags, wallet }) =>
- ({ auth, claims, content, subscriptions, settings, tags, wallet }))(store.getState());
- NativeModules.StatePersistor.update(state, persistFilter);
-}); */
+ 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,
+ },
+ };
+
+ if (!isEqual(newPayload, currentPayload)) {
+ currentPayload = newPayload;
+ if (Lbryio.authToken) {
+ Lbryio.call('user_settings', 'set', { settings: JSON.stringify(newPayload) });
+ }
+ }
+});
// TODO: Find i18n module that is compatible with react-native
global.__ = str => str;
diff --git a/src/page/channel/index.js b/src/page/channel/index.js
index fae3125..42c42cf 100644
--- a/src/page/channel/index.js
+++ b/src/page/channel/index.js
@@ -1,5 +1,5 @@
import { connect } from 'react-redux';
-import { makeSelectClaimForUri, selectMyChannelClaims } from 'lbry-redux';
+import { doAbandonClaim, doFetchChannelListMine, makeSelectClaimForUri, selectMyChannelClaims } from 'lbry-redux';
import { doPopDrawerStack } from 'redux/actions/drawer';
import { doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
import { selectDrawerStack } from 'redux/selectors/drawer';
@@ -15,6 +15,8 @@ const select = (state, props) => ({
});
const perform = dispatch => ({
+ abandonClaim: (txid, nout) => dispatch(doAbandonClaim(txid, nout)),
+ fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
popDrawerStack: () => dispatch(doPopDrawerStack()),
setSortByItem: item => dispatch(doSetSortByItem(item)),
setTimeItem: item => dispatch(doSetTimeItem(item)),
diff --git a/src/page/channel/view.js b/src/page/channel/view.js
index d20ffd5..2a787be 100644
--- a/src/page/channel/view.js
+++ b/src/page/channel/view.js
@@ -19,6 +19,7 @@ import ClaimList from 'component/claimList';
import Colors from 'styles/colors';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import Button from 'component/button';
+import EmptyStateView from 'component/emptyStateView';
import Icon from 'react-native-vector-icons/FontAwesome5';
import Link from 'component/link';
import ModalPicker from 'component/modalPicker';
@@ -47,7 +48,9 @@ class ChannelPage extends React.PureComponent {
}
componentDidMount() {
+ const { fetchChannelListMine } = this.props;
NativeModules.Firebase.setCurrentScreen('Channel');
+ fetchChannelListMine();
}
handleSortByItemSelected = item => {
@@ -128,9 +131,7 @@ class ChannelPage extends React.PureComponent {
return (
{!websiteUrl && !email && !description && (
-
- Nothing here yet. Please check back later.
-
+
)}
{(websiteUrl || email || description) && (
@@ -266,7 +267,7 @@ class ChannelPage extends React.PureComponent {
)}
{ownedChannel && (