Compare commits
10 commits
lbry-tv-ex
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
aa5dd878c0 | ||
|
47c6fb5889 | ||
|
89a9571ce1 | ||
|
689e30a5f0 | ||
|
33b4806c84 | ||
|
7e1794ce29 | ||
|
4c4d561f30 | ||
|
a5953dcef0 | ||
|
d33ed55bdf | ||
|
12d7fbd472 |
73 changed files with 1282 additions and 12597 deletions
8
.gitlab-ci.yml
Normal file
8
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
|
||||||
|
build:
|
||||||
|
variables:
|
||||||
|
REACT_NATIVE_BRANCH: $CI_COMMIT_REF_NAME
|
||||||
|
stage: build
|
||||||
|
trigger: lbry/lbry-android
|
2
android
2
android
|
@ -1 +1 @@
|
||||||
Subproject commit bfd3c711abc4f693dbb68b06fdfce67036b1e4a3
|
Subproject commit ff30e7f6a4358fd997a9e6d9f75bfe6959eafcb6
|
|
@ -304,5 +304,23 @@
|
||||||
"This content cannot be viewed at this time. Please try again in a bit.": "This content cannot be viewed at this time. Please try again in a bit.",
|
"This content cannot be viewed at this time. Please try again in a bit.": "This content cannot be viewed at this time. Please try again in a bit.",
|
||||||
"Download file": "Download file",
|
"Download file": "Download file",
|
||||||
"Save %title% (%size%) to your device": "Save %title% (%size%) to your device",
|
"Save %title% (%size%) to your device": "Save %title% (%size%) to your device",
|
||||||
"Save \"%title%\" (%size%) to your device": "Save \"%title%\" (%size%) to your device"
|
"Save \"%title%\" (%size%) to your device": "Save \"%title%\" (%size%) to your device",
|
||||||
|
"Find Channels to follow": "Find Channels to follow",
|
||||||
|
"LBRY works better if you follow at least 5 creators you like. Sign in to show creators you follow if you already have an account.": "LBRY works better if you follow at least 5 creators you like. Sign in to show creators you follow if you already have an account.",
|
||||||
|
"%remaining% more...": "%remaining% more...",
|
||||||
|
"Did you know that you can earn free credits worth up to %amount%?": "Did you know that you can earn free credits worth up to %amount%?",
|
||||||
|
"SHOW ME": "SHOW ME",
|
||||||
|
"Convert credits to USD on Bittrex": "Convert credits to USD on Bittrex",
|
||||||
|
"You also have": "You also have",
|
||||||
|
"in tips": "in tips",
|
||||||
|
"Earn more tips by uploading cool videos": "Earn more tips by uploading cool videos",
|
||||||
|
"You staked": "You staked",
|
||||||
|
"in your publishes": "in your publishes",
|
||||||
|
"in your supports": "in your supports",
|
||||||
|
"Your wallet is not currently synced with lbry.tv. You are responsible for backing up your wallet.": "Your wallet is not currently synced with lbry.tv. You are responsible for backing up your wallet.",
|
||||||
|
"A backup of your wallet is synced with lbry.tv": "A backup of your wallet is synced with lbry.tv",
|
||||||
|
"What does this mean?": "What does this mean?",
|
||||||
|
"LBRY credits allow you to publish or purchase content.": "LBRY credits allow you to publish or purchase content.",
|
||||||
|
"You can obtain free credits worth %amount% after you provide an email address.": "You can obtain free credits worth %amount% after you provide an email address.",
|
||||||
|
"up to": "up to"
|
||||||
}
|
}
|
12178
package-lock.json
generated
12178
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -15,8 +15,8 @@
|
||||||
"base-64": "^0.1.0",
|
"base-64": "^0.1.0",
|
||||||
"@expo/vector-icons": "^8.1.0",
|
"@expo/vector-icons": "^8.1.0",
|
||||||
"gfycat-style-urls": "^1.0.3",
|
"gfycat-style-urls": "^1.0.3",
|
||||||
"lbry-redux": "lbryio/lbry-redux#84e697079968364fe526020086c8a44f4d2ef391",
|
"lbry-redux": "lbryio/lbry-redux#69ffd110dbf3633e5847f61f008751edec033017",
|
||||||
"lbryinc": "lbryio/lbryinc#28afb9b06c3d142bad8347939c043a21b6cb1ae1",
|
"lbryinc": "lbryio/lbryinc#667024ebb7cb207609273174ca422cee47469270",
|
||||||
"lodash": ">=4.17.11",
|
"lodash": ">=4.17.11",
|
||||||
"merge": ">=1.2.1",
|
"merge": ">=1.2.1",
|
||||||
"moment": "^2.22.1",
|
"moment": "^2.22.1",
|
||||||
|
|
|
@ -42,8 +42,10 @@ import {
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { selectDrawerStack } from 'redux/selectors/drawer';
|
import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||||
import {
|
import {
|
||||||
|
Lbry,
|
||||||
ACTIONS,
|
ACTIONS,
|
||||||
SETTINGS,
|
SETTINGS,
|
||||||
|
doBalanceSubscribe,
|
||||||
doDismissToast,
|
doDismissToast,
|
||||||
doPopulateSharedUserState,
|
doPopulateSharedUserState,
|
||||||
doPreferenceGet,
|
doPreferenceGet,
|
||||||
|
@ -52,6 +54,10 @@ import {
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import {
|
import {
|
||||||
Lbryio,
|
Lbryio,
|
||||||
|
rewards as REWARD_TYPES,
|
||||||
|
doBlackListedOutpointsSubscribe,
|
||||||
|
doClaimRewardType,
|
||||||
|
doFilteredOutpointsSubscribe,
|
||||||
doGetSync,
|
doGetSync,
|
||||||
doUserCheckEmailVerified,
|
doUserCheckEmailVerified,
|
||||||
doUserEmailVerify,
|
doUserEmailVerify,
|
||||||
|
@ -75,6 +81,7 @@ import discoverStyle from 'styles/discover';
|
||||||
import searchStyle from 'styles/search';
|
import searchStyle from 'styles/search';
|
||||||
import SearchRightHeaderIcon from 'component/searchRightHeaderIcon';
|
import SearchRightHeaderIcon from 'component/searchRightHeaderIcon';
|
||||||
import Snackbar from 'react-native-snackbar';
|
import Snackbar from 'react-native-snackbar';
|
||||||
|
import { doSetSdkReady } from 'redux/actions/settings';
|
||||||
|
|
||||||
const SYNC_GET_INTERVAL = 1000 * 60 * 5; // every 5 minutes
|
const SYNC_GET_INTERVAL = 1000 * 60 * 5; // every 5 minutes
|
||||||
|
|
||||||
|
@ -327,6 +334,7 @@ class AppWithNavigationState extends React.Component {
|
||||||
this.emailVerifyCheckInterval = setInterval(() => this.checkEmailVerification(), 5000);
|
this.emailVerifyCheckInterval = setInterval(() => this.checkEmailVerification(), 5000);
|
||||||
Linking.addEventListener('url', this._handleUrl);
|
Linking.addEventListener('url', this._handleUrl);
|
||||||
|
|
||||||
|
DeviceEventEmitter.addListener('onSdkReady', this.handleSdkReady);
|
||||||
DeviceEventEmitter.addListener('onDownloadAborted', this.handleDownloadAborted);
|
DeviceEventEmitter.addListener('onDownloadAborted', this.handleDownloadAborted);
|
||||||
DeviceEventEmitter.addListener('onDownloadStarted', this.handleDownloadStarted);
|
DeviceEventEmitter.addListener('onDownloadStarted', this.handleDownloadStarted);
|
||||||
DeviceEventEmitter.addListener('onDownloadUpdated', this.handleDownloadUpdated);
|
DeviceEventEmitter.addListener('onDownloadUpdated', this.handleDownloadUpdated);
|
||||||
|
@ -366,6 +374,70 @@ class AppWithNavigationState extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
checkNewAndroidReward = () => {
|
||||||
|
const { dispatch, doToast } = this.props;
|
||||||
|
const claimRewardCallback = err => {
|
||||||
|
if (err) {
|
||||||
|
// an error occurred, do not display anything
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// reward successfully claimed
|
||||||
|
NativeModules.UtilityModule.setNativeBooleanSetting(Constants.SETTING_NEW_ANDROID_REWARD_CLAIMED, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
NativeModules.UtilityModule.getNativeBooleanSetting(Constants.SETTING_NEW_ANDROID_REWARD_CLAIMED, false).then(
|
||||||
|
rewardClaimed => {
|
||||||
|
if (!rewardClaimed) {
|
||||||
|
dispatch(
|
||||||
|
doClaimRewardType(REWARD_TYPES.TYPE_NEW_ANDROID, { notifyError: false, callback: claimRewardCallback }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
handleSdkReady = () => {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
dispatch(doSetSdkReady());
|
||||||
|
dispatch(doBalanceSubscribe());
|
||||||
|
dispatch(doBlackListedOutpointsSubscribe());
|
||||||
|
dispatch(doFilteredOutpointsSubscribe());
|
||||||
|
|
||||||
|
Lbry.wallet_status().then(secureWalletStatus => {
|
||||||
|
// For now, automatically unlock the wallet if a password is set so that downloads work
|
||||||
|
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(password => {
|
||||||
|
if ((secureWalletStatus.is_encrypted && !secureWalletStatus.is_locked) || secureWalletStatus.is_locked) {
|
||||||
|
this.setState({
|
||||||
|
message: __('Unlocking account'),
|
||||||
|
details: __('Decrypting wallet'),
|
||||||
|
});
|
||||||
|
|
||||||
|
// unlock the wallet and then finish the splash screen
|
||||||
|
Lbry.wallet_unlock({ password: password || '' }).then(unlocked => {
|
||||||
|
if (unlocked) {
|
||||||
|
} else {
|
||||||
|
// this.handleAccountUnlockFailed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.checkNewAndroidReward();
|
||||||
|
};
|
||||||
|
|
||||||
|
handleAccountUnlockFailed() {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
dispatch(
|
||||||
|
doToast({
|
||||||
|
message: __(
|
||||||
|
'Your wallet failed to unlock, which means you may not be able to play any videos or access your funds. Restart the app to fix this.',
|
||||||
|
),
|
||||||
|
isError: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
handleDownloadStarted = evt => {
|
handleDownloadStarted = evt => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
const { uri, outpoint, fileInfo } = evt;
|
const { uri, outpoint, fileInfo } = evt;
|
||||||
|
@ -401,6 +473,7 @@ class AppWithNavigationState extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
DeviceEventEmitter.removeListener('onSdkReady', this.handleSdkReady);
|
||||||
DeviceEventEmitter.removeListener('onDownloadAborted', this.handleDownloadAborted);
|
DeviceEventEmitter.removeListener('onDownloadAborted', this.handleDownloadAborted);
|
||||||
DeviceEventEmitter.removeListener('onDownloadStarted', this.handleDownloadStarted);
|
DeviceEventEmitter.removeListener('onDownloadStarted', this.handleDownloadStarted);
|
||||||
DeviceEventEmitter.removeListener('onDownloadUpdated', this.handleDownloadUpdated);
|
DeviceEventEmitter.removeListener('onDownloadUpdated', this.handleDownloadUpdated);
|
||||||
|
|
|
@ -19,7 +19,4 @@ const perform = dispatch => ({
|
||||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(ChannelIconItem);
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(ChannelIconItem);
|
|
||||||
|
|
|
@ -23,7 +23,4 @@ const perform = dispatch => ({
|
||||||
claimSearch: options => dispatch(doClaimSearch(options)),
|
claimSearch: options => dispatch(doClaimSearch(options)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(ClaimList);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(ClaimList);
|
|
||||||
|
|
|
@ -36,7 +36,4 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(ClaimResultItem);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(ClaimResultItem);
|
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doFetchChannelListMine, selectMyChannelClaims } from 'lbry-redux';
|
import { doToast, selectBalance, selectMyChannelClaims } from 'lbry-redux';
|
||||||
import { selectUser } from 'lbryinc';
|
import { selectUnclaimedRewardValue, selectUser } from 'lbryinc';
|
||||||
|
import { selectSdkReady } from 'redux/selectors/settings';
|
||||||
import DrawerContent from './view';
|
import DrawerContent from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
balance: selectBalance(state),
|
||||||
channels: selectMyChannelClaims(state),
|
channels: selectMyChannelClaims(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
|
unclaimedRewardAmount: selectUnclaimedRewardValue(state),
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
notify: data => dispatch(doToast(data)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(DrawerContent);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(DrawerContent);
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import channelIconStyle from 'styles/channelIcon';
|
import channelIconStyle from 'styles/channelIcon';
|
||||||
import discoverStyle from 'styles/discover';
|
import discoverStyle from 'styles/discover';
|
||||||
|
import { Lbryio } from 'lbryinc';
|
||||||
|
import { formatUsd } from 'utils/helper';
|
||||||
|
|
||||||
const groupedMenuItems = {
|
const groupedMenuItems = {
|
||||||
'Find content': [
|
'Find content': [
|
||||||
|
@ -31,11 +33,27 @@ const groupedMenuItems = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const groupNames = Object.keys(groupedMenuItems);
|
const groupNames = Object.keys(groupedMenuItems);
|
||||||
|
const routesRequiringSdkReady = [
|
||||||
|
Constants.DRAWER_ROUTE_CHANNEL_CREATOR,
|
||||||
|
Constants.DRAWER_ROUTE_MY_LBRY,
|
||||||
|
Constants.DRAWER_ROUTE_PUBLISHES,
|
||||||
|
Constants.DRAWER_ROUTE_PUBLISH,
|
||||||
|
Constants.DRAWER_ROUTE_WALLET,
|
||||||
|
Constants.DRAWER_ROUTE_REWARDS,
|
||||||
|
Constants.DRAWER_ROUTE_INVITES,
|
||||||
|
];
|
||||||
|
|
||||||
class DrawerContent extends React.PureComponent {
|
class DrawerContent extends React.PureComponent {
|
||||||
|
state = {
|
||||||
|
usdExchangeRate: 0,
|
||||||
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { fetchChannelListMine } = this.props;
|
Lbryio.getExchangeRates().then(rates => {
|
||||||
fetchChannelListMine();
|
if (!isNaN(rates.LBC_USD)) {
|
||||||
|
this.setState({ usdExchangeRate: rates.LBC_USD });
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getAvatarImageUrl = () => {
|
getAvatarImageUrl = () => {
|
||||||
|
@ -62,8 +80,23 @@ class DrawerContent extends React.PureComponent {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleItemPress = routeName => {
|
||||||
|
const { navigation, notify, sdkReady } = this.props;
|
||||||
|
if (!sdkReady && routesRequiringSdkReady.includes(routeName)) {
|
||||||
|
if (navigation.closeDrawer) {
|
||||||
|
navigation.closeDrawer();
|
||||||
|
}
|
||||||
|
notify({
|
||||||
|
message: __('The background service is still initializing. Please try again when initialization is complete.'),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
navigation.navigate({ routeName: routeName });
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { activeTintColor, navigation, user, onItemPress } = this.props;
|
const { activeTintColor, balance, navigation, unclaimedRewardAmount, user, onItemPress } = this.props;
|
||||||
const { state } = navigation;
|
const { state } = navigation;
|
||||||
|
|
||||||
const activeItemKey = state.routes[state.index] ? state.routes[state.index].key : null;
|
const activeItemKey = state.routes[state.index] ? state.routes[state.index].key : null;
|
||||||
|
@ -157,7 +190,7 @@ class DrawerContent extends React.PureComponent {
|
||||||
focused ? discoverStyle.menuItemTouchAreaFocused : null,
|
focused ? discoverStyle.menuItemTouchAreaFocused : null,
|
||||||
]}
|
]}
|
||||||
key={item.label}
|
key={item.label}
|
||||||
onPress={() => navigation.navigate({ routeName: item.route })}
|
onPress={() => this.handleItemPress(item.route)}
|
||||||
delayPressIn={0}
|
delayPressIn={0}
|
||||||
>
|
>
|
||||||
<View style={discoverStyle.menuItemIcon}>
|
<View style={discoverStyle.menuItemIcon}>
|
||||||
|
@ -170,6 +203,15 @@ class DrawerContent extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
<Text style={[discoverStyle.menuItem, focused ? discoverStyle.menuItemFocused : null]}>
|
<Text style={[discoverStyle.menuItem, focused ? discoverStyle.menuItemFocused : null]}>
|
||||||
{__(item.label)}
|
{__(item.label)}
|
||||||
|
{item.label === 'Wallet' && this.state.usdExchangeRate > 0 && (
|
||||||
|
<Text> ({formatUsd(parseFloat(balance) * parseFloat(this.state.usdExchangeRate))})</Text>
|
||||||
|
)}
|
||||||
|
{item.label === 'Rewards' && this.state.usdExchangeRate > 0 && (
|
||||||
|
<Text>
|
||||||
|
{' '}
|
||||||
|
({formatUsd(parseFloat(unclaimedRewardAmount) * parseFloat(this.state.usdExchangeRate))})
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
|
@ -35,7 +35,4 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(FileItem);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(FileItem);
|
|
||||||
|
|
|
@ -70,7 +70,9 @@ class FileItem extends React.PureComponent {
|
||||||
const outpointsToHide = !blackListedOutpoints
|
const outpointsToHide = !blackListedOutpoints
|
||||||
? filteredOutpoints
|
? filteredOutpoints
|
||||||
: blackListedOutpoints.concat(filteredOutpoints);
|
: blackListedOutpoints.concat(filteredOutpoints);
|
||||||
shouldHide = outpointsToHide.some(outpoint => outpoint.txid === claim.txid && outpoint.nout === claim.nout);
|
shouldHide = outpointsToHide.some(
|
||||||
|
outpoint => outpoint && outpoint.txid === claim.txid && outpoint.nout === claim.nout,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (shouldHide) {
|
if (shouldHide) {
|
||||||
// don't display blacklisted or filtered outpoints on the Your tags page
|
// don't display blacklisted or filtered outpoints on the Your tags page
|
||||||
|
|
|
@ -36,7 +36,4 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
setPlayerVisible: (visible, uri) => dispatch(doSetPlayerVisible(visible, uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(FileListItem);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(FileListItem);
|
|
||||||
|
|
|
@ -99,6 +99,7 @@ class FileListItem extends React.PureComponent {
|
||||||
isRewardContent,
|
isRewardContent,
|
||||||
channelClaimId,
|
channelClaimId,
|
||||||
fullChannelUri,
|
fullChannelUri,
|
||||||
|
repostUrl,
|
||||||
repostChannel,
|
repostChannel,
|
||||||
repostChannelUrl,
|
repostChannelUrl,
|
||||||
shortChannelUri,
|
shortChannelUri,
|
||||||
|
@ -114,18 +115,21 @@ class FileListItem extends React.PureComponent {
|
||||||
channelClaimId = signingChannel ? signingChannel.claim_id : null;
|
channelClaimId = signingChannel ? signingChannel.claim_id : null;
|
||||||
fullChannelUri = channelClaimId ? `${channel}#${channelClaimId}` : channel;
|
fullChannelUri = channelClaimId ? `${channel}#${channelClaimId}` : channel;
|
||||||
shortChannelUri = signingChannel ? signingChannel.short_url : null;
|
shortChannelUri = signingChannel ? signingChannel.short_url : null;
|
||||||
|
repostUrl = claim.repost_url;
|
||||||
repostChannelUrl = claim.repost_channel_url;
|
repostChannelUrl = claim.repost_channel_url;
|
||||||
if (repostChannelUrl) {
|
if (repostUrl) {
|
||||||
const { claimName: repostChannelName } = parseURI(repostChannelUrl);
|
const { claimName: repostName, channelName } = parseURI(repostUrl);
|
||||||
repostChannel = repostChannelName;
|
repostChannel = channelName;
|
||||||
}
|
}
|
||||||
isRepost = !!repostChannelUrl;
|
isRepost = !!repostUrl;
|
||||||
|
|
||||||
if (blackListedOutpoints || filteredOutpoints) {
|
if (blackListedOutpoints || filteredOutpoints) {
|
||||||
const outpointsToHide = !blackListedOutpoints
|
const outpointsToHide = !blackListedOutpoints
|
||||||
? filteredOutpoints
|
? filteredOutpoints
|
||||||
: blackListedOutpoints.concat(filteredOutpoints);
|
: blackListedOutpoints.concat(filteredOutpoints);
|
||||||
shouldHide = outpointsToHide.some(outpoint => outpoint.txid === claim.txid && outpoint.nout === claim.nout);
|
shouldHide = outpointsToHide.some(
|
||||||
|
outpoint => outpoint && outpoint.txid === claim.txid && outpoint.nout === claim.nout,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: hide channels on tag pages?
|
// TODO: hide channels on tag pages?
|
||||||
|
@ -143,10 +147,23 @@ class FileListItem extends React.PureComponent {
|
||||||
<View>
|
<View>
|
||||||
{isRepost && (
|
{isRepost && (
|
||||||
<View style={fileListStyle.repostInfo}>
|
<View style={fileListStyle.repostInfo}>
|
||||||
<Icon name={"retweet"} size={14} style={fileListStyle.repostIcon} />
|
<Icon name={'retweet'} size={14} style={fileListStyle.repostIcon} />
|
||||||
<Text style={fileListStyle.repostChannelName}>
|
<Text style={fileListStyle.repostChannelName}>
|
||||||
<Link text={repostChannel}
|
<Link
|
||||||
onPress={() => navigateToUri(navigation, normalizeURI(repostChannelUrl), null, false, null, false)} /> reposted</Text>
|
text={`@${repostChannel}`}
|
||||||
|
onPress={() =>
|
||||||
|
navigateToUri(
|
||||||
|
navigation,
|
||||||
|
normalizeURI(repostChannelUrl || `@${repostChannel}`),
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>{' '}
|
||||||
|
reposted
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { connect } from 'react-redux';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import { selectBalance } from 'lbry-redux';
|
import { selectBalance } from 'lbry-redux';
|
||||||
import { selectUnclaimedRewardValue } from 'lbryinc';
|
import { selectUnclaimedRewardValue } from 'lbryinc';
|
||||||
import Constants from 'constants';
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import FloatingWalletBalance from './view';
|
import FloatingWalletBalance from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
@ -11,7 +11,4 @@ const select = state => ({
|
||||||
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, null)(FloatingWalletBalance);
|
||||||
select,
|
|
||||||
null
|
|
||||||
)(FloatingWalletBalance);
|
|
||||||
|
|
28
src/component/modalRepostView/index.js
Normal file
28
src/component/modalRepostView/index.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import {
|
||||||
|
doClearRepostError,
|
||||||
|
doFetchChannelListMine,
|
||||||
|
doRepost,
|
||||||
|
doToast,
|
||||||
|
selectBalance,
|
||||||
|
selectMyChannelClaims,
|
||||||
|
selectRepostError,
|
||||||
|
selectRepostLoading,
|
||||||
|
} from 'lbry-redux';
|
||||||
|
import ModalRepostView from './view';
|
||||||
|
|
||||||
|
const select = state => ({
|
||||||
|
balance: selectBalance(state),
|
||||||
|
channels: selectMyChannelClaims(state),
|
||||||
|
reposting: selectRepostLoading(state),
|
||||||
|
error: selectRepostError(state),
|
||||||
|
});
|
||||||
|
|
||||||
|
const perform = dispatch => ({
|
||||||
|
fetchChannelListMine: () => dispatch(doFetchChannelListMine(1, 99999, true)),
|
||||||
|
notify: data => dispatch(doToast(data)),
|
||||||
|
repost: options => dispatch(doRepost(options)),
|
||||||
|
clearError: () => dispatch(doClearRepostError()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(select, perform)(ModalRepostView);
|
204
src/component/modalRepostView/view.js
Normal file
204
src/component/modalRepostView/view.js
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { ActivityIndicator, Alert, Text, TextInput, TouchableOpacity, View } from 'react-native';
|
||||||
|
import { formatCredits, creditsToString } from 'lbry-redux';
|
||||||
|
import modalStyle from 'styles/modal';
|
||||||
|
import modalRepostStyle from 'styles/modalRepost';
|
||||||
|
import ChannelSelector from 'component/channelSelector';
|
||||||
|
import Button from 'component/button';
|
||||||
|
import Colors from 'styles/colors';
|
||||||
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
|
import Link from 'component/link';
|
||||||
|
import { logPublish } from 'utils/helper';
|
||||||
|
|
||||||
|
export default class ModalRepostView extends React.PureComponent {
|
||||||
|
depositAmountInput;
|
||||||
|
|
||||||
|
state = {
|
||||||
|
channelName: null,
|
||||||
|
creditsInputFocused: false,
|
||||||
|
depositAmount: '0.01',
|
||||||
|
repostName: null,
|
||||||
|
repostStarted: false,
|
||||||
|
showAdvanced: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { claim, fetchChannelListMine } = this.props;
|
||||||
|
const { name } = claim;
|
||||||
|
fetchChannelListMine();
|
||||||
|
this.setState({ repostName: name });
|
||||||
|
this.checkChannelSelection(this.props);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
this.checkChannelSelection(nextProps);
|
||||||
|
const { notify } = this.props;
|
||||||
|
const { reposting, error } = nextProps;
|
||||||
|
if (this.state.repostStarted && !reposting && error) {
|
||||||
|
this.setState({ repostStarted: false });
|
||||||
|
notify({ message: error, isError: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkChannelSelection = props => {
|
||||||
|
const { channels = [] } = props;
|
||||||
|
if (!this.state.channelName && channels && channels.length > 0) {
|
||||||
|
const firstChannel = channels[0];
|
||||||
|
this.setState({ channelName: firstChannel.name });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleChannelChange = channelName => {
|
||||||
|
const { channels = [] } = this.props;
|
||||||
|
if (channels && channels.length > 0) {
|
||||||
|
const filtered = channels.filter(c => c.name === channelName);
|
||||||
|
if (filtered.length > 0) {
|
||||||
|
const channel = filtered[0];
|
||||||
|
this.setState({ channelName });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleRepost = () => {
|
||||||
|
const { claim, balance, notify, repost, onRepostSuccessful, channels = [], clearError } = this.props;
|
||||||
|
const { depositAmount, repostName, channelName } = this.state;
|
||||||
|
|
||||||
|
if (parseInt(depositAmount, 10) > balance) {
|
||||||
|
notify({
|
||||||
|
message: 'Insufficient credits',
|
||||||
|
isError: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearError();
|
||||||
|
const channel = channels.filter(ch => ch.name === channelName)[0];
|
||||||
|
this.setState({ repostStarted: true }, () => {
|
||||||
|
repost({
|
||||||
|
name: repostName,
|
||||||
|
bid: creditsToString(depositAmount),
|
||||||
|
channel_id: channel.claim_id,
|
||||||
|
claim_id: claim.claim_id,
|
||||||
|
}).then(repostClaim => {
|
||||||
|
logPublish(repostClaim);
|
||||||
|
this.setState({ repostStarted: false });
|
||||||
|
notify({ message: __('The content was successfully reposted!') });
|
||||||
|
if (onRepostSuccessful) onRepostSuccessful();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { balance, channels, reposting, title, onCancelPress, onOverlayPress } = this.props;
|
||||||
|
const canRepost = !!this.state.channelName && !!this.state.repostName;
|
||||||
|
const channelsLoaded = channels && channels.length > 0;
|
||||||
|
const processing = this.state.repostStarted || reposting || !channelsLoaded;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity style={modalStyle.overlay} activeOpacity={1} onPress={onOverlayPress}>
|
||||||
|
<TouchableOpacity style={modalStyle.container} activeOpacity={1}>
|
||||||
|
<View
|
||||||
|
style={modalRepostStyle.container}
|
||||||
|
onLayout={() => {
|
||||||
|
if (this.tipAmountInput) {
|
||||||
|
this.tipAmountInput.focus();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={modalRepostStyle.title} numberOfLines={1}>
|
||||||
|
{__('Repost %title%', { title })}
|
||||||
|
</Text>
|
||||||
|
<Text style={modalRepostStyle.infoText}>
|
||||||
|
{__('Repost your favorite content to help more people discover them!')}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={modalRepostStyle.label}>{__('Channel to post on')}</Text>
|
||||||
|
<ChannelSelector
|
||||||
|
showAnonymous={false}
|
||||||
|
channelName={this.state.channelName}
|
||||||
|
onChannelChange={this.handleChannelChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{this.state.showAdvanced && (
|
||||||
|
<View>
|
||||||
|
<Text style={modalRepostStyle.label}>{__('Name')}</Text>
|
||||||
|
<View style={modalRepostStyle.nameRow}>
|
||||||
|
<TextInput
|
||||||
|
editable={false}
|
||||||
|
value={this.state.channelName ? `lbry://${this.state.channelName}/` : ''}
|
||||||
|
style={modalRepostStyle.input}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
editable={canRepost}
|
||||||
|
value={this.state.repostName}
|
||||||
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
|
selectTextOnFocus
|
||||||
|
onChangeText={value => this.setState({ repostName: value })}
|
||||||
|
style={modalRepostStyle.input}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text style={modalRepostStyle.label}>{__('Deposit')}</Text>
|
||||||
|
<View style={modalRepostStyle.row}>
|
||||||
|
<View style={modalRepostStyle.amountRow}>
|
||||||
|
<TextInput
|
||||||
|
editable={!this.state.repostStarted}
|
||||||
|
ref={ref => (this.depositAmountInput = ref)}
|
||||||
|
onChangeText={value => this.setState({ tipAmount: value })}
|
||||||
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
|
keyboardType={'numeric'}
|
||||||
|
onFocus={() => this.setState({ creditsInputFocused: true })}
|
||||||
|
onBlur={() => this.setState({ creditsInputFocused: false })}
|
||||||
|
placeholder={'0'}
|
||||||
|
value={this.state.depositAmount}
|
||||||
|
selectTextOnFocus
|
||||||
|
style={modalRepostStyle.depositAmountInput}
|
||||||
|
/>
|
||||||
|
<Text style={modalRepostStyle.currency}>LBC</Text>
|
||||||
|
<View style={modalRepostStyle.balance}>
|
||||||
|
{this.state.creditsInputFocused && <Icon name="coins" size={12} />}
|
||||||
|
{this.state.creditsInputFocused && (
|
||||||
|
<Text style={modalRepostStyle.balanceText}>{formatCredits(parseFloat(balance), 1, true)}</Text>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<View style={modalRepostStyle.buttonRow}>
|
||||||
|
{!processing && (
|
||||||
|
<Link
|
||||||
|
style={modalRepostStyle.cancelLink}
|
||||||
|
text={__('Cancel')}
|
||||||
|
onPress={() => {
|
||||||
|
if (onCancelPress) onCancelPress();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{processing && <ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />}
|
||||||
|
|
||||||
|
<View style={modalRepostStyle.rightButtonRow}>
|
||||||
|
<Link
|
||||||
|
style={modalRepostStyle.advancedLink}
|
||||||
|
text={this.state.showAdvanced ? __('Hide advanced') : __('Show advanced')}
|
||||||
|
onPress={() => {
|
||||||
|
this.setState({ showAdvanced: !this.state.showAdvanced });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
text={__('Repost')}
|
||||||
|
style={modalRepostStyle.button}
|
||||||
|
disabled={!canRepost || this.state.repostStarted || reposting}
|
||||||
|
onPress={this.handleRepost}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doSendTip, doToast, selectBalance } from 'lbry-redux';
|
import { doSendTip, doToast, selectBalance } from 'lbry-redux';
|
||||||
|
import { selectSdkReady } from 'redux/selectors/settings';
|
||||||
import ModalTipView from './view';
|
import ModalTipView from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -12,7 +14,4 @@ const perform = dispatch => ({
|
||||||
dispatch(doSendTip(amount, claimId, isSupport, successCallback, errorCallback)),
|
dispatch(doSendTip(amount, claimId, isSupport, successCallback, errorCallback)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(ModalTipView);
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(ModalTipView);
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import modalStyle from 'styles/modal';
|
||||||
import modalTipStyle from 'styles/modalTip';
|
import modalTipStyle from 'styles/modalTip';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
|
|
||||||
|
@ -19,12 +18,22 @@ export default class ModalTipView extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleSendTip = () => {
|
handleSendTip = () => {
|
||||||
const { claim, balance, notify, onSendTipFailed, onSendTipSuccessful, sendTip } = this.props;
|
const { claim, balance, notify, onSendTipFailed, onSendTipSuccessful, sdkReady, sendTip } = this.props;
|
||||||
const { tipAmount } = this.state;
|
const { tipAmount } = this.state;
|
||||||
|
|
||||||
|
if (!sdkReady) {
|
||||||
|
notify({
|
||||||
|
message: __(
|
||||||
|
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
||||||
|
),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (tipAmount > balance) {
|
if (tipAmount > balance) {
|
||||||
notify({
|
notify({
|
||||||
message: 'Insufficient credits',
|
message: 'Insufficient credits',
|
||||||
|
isError: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -56,13 +65,13 @@ export default class ModalTipView extends React.PureComponent {
|
||||||
() => {
|
() => {
|
||||||
// error
|
// error
|
||||||
if (onSendTipFailed) onSendTipFailed();
|
if (onSendTipFailed) onSendTipFailed();
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
{ cancelable: true }
|
{ cancelable: true },
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -115,7 +124,7 @@ export default class ModalTipView extends React.PureComponent {
|
||||||
<Text style={modalTipStyle.infoText}>
|
<Text style={modalTipStyle.infoText}>
|
||||||
{__(
|
{__(
|
||||||
'This will appear as a tip for %content%, which will boost its ability to be discovered while active.',
|
'This will appear as a tip for %content%, which will boost its ability to be discovered while active.',
|
||||||
{ content: contentName }
|
{ content: contentName },
|
||||||
)}{' '}
|
)}{' '}
|
||||||
<Link
|
<Link
|
||||||
style={modalTipStyle.learnMoreLink}
|
style={modalTipStyle.learnMoreLink}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native';
|
import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import Colors from '../../styles/colors';
|
import { formatUsd } from 'utils/helper';
|
||||||
|
import Colors from 'styles/colors';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from '../link';
|
import Link from 'component/link';
|
||||||
import rewardStyle from '../../styles/reward';
|
import rewardStyle from 'styles/reward';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
canClaim: boolean,
|
canClaim: boolean,
|
||||||
|
@ -61,7 +62,7 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
if (reward) {
|
if (reward) {
|
||||||
const claimed = !!reward.transaction_id;
|
const claimed = !!reward.transaction_id;
|
||||||
if (!claimed && reward.reward_range && reward.reward_range.includes('-')) {
|
if (!claimed && reward.reward_range && reward.reward_range.includes('-')) {
|
||||||
return reward.reward_range.split('-')[0] + '+'; // ex: 5+
|
return reward.reward_range.split('-')[1];
|
||||||
} else if (reward.reward_amount > 0) {
|
} else if (reward.reward_amount > 0) {
|
||||||
return reward.reward_amount;
|
return reward.reward_amount;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +73,7 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { canClaim, isPending, onClaimPress, reward } = this.props;
|
const { canClaim, isPending, onClaimPress, reward, usdExchangeRate } = this.props;
|
||||||
const claimed = !!reward.transaction_id;
|
const claimed = !!reward.transaction_id;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -117,8 +118,16 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
<View style={rewardStyle.rightCol}>
|
<View style={rewardStyle.rightCol}>
|
||||||
|
{reward.reward_range && reward.reward_range.indexOf('-') > -1 && (
|
||||||
|
<Text style={rewardStyle.rightColHeader}>{__('up to')}</Text>
|
||||||
|
)}
|
||||||
<Text style={rewardStyle.rewardAmount}>{this.getDisplayAmount()}</Text>
|
<Text style={rewardStyle.rewardAmount}>{this.getDisplayAmount()}</Text>
|
||||||
<Text style={rewardStyle.rewardCurrency}>LBC</Text>
|
<Text style={rewardStyle.rewardCurrency}>LBC</Text>
|
||||||
|
{usdExchangeRate > 0 && (
|
||||||
|
<Text style={rewardStyle.rewardUsd}>
|
||||||
|
≈{formatUsd(parseFloat(this.getDisplayAmount()) * parseFloat(usdExchangeRate))}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Link from 'component/link';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import rewardStyle from 'styles/reward';
|
import rewardStyle from 'styles/reward';
|
||||||
|
import { formatUsd } from '../../utils/helper';
|
||||||
|
|
||||||
class RewardEnrolment extends React.Component {
|
class RewardEnrolment extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -29,7 +30,7 @@ class RewardEnrolment extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { fetching, navigation, unclaimedRewardAmount, user } = this.props;
|
const { unclaimedRewardAmount, usdExchangeRate } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={rewardStyle.enrollContainer}>
|
<View style={rewardStyle.enrollContainer}>
|
||||||
|
@ -43,9 +44,11 @@ class RewardEnrolment extends React.Component {
|
||||||
|
|
||||||
<View style={rewardStyle.onboarding}>
|
<View style={rewardStyle.onboarding}>
|
||||||
<Text style={rewardStyle.enrollDescText}>
|
<Text style={rewardStyle.enrollDescText}>
|
||||||
{__('LBRY credits allow you to purchase content, publish content, and influence the network.')}
|
{__('LBRY credits allow you to publish or purchase content.')}
|
||||||
{'\n\n'}
|
{'\n\n'}
|
||||||
{__('You get credits for free for providing an email address and taking other basic actions.')}
|
{__('You can obtain free credits worth %amount% after you provide an email address.', {
|
||||||
|
amount: formatUsd(parseFloat(unclaimedRewardAmount) * parseFloat(usdExchangeRate)),
|
||||||
|
})}
|
||||||
{'\n\n'}
|
{'\n\n'}
|
||||||
<Link style={rewardStyle.learnMoreLink} text={__('Learn more')} onPress={this.onLearnMorePressed} />.
|
<Link style={rewardStyle.learnMoreLink} text={__('Learn more')} onPress={this.onLearnMorePressed} />.
|
||||||
</Text>
|
</Text>
|
||||||
|
|
4
src/component/sdkLoadingStatus/index.js
Normal file
4
src/component/sdkLoadingStatus/index.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import SdkLoadingStatus from './view';
|
||||||
|
|
||||||
|
export default connect()(SdkLoadingStatus);
|
15
src/component/sdkLoadingStatus/view.js
Normal file
15
src/component/sdkLoadingStatus/view.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { ActivityIndicator, Text, View } from 'react-native';
|
||||||
|
import React from 'react';
|
||||||
|
import discoverStyle from 'styles/discover';
|
||||||
|
import Colors from 'styles/colors';
|
||||||
|
|
||||||
|
export default class SdkLoadingStatus extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={discoverStyle.sdkLoading}>
|
||||||
|
<ActivityIndicator color={Colors.White} size={'small'} />
|
||||||
|
<Text style={discoverStyle.sdkLoadingText}>{__('The LBRY background service is initializing...')}</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,4 @@ const perform = dispatch => ({
|
||||||
unsubscribe: subscription => doChannelUnsubscribe(subscription),
|
unsubscribe: subscription => doChannelUnsubscribe(subscription),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(SuggestedSubscriptionItem);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(SuggestedSubscriptionItem);
|
|
||||||
|
|
|
@ -16,7 +16,4 @@ const perform = dispatch => ({
|
||||||
claimSearch: options => dispatch(doClaimSearch(options)),
|
claimSearch: options => dispatch(doClaimSearch(options)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(SuggestedSubscriptions);
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(SuggestedSubscriptions);
|
|
||||||
|
|
|
@ -24,7 +24,4 @@ const perform = dispatch => ({
|
||||||
claimSearch: options => dispatch(doClaimSearch(options)),
|
claimSearch: options => dispatch(doClaimSearch(options)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(SuggestedSubscriptionsGrid);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(SuggestedSubscriptionsGrid);
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ class SuggestedSubscriptionsGrid extends React.PureComponent {
|
||||||
const uris = claimSearchByQuery[claimSearchKey];
|
const uris = claimSearchByQuery[claimSearchKey];
|
||||||
if (
|
if (
|
||||||
lastPageReached[claimSearchKey] ||
|
lastPageReached[claimSearchKey] ||
|
||||||
((uris.length > 0 && uris.length < suggestedPageSize) || uris.length >= softLimit)
|
(uris.length > 0 && uris.length < suggestedPageSize) || uris.length >= softLimit
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ class SuggestedSubscriptionsGrid extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claimSearchByQuery, suggested, inModal, navigation } = this.props;
|
const { claimSearchByQuery, inModal, navigation } = this.props;
|
||||||
const options = this.buildClaimSearchOptions();
|
const options = this.buildClaimSearchOptions();
|
||||||
const claimSearchKey = createNormalizedClaimSearchKey(options);
|
const claimSearchKey = createNormalizedClaimSearchKey(options);
|
||||||
const claimSearchUris = claimSearchByQuery[claimSearchKey];
|
const claimSearchUris = claimSearchByQuery[claimSearchKey];
|
||||||
|
@ -92,7 +92,7 @@ class SuggestedSubscriptionsGrid extends React.PureComponent {
|
||||||
maxToRenderPerBatch={48}
|
maxToRenderPerBatch={48}
|
||||||
removeClippedSubviews
|
removeClippedSubviews
|
||||||
itemDimension={120}
|
itemDimension={120}
|
||||||
spacing={2}
|
spacing={1}
|
||||||
items={claimSearchUris}
|
items={claimSearchUris}
|
||||||
style={inModal ? subscriptionsStyle.modalScrollContainer : subscriptionsStyle.scrollContainer}
|
style={inModal ? subscriptionsStyle.modalScrollContainer : subscriptionsStyle.scrollContainer}
|
||||||
contentContainerStyle={
|
contentContainerStyle={
|
||||||
|
|
|
@ -6,7 +6,4 @@ const select = state => ({
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, null)(WalletBalance);
|
||||||
select,
|
|
||||||
null
|
|
||||||
)(WalletBalance);
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Image, Text, View } from 'react-native';
|
import { Image, Text, View } from 'react-native';
|
||||||
import { Lbry, formatCredits } from 'lbry-redux';
|
import { formatCredits } from 'lbry-redux';
|
||||||
import Address from 'component/address';
|
import { Lbryio } from 'lbryinc';
|
||||||
import Button from 'component/button';
|
import { formatUsd } from 'utils/helper';
|
||||||
import walletStyle from 'styles/wallet';
|
import walletStyle from 'styles/wallet';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -11,6 +11,18 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class WalletBalance extends React.PureComponent<Props> {
|
class WalletBalance extends React.PureComponent<Props> {
|
||||||
|
state = {
|
||||||
|
usdExchangeRate: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
Lbryio.getExchangeRates().then(rates => {
|
||||||
|
if (!isNaN(rates.LBC_USD)) {
|
||||||
|
this.setState({ usdExchangeRate: rates.LBC_USD });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { balance } = this.props;
|
const { balance } = this.props;
|
||||||
return (
|
return (
|
||||||
|
@ -21,6 +33,13 @@ class WalletBalance extends React.PureComponent<Props> {
|
||||||
<Text style={walletStyle.balance}>
|
<Text style={walletStyle.balance}>
|
||||||
{(balance || balance === 0) && formatCredits(parseFloat(balance), 2) + ' LBC'}
|
{(balance || balance === 0) && formatCredits(parseFloat(balance), 2) + ' LBC'}
|
||||||
</Text>
|
</Text>
|
||||||
|
<Text style={walletStyle.usdBalance}>
|
||||||
|
{this.state.usdExchangeRate > 0 && (
|
||||||
|
<Text>
|
||||||
|
≈{formatUsd(isNaN(balance) ? 0 : parseFloat(balance) * parseFloat(this.state.usdExchangeRate))}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectClaimsBalance, selectSupportsBalance, selectTipsBalance } from 'lbry-redux';
|
import { selectClaimsBalance, selectSupportsBalance, selectTipsBalance } from 'lbry-redux';
|
||||||
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import WalletBalanceExtra from './view';
|
import WalletBalanceExtra from './view';
|
||||||
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
claimsBalance: selectClaimsBalance(state) || 0,
|
claimsBalance: selectClaimsBalance(state) || 0,
|
||||||
|
deviceWalletSynced: makeSelectClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED)(state),
|
||||||
supportsBalance: selectSupportsBalance(state) || 0,
|
supportsBalance: selectSupportsBalance(state) || 0,
|
||||||
tipsBalance: selectTipsBalance(state) || 0,
|
tipsBalance: selectTipsBalance(state) || 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, null)(WalletBalanceExtra);
|
||||||
select,
|
|
||||||
null,
|
|
||||||
)(WalletBalanceExtra);
|
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Image, Text, View } from 'react-native';
|
import { Text, View } from 'react-native';
|
||||||
import { Lbry, formatCredits } from 'lbry-redux';
|
import { formatCredits } from 'lbry-redux';
|
||||||
import Address from 'component/address';
|
import { Lbryio } from 'lbryinc';
|
||||||
import Button from 'component/button';
|
import { formatUsd } from 'utils/helper';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
|
import Link from 'component/link';
|
||||||
import walletStyle from 'styles/wallet';
|
import walletStyle from 'styles/wallet';
|
||||||
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claimsBalance: number,
|
claimsBalance: number,
|
||||||
|
@ -15,37 +17,96 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class WalletBalanceExtra extends React.PureComponent<Props> {
|
class WalletBalanceExtra extends React.PureComponent<Props> {
|
||||||
|
state = {
|
||||||
|
usdExchangeRate: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
Lbryio.getExchangeRates().then(rates => {
|
||||||
|
if (!isNaN(rates.LBC_USD)) {
|
||||||
|
this.setState({ usdExchangeRate: rates.LBC_USD });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claimsBalance, supportsBalance, tipsBalance } = this.props;
|
const { claimsBalance, deviceWalletSynced, navigation, supportsBalance, tipsBalance } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={walletStyle.balanceExtraCard}>
|
<View style={walletStyle.balanceExtra}>
|
||||||
<View style={walletStyle.walletExtraRow}>
|
<View style={walletStyle.usdInfoCard}>
|
||||||
<View style={walletStyle.walletExtraCol}>
|
<Text style={walletStyle.usdInfoText}>
|
||||||
<Icon style={walletStyle.walletExtraIcon} color={Colors.LbryGreen} name={'gift'} size={16} />
|
You can convert your credits to USD and withdraw the converted amount using an exchange.{' '}
|
||||||
<Text style={walletStyle.walletExtraCaption}>{__('You also have')}</Text>
|
<Link
|
||||||
<View style={walletStyle.balanceRow}>
|
style={walletStyle.usdConvertFaqLink}
|
||||||
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(tipsBalance), 2)}</Text>
|
href={'https://lbry.com/faq/exchanges'}
|
||||||
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
text={__('Learn more')}
|
||||||
</View>
|
/>
|
||||||
<Text style={walletStyle.text}>{__('in tips')}</Text>
|
.
|
||||||
</View>
|
</Text>
|
||||||
|
<Link
|
||||||
|
style={walletStyle.usdConvertLink}
|
||||||
|
href={'https://bittrex.com/Account/Register?referralCode=4M1-P30-BON'}
|
||||||
|
text={__('Convert credits to USD on Bittrex')}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
<View style={walletStyle.walletExtraCol}>
|
<View style={walletStyle.balanceExtraCard}>
|
||||||
<Icon style={walletStyle.walletExtraIcon} color={Colors.LbryGreen} name={'lock'} size={16} />
|
<View style={walletStyle.walletExtraRow}>
|
||||||
<Text style={walletStyle.walletExtraCaption}>{__('You staked')}</Text>
|
<View style={walletStyle.walletExtraCol}>
|
||||||
<View style={walletStyle.balanceRow}>
|
<Icon style={walletStyle.walletExtraIcon} color={Colors.LbryGreen} name={'gift'} size={16} />
|
||||||
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(claimsBalance), 2)}</Text>
|
<Text style={walletStyle.walletExtraCaption}>{__('You also have')}</Text>
|
||||||
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
<View style={walletStyle.balanceRow}>
|
||||||
|
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(tipsBalance), 2)}</Text>
|
||||||
|
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={walletStyle.usdWalletExtraBalance}>
|
||||||
|
≈{formatUsd(parseFloat(tipsBalance) * parseFloat(this.state.usdExchangeRate))}
|
||||||
|
</Text>
|
||||||
|
<Text style={walletStyle.text}>{__('in tips')}</Text>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
style={walletStyle.earnTipsLink}
|
||||||
|
onPress={() => {
|
||||||
|
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_PUBLISH });
|
||||||
|
}}
|
||||||
|
text={__('Earn more tips by uploading cool videos')}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<Text style={walletStyle.text}>{__('in your publishes')}</Text>
|
|
||||||
<View style={[walletStyle.balanceRow, walletStyle.walletExtraTopMargin]}>
|
<View style={walletStyle.walletExtraCol}>
|
||||||
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(supportsBalance), 2)}</Text>
|
<Icon style={walletStyle.walletExtraIcon} color={Colors.LbryGreen} name={'lock'} size={16} />
|
||||||
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
<Text style={walletStyle.walletExtraCaption}>{__('You staked')}</Text>
|
||||||
|
<View style={walletStyle.balanceRow}>
|
||||||
|
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(claimsBalance), 2)}</Text>
|
||||||
|
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={walletStyle.text}>{__('in your publishes')}</Text>
|
||||||
|
<View style={[walletStyle.balanceRow, walletStyle.walletExtraTopMargin]}>
|
||||||
|
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(supportsBalance), 2)}</Text>
|
||||||
|
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={walletStyle.text}>{__('in your supports')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={walletStyle.text}>{__('in your supports')}</Text>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
<View style={walletStyle.syncDriverCustody}>
|
||||||
|
<Text style={walletStyle.syncInfoText}>
|
||||||
|
{deviceWalletSynced
|
||||||
|
? __('A backup of your wallet is synced with lbry.tv')
|
||||||
|
: __('Your wallet is not currently synced with lbry.tv. You are responsible for backing up your wallet.')}
|
||||||
|
</Text>
|
||||||
|
<Link
|
||||||
|
text={__('What does this mean?')}
|
||||||
|
href={
|
||||||
|
deviceWalletSynced
|
||||||
|
? 'https://lbry.com/faq/account-sync'
|
||||||
|
: 'https://lbry.com/faq/how-to-backup-wallet#android'
|
||||||
|
}
|
||||||
|
style={walletStyle.syncInfoLink}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class WalletSyncDriver extends React.PureComponent<Props> {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
{ cancelable: true }
|
{ cancelable: true },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,6 +45,9 @@ const Constants = {
|
||||||
SETTING_REWARDS_NOT_INTERESTED: 'rewardsNotInterested',
|
SETTING_REWARDS_NOT_INTERESTED: 'rewardsNotInterested',
|
||||||
SETTING_DEVICE_WALLET_SYNCED: 'deviceWalletSynced',
|
SETTING_DEVICE_WALLET_SYNCED: 'deviceWalletSynced',
|
||||||
SETTING_DHT_ENABLED: 'dhtEnabled',
|
SETTING_DHT_ENABLED: 'dhtEnabled',
|
||||||
|
SETTING_NEW_ANDROID_REWARD_CLAIMED: 'newAndroidRewardClaimed',
|
||||||
|
|
||||||
|
ACTION_SDK_READY: 'SDK_READY',
|
||||||
|
|
||||||
ACTION_DELETE_COMPLETED_BLOBS: 'DELETE_COMPLETED_BLOBS',
|
ACTION_DELETE_COMPLETED_BLOBS: 'DELETE_COMPLETED_BLOBS',
|
||||||
ACTION_FIRST_RUN_PAGE_CHANGED: 'FIRST_RUN_PAGE_CHANGED',
|
ACTION_FIRST_RUN_PAGE_CHANGED: 'FIRST_RUN_PAGE_CHANGED',
|
||||||
|
@ -147,7 +150,7 @@ const Constants = {
|
||||||
|
|
||||||
TRUE_STRING: 'true',
|
TRUE_STRING: 'true',
|
||||||
|
|
||||||
MINIMUM_TRANSACTION_BALANCE: 0.1,
|
MINIMUM_TRANSACTION_BALANCE: 0.01,
|
||||||
|
|
||||||
SHARE_BASE_URL: 'https://open.lbry.com',
|
SHARE_BASE_URL: 'https://open.lbry.com',
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,6 +55,10 @@ import settingsReducer from 'redux/reducers/settings';
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
|
|
||||||
window.__ = __;
|
window.__ = __;
|
||||||
|
if (!NativeModules.UtilityModule.dhtEnabled) {
|
||||||
|
Lbry.alternateConnectionString = 'https://api.lbry.tv/api/v1/proxy';
|
||||||
|
Lbry.methodsUsingAlternateConnectionString = ['claim_search', 'resolve'];
|
||||||
|
}
|
||||||
|
|
||||||
const globalExceptionHandler = (error, isFatal) => {
|
const globalExceptionHandler = (error, isFatal) => {
|
||||||
if (error && NativeModules.Firebase) {
|
if (error && NativeModules.Firebase) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import {
|
||||||
import { doUpdateChannelFormState, doClearChannelFormState } from 'redux/actions/form';
|
import { doUpdateChannelFormState, doClearChannelFormState } from 'redux/actions/form';
|
||||||
import { selectDrawerStack } from 'redux/selectors/drawer';
|
import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||||
import { selectChannelFormState, selectHasChannelFormState } from 'redux/selectors/form';
|
import { selectChannelFormState, selectHasChannelFormState } from 'redux/selectors/form';
|
||||||
|
import { selectSdkReady } from 'redux/selectors/settings';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import ChannelCreator from './view';
|
import ChannelCreator from './view';
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ const select = state => ({
|
||||||
fetchingChannels: selectFetchingMyChannels(state),
|
fetchingChannels: selectFetchingMyChannels(state),
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
hasFormState: selectHasChannelFormState(state),
|
hasFormState: selectHasChannelFormState(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
updatingChannel: selectUpdatingChannel(state),
|
updatingChannel: selectUpdatingChannel(state),
|
||||||
updateChannelError: selectUpdateChannelError(state),
|
updateChannelError: selectUpdateChannelError(state),
|
||||||
});
|
});
|
||||||
|
@ -52,7 +54,4 @@ const perform = dispatch => ({
|
||||||
setExplicitNavigateBack: flag => dispatch(doSetExplicitNavigateBack(flag)),
|
setExplicitNavigateBack: flag => dispatch(doSetExplicitNavigateBack(flag)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(ChannelCreator);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(ChannelCreator);
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
channelNameUserEdited: false,
|
channelNameUserEdited: false,
|
||||||
newChannelTitle: '',
|
newChannelTitle: '',
|
||||||
newChannelName: '',
|
newChannelName: '',
|
||||||
newChannelBid: 0.1,
|
newChannelBid: 0.01,
|
||||||
addingChannel: false,
|
addingChannel: false,
|
||||||
creatingChannel: false,
|
creatingChannel: false,
|
||||||
editChannelUrl: null,
|
editChannelUrl: null,
|
||||||
|
@ -176,9 +176,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
NativeModules.Firebase.setCurrentScreen('Channels').then(result => {
|
NativeModules.Firebase.setCurrentScreen('Channels').then(result => {
|
||||||
pushDrawerStack(Constants.DRAWER_ROUTE_CHANNEL_CREATOR, navigation.state.params ? navigation.state.params : null);
|
pushDrawerStack(Constants.DRAWER_ROUTE_CHANNEL_CREATOR, navigation.state.params ? navigation.state.params : null);
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
if (!fetchingChannels) {
|
fetchChannelListMine();
|
||||||
fetchChannelListMine();
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceEventEmitter.addListener('onDocumentPickerFilePicked', this.onFilePicked);
|
DeviceEventEmitter.addListener('onDocumentPickerFilePicked', this.onFilePicked);
|
||||||
DeviceEventEmitter.addListener('onDocumentPickerCanceled', this.onPickerCanceled);
|
DeviceEventEmitter.addListener('onDocumentPickerCanceled', this.onPickerCanceled);
|
||||||
|
@ -282,7 +280,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
handleCreateCancel = () => {
|
handleCreateCancel = () => {
|
||||||
const { clearChannelFormState } = this.props;
|
const { clearChannelFormState } = this.props;
|
||||||
clearChannelFormState(); // explicitly clear state on cancel?
|
clearChannelFormState(); // explicitly clear state on cancel?
|
||||||
this.setState({ showCreateChannel: false, newChannelName: '', newChannelBid: 0.1 });
|
this.setState({ showCreateChannel: false, newChannelName: '', newChannelBid: 0.01 });
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePickerValueChange = (itemValue, itemIndex) => {
|
handlePickerValueChange = (itemValue, itemIndex) => {
|
||||||
|
@ -591,7 +589,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
channelNameUserEdited: false,
|
channelNameUserEdited: false,
|
||||||
newChannelTitle: '',
|
newChannelTitle: '',
|
||||||
newChannelName: '',
|
newChannelName: '',
|
||||||
newChannelBid: 0.1,
|
newChannelBid: 0.01,
|
||||||
addingChannel: false,
|
addingChannel: false,
|
||||||
creatingChannel: false,
|
creatingChannel: false,
|
||||||
newChannelNameError: '',
|
newChannelNameError: '',
|
||||||
|
@ -802,7 +800,15 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { abandoningClaimIds, balance, fetchingChannels, updatingChannel, channels = [], navigation } = this.props;
|
const {
|
||||||
|
abandoningClaimIds,
|
||||||
|
balance,
|
||||||
|
fetchingChannels,
|
||||||
|
sdkReady,
|
||||||
|
updatingChannel,
|
||||||
|
channels = [],
|
||||||
|
navigation,
|
||||||
|
} = this.props;
|
||||||
const {
|
const {
|
||||||
autoStyle,
|
autoStyle,
|
||||||
autoStyles,
|
autoStyles,
|
||||||
|
@ -826,6 +832,19 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
|
|
||||||
const hasChannels = channels && channels.length > 0;
|
const hasChannels = channels && channels.length > 0;
|
||||||
|
|
||||||
|
if (!sdkReady) {
|
||||||
|
return (
|
||||||
|
<View style={channelCreatorStyle.container}>
|
||||||
|
<UriBar navigation={navigation} />
|
||||||
|
<EmptyStateView
|
||||||
|
message={__(
|
||||||
|
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={channelCreatorStyle.container}>
|
<View style={channelCreatorStyle.container}>
|
||||||
<UriBar
|
<UriBar
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doSetClientSetting, doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
import { doSetClientSetting, doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
||||||
import { makeSelectClientSetting, selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectSdkReady, selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import DiscoverPage from './view';
|
import DiscoverPage from './view';
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ const select = state => ({
|
||||||
followedTags: selectFollowedTags(state),
|
followedTags: selectFollowedTags(state),
|
||||||
ratingReminderDisabled: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED)(state),
|
ratingReminderDisabled: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED)(state),
|
||||||
ratingReminderLastShown: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_LAST_SHOWN)(state),
|
ratingReminderLastShown: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_LAST_SHOWN)(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
sortByItem: selectSortByItem(state),
|
sortByItem: selectSortByItem(state),
|
||||||
timeItem: selectTimeItem(state),
|
timeItem: selectTimeItem(state),
|
||||||
unreadSubscriptions: selectUnreadSubscriptions(state),
|
unreadSubscriptions: selectUnreadSubscriptions(state),
|
||||||
|
@ -46,7 +47,4 @@ const perform = dispatch => ({
|
||||||
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(DiscoverPage);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(DiscoverPage);
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import ModalTagSelector from 'component/modalTagSelector';
|
import ModalTagSelector from 'component/modalTagSelector';
|
||||||
import ModalPicker from 'component/modalPicker';
|
import ModalPicker from 'component/modalPicker';
|
||||||
|
import SdkLoadingStatus from 'component/sdkLoadingStatus';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
@ -268,8 +269,8 @@ class DiscoverPage extends React.PureComponent {
|
||||||
);
|
);
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { currentRoute, navigation, sortByItem, timeItem } = this.props;
|
const { currentRoute, navigation, sdkReady, sortByItem, timeItem } = this.props;
|
||||||
const { orderBy, showModalTagSelector, showSortPicker, showTimePicker } = this.state;
|
const { showModalTagSelector, showSortPicker, showTimePicker } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={discoverStyle.container}>
|
<View style={discoverStyle.container}>
|
||||||
|
@ -289,7 +290,7 @@ class DiscoverPage extends React.PureComponent {
|
||||||
keyExtractor={(item, index) => item}
|
keyExtractor={(item, index) => item}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!showModalTagSelector && !showSortPicker && !showTimePicker && (
|
{sdkReady && !showModalTagSelector && !showSortPicker && !showTimePicker && (
|
||||||
<FloatingWalletBalance navigation={navigation} />
|
<FloatingWalletBalance navigation={navigation} />
|
||||||
)}
|
)}
|
||||||
{showModalTagSelector && (
|
{showModalTagSelector && (
|
||||||
|
@ -316,6 +317,8 @@ class DiscoverPage extends React.PureComponent {
|
||||||
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{!sdkReady && <SdkLoadingStatus />}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,15 +11,17 @@ import {
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doDeleteFile } from 'redux/actions/file';
|
import { doDeleteFile } from 'redux/actions/file';
|
||||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||||
|
import { selectSdkReady } from 'redux/selectors/settings';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import DownloadsPage from './view';
|
import DownloadsPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
claims: selectMyClaimsWithoutChannels(state),
|
claims: selectMyClaimsWithoutChannels(state),
|
||||||
currentRoute: selectCurrentRoute(state),
|
currentRoute: selectCurrentRoute(state),
|
||||||
fileInfos: selectFileInfosDownloaded(state),
|
|
||||||
downloadedUris: selectDownloadedUris(state),
|
downloadedUris: selectDownloadedUris(state),
|
||||||
|
fileInfos: selectFileInfosDownloaded(state),
|
||||||
fetching: selectIsFetchingFileList(state) || selectIsFetchingClaimListMine(state),
|
fetching: selectIsFetchingFileList(state) || selectIsFetchingClaimListMine(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -32,7 +34,4 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(DownloadsPage);
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(DownloadsPage);
|
|
||||||
|
|
|
@ -144,11 +144,24 @@ class DownloadsPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { fetching, claims, downloadedUris, fileInfos, navigation } = this.props;
|
const { downloadedUris, fetching, navigation, sdkReady } = this.props;
|
||||||
const { selectionMode, selectedUris } = this.state;
|
const { selectionMode, selectedUris } = this.state;
|
||||||
const filteredUris = this.getFilteredUris();
|
const filteredUris = this.getFilteredUris();
|
||||||
const hasDownloads = filteredUris && filteredUris.length > 0;
|
const hasDownloads = filteredUris && filteredUris.length > 0;
|
||||||
|
|
||||||
|
if (!sdkReady) {
|
||||||
|
return (
|
||||||
|
<View style={downloadsStyle.container}>
|
||||||
|
<UriBar navigation={navigation} />
|
||||||
|
<EmptyStateView
|
||||||
|
message={__(
|
||||||
|
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={downloadsStyle.container}>
|
<View style={downloadsStyle.container}>
|
||||||
<UriBar
|
<UriBar
|
||||||
|
|
|
@ -41,6 +41,7 @@ import { doDeleteFile, doStopDownloadingFile } from 'redux/actions/file';
|
||||||
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doToggleFullscreenMode } from 'redux/actions/settings';
|
import { doToggleFullscreenMode } from 'redux/actions/settings';
|
||||||
import { selectDrawerStack, makeSelectPlayerVisible } from 'redux/selectors/drawer';
|
import { selectDrawerStack, makeSelectPlayerVisible } from 'redux/selectors/drawer';
|
||||||
|
import { selectSdkReady } from 'redux/selectors/settings';
|
||||||
import FilePage from './view';
|
import FilePage from './view';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
|
@ -66,6 +67,7 @@ const select = (state, props) => {
|
||||||
failedPurchaseUris: selectFailedPurchaseUris(state),
|
failedPurchaseUris: selectFailedPurchaseUris(state),
|
||||||
myClaimUris: selectMyClaimUrisWithoutChannels(state),
|
myClaimUris: selectMyClaimUrisWithoutChannels(state),
|
||||||
purchaseUriErrorMessage: selectPurchaseUriErrorMessage(state),
|
purchaseUriErrorMessage: selectPurchaseUriErrorMessage(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
streamingUrl: makeSelectStreamingUrlForUri(contentUri)(state),
|
streamingUrl: makeSelectStreamingUrlForUri(contentUri)(state),
|
||||||
thumbnail: makeSelectThumbnailForUri(contentUri)(state),
|
thumbnail: makeSelectThumbnailForUri(contentUri)(state),
|
||||||
title: makeSelectTitleForUri(contentUri)(state),
|
title: makeSelectTitleForUri(contentUri)(state),
|
||||||
|
@ -99,7 +101,4 @@ const perform = dispatch => ({
|
||||||
toggleFullscreenMode: mode => dispatch(doToggleFullscreenMode(mode)),
|
toggleFullscreenMode: mode => dispatch(doToggleFullscreenMode(mode)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(FilePage);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(FilePage);
|
|
||||||
|
|
|
@ -37,13 +37,13 @@ import FilePrice from 'component/filePrice';
|
||||||
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import MediaPlayer from 'component/mediaPlayer';
|
import MediaPlayer from 'component/mediaPlayer';
|
||||||
|
import ModalRepostView from 'component/modalRepostView';
|
||||||
import ModalTipView from 'component/modalTipView';
|
import ModalTipView from 'component/modalTipView';
|
||||||
import ProgressCircle from 'react-native-progress-circle';
|
import ProgressCircle from 'react-native-progress-circle';
|
||||||
import RelatedContent from 'component/relatedContent';
|
import RelatedContent from 'component/relatedContent';
|
||||||
import SubscribeButton from 'component/subscribeButton';
|
import SubscribeButton from 'component/subscribeButton';
|
||||||
import SubscribeNotificationButton from 'component/subscribeNotificationButton';
|
import SubscribeNotificationButton from 'component/subscribeNotificationButton';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import Video from 'react-native-video';
|
|
||||||
import FileRewardsDriver from 'component/fileRewardsDriver';
|
import FileRewardsDriver from 'component/fileRewardsDriver';
|
||||||
import filePageStyle from 'styles/filePage';
|
import filePageStyle from 'styles/filePage';
|
||||||
import uriBarStyle from 'styles/uriBar';
|
import uriBarStyle from 'styles/uriBar';
|
||||||
|
@ -73,7 +73,7 @@ class FilePage extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
attemptAutoGet: false,
|
autoGetAttempted: false,
|
||||||
autoOpened: false,
|
autoOpened: false,
|
||||||
autoDownloadStarted: false,
|
autoDownloadStarted: false,
|
||||||
autoPlayMedia: false,
|
autoPlayMedia: false,
|
||||||
|
@ -95,6 +95,7 @@ class FilePage extends React.PureComponent {
|
||||||
showImageViewer: false,
|
showImageViewer: false,
|
||||||
showWebView: false,
|
showWebView: false,
|
||||||
showTipView: false,
|
showTipView: false,
|
||||||
|
showRepostView: false,
|
||||||
playbackStarted: false,
|
playbackStarted: false,
|
||||||
playerBgHeight: 0,
|
playerBgHeight: 0,
|
||||||
playerHeight: 0,
|
playerHeight: 0,
|
||||||
|
@ -266,6 +267,7 @@ class FilePage extends React.PureComponent {
|
||||||
'playerBgHeighht',
|
'playerBgHeighht',
|
||||||
'playerHeight',
|
'playerHeight',
|
||||||
'relatedY',
|
'relatedY',
|
||||||
|
'showRepostView',
|
||||||
'showTipView',
|
'showTipView',
|
||||||
'showImageViewer',
|
'showImageViewer',
|
||||||
'showWebView',
|
'showWebView',
|
||||||
|
@ -297,7 +299,17 @@ class FilePage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState) {
|
componentDidUpdate(prevProps, prevState) {
|
||||||
const { claim, contentType, costInfo, fileInfo, isResolvingUri, resolveUri, navigation, title } = this.props;
|
const {
|
||||||
|
claim,
|
||||||
|
contentType,
|
||||||
|
costInfo,
|
||||||
|
fileInfo,
|
||||||
|
isResolvingUri,
|
||||||
|
resolveUri,
|
||||||
|
sdkReady,
|
||||||
|
navigation,
|
||||||
|
title,
|
||||||
|
} = this.props;
|
||||||
const { uri } = this.state;
|
const { uri } = this.state;
|
||||||
if (!isResolvingUri && claim === undefined && uri) {
|
if (!isResolvingUri && claim === undefined && uri) {
|
||||||
resolveUri(uri);
|
resolveUri(uri);
|
||||||
|
@ -323,10 +335,12 @@ class FilePage extends React.PureComponent {
|
||||||
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
||||||
const isViewable = mediaType === 'image' || mediaType === 'text';
|
const isViewable = mediaType === 'image' || mediaType === 'text';
|
||||||
if (claim && costInfo && costInfo.cost === 0 && !this.state.autoGetAttempted && isViewable) {
|
if (claim && costInfo && costInfo.cost === 0 && !this.state.autoGetAttempted && isViewable) {
|
||||||
this.setState({ autoGetAttempted: true }, () => this.checkStoragePermissionForDownload());
|
this.setState({ autoGetAttempted: true }, () => {
|
||||||
|
this.checkStoragePermissionForDownload();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((costInfo && costInfo.cost > 0) || !isPlayable) && (!fileInfo && !isViewable) && !this.state.showRecommended) {
|
if (((costInfo && costInfo.cost > 0) || !isPlayable) && !fileInfo && !isViewable && !this.state.showRecommended) {
|
||||||
this.setState({ showRecommended: true });
|
this.setState({ showRecommended: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,7 +720,7 @@ class FilePage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
confirmPurchaseUri = (uri, costInfo, download) => {
|
confirmPurchaseUri = (uri, costInfo, download) => {
|
||||||
const { notify, purchaseUri, title } = this.props;
|
const { notify, purchaseUri, sdkReady, title } = this.props;
|
||||||
if (!costInfo) {
|
if (!costInfo) {
|
||||||
notify({ message: __('This content cannot be viewed at this time. Please try again in a bit.'), isError: true });
|
notify({ message: __('This content cannot be viewed at this time. Please try again in a bit.'), isError: true });
|
||||||
this.setState({ downloadPressed: false });
|
this.setState({ downloadPressed: false });
|
||||||
|
@ -715,6 +729,11 @@ class FilePage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { cost } = costInfo;
|
const { cost } = costInfo;
|
||||||
|
if (!NativeModules.UtilityModule.dhtEnabled && !sdkReady && parseFloat(cost) === 0) {
|
||||||
|
this.attemptLbryTvPlayback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (costInfo.cost > 0) {
|
if (costInfo.cost > 0) {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
__('Confirm Purchase'),
|
__('Confirm Purchase'),
|
||||||
|
@ -742,22 +761,40 @@ class FilePage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getStreamUrlForClaim = claim => {
|
||||||
|
const { name, claim_id: claimId } = claim;
|
||||||
|
return `https://player.lbry.tv/content/claims/${name}/${claimId}/stream`;
|
||||||
|
};
|
||||||
|
|
||||||
|
attemptLbryTvPlayback = () => {
|
||||||
|
const { claim } = this.props;
|
||||||
|
if (claim) {
|
||||||
|
this.setState({ streamingMode: true, currentStreamUrl: this.getStreamUrlForClaim(claim) });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onFileDownloadButtonPressed = () => {
|
onFileDownloadButtonPressed = () => {
|
||||||
this.startTime = Date.now();
|
this.startTime = Date.now();
|
||||||
const { claim, costInfo, contentType, setPlayerVisible } = this.props;
|
const { claim, costInfo, contentType, notify, sdkReady, setPlayerVisible } = this.props;
|
||||||
const mediaType = Lbry.getMediaType(contentType);
|
const mediaType = Lbry.getMediaType(contentType);
|
||||||
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
||||||
const isViewable = mediaType === 'image' || mediaType === 'text';
|
const isViewable = mediaType === 'image' || mediaType === 'text';
|
||||||
|
|
||||||
const purchaseUrl = this.getPurchaseUrl();
|
const purchaseUrl = this.getPurchaseUrl();
|
||||||
NativeModules.Firebase.track('purchase_uri', { uri: purchaseUrl });
|
|
||||||
|
|
||||||
if (!isPlayable) {
|
if (!isPlayable) {
|
||||||
|
if (!sdkReady) {
|
||||||
|
notify({
|
||||||
|
message: __('The LBRY background service is still initializing. Please wait a few moments and try again.'),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.onDownloadPressed();
|
this.onDownloadPressed();
|
||||||
} else {
|
} else {
|
||||||
this.confirmPurchaseUri(purchaseUrl, costInfo, !isPlayable);
|
this.confirmPurchaseUri(purchaseUrl, costInfo, !isPlayable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NativeModules.Firebase.track('purchase_uri', { uri: purchaseUrl });
|
||||||
|
|
||||||
if (isPlayable) {
|
if (isPlayable) {
|
||||||
this.setState({ downloadPressed: true, autoPlayMedia: true, stopDownloadConfirmed: false });
|
this.setState({ downloadPressed: true, autoPlayMedia: true, stopDownloadConfirmed: false });
|
||||||
}
|
}
|
||||||
|
@ -783,7 +820,16 @@ class FilePage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
onDownloadPressed = () => {
|
onDownloadPressed = () => {
|
||||||
const { claim, title } = this.props;
|
const { claim, notify, sdkReady, title } = this.props;
|
||||||
|
if (!sdkReady) {
|
||||||
|
notify({
|
||||||
|
message: __(
|
||||||
|
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
||||||
|
),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const fileSize = claim && claim.value && claim.value.source ? claim.value.source.size : 0;
|
const fileSize = claim && claim.value && claim.value.source ? claim.value.source.size : 0;
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
__('Download file'),
|
__('Download file'),
|
||||||
|
@ -983,7 +1029,6 @@ class FilePage extends React.PureComponent {
|
||||||
myClaimUris,
|
myClaimUris,
|
||||||
navigation,
|
navigation,
|
||||||
position,
|
position,
|
||||||
purchaseUri,
|
|
||||||
pushDrawerStack,
|
pushDrawerStack,
|
||||||
setPlayerVisible,
|
setPlayerVisible,
|
||||||
thumbnail,
|
thumbnail,
|
||||||
|
@ -1093,7 +1138,8 @@ class FilePage extends React.PureComponent {
|
||||||
const channelName = signingChannel && signingChannel.name;
|
const channelName = signingChannel && signingChannel.name;
|
||||||
const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
|
const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
|
||||||
const fullUri = `${claim.name}#${claim.claim_id}`;
|
const fullUri = `${claim.name}#${claim.claim_id}`;
|
||||||
const canEdit = myClaimUris.includes(normalizeURI(fullUri));
|
const canEdit =
|
||||||
|
myClaimUris.includes(normalizeURI(fullUri)) || myClaimUris.includes(normalizeURI(claim.canonical_url));
|
||||||
const showActions =
|
const showActions =
|
||||||
(canEdit || (fileInfo && fileInfo.download_path)) &&
|
(canEdit || (fileInfo && fileInfo.download_path)) &&
|
||||||
!this.state.fullscreenMode &&
|
!this.state.fullscreenMode &&
|
||||||
|
@ -1177,7 +1223,7 @@ class FilePage extends React.PureComponent {
|
||||||
style={filePageStyle.mediaContainer}
|
style={filePageStyle.mediaContainer}
|
||||||
onPress={this.onFileDownloadButtonPressed}
|
onPress={this.onFileDownloadButtonPressed}
|
||||||
>
|
>
|
||||||
{(canOpen || (!fileInfo || (isPlayable && !canLoadMedia)) || (!canOpen && fileInfo)) && (
|
{(canOpen || !fileInfo || (isPlayable && !canLoadMedia) || (!canOpen && fileInfo)) && (
|
||||||
<FileItemMedia
|
<FileItemMedia
|
||||||
duration={duration}
|
duration={duration}
|
||||||
style={filePageStyle.thumbnail}
|
style={filePageStyle.thumbnail}
|
||||||
|
@ -1314,6 +1360,14 @@ class FilePage extends React.PureComponent {
|
||||||
<Text style={filePageStyle.largeButtonText}>{__('Share')}</Text>
|
<Text style={filePageStyle.largeButtonText}>{__('Share')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={filePageStyle.largeButton}
|
||||||
|
onPress={() => this.setState({ showRepostView: true })}
|
||||||
|
>
|
||||||
|
<Icon name={'retweet'} size={16} style={filePageStyle.largeButtonIcon} />
|
||||||
|
<Text style={filePageStyle.largeButtonText}>{__('Repost')}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={filePageStyle.largeButton}
|
style={filePageStyle.largeButton}
|
||||||
onPress={() => this.setState({ showTipView: true })}
|
onPress={() => this.setState({ showTipView: true })}
|
||||||
|
@ -1488,7 +1542,17 @@ class FilePage extends React.PureComponent {
|
||||||
onSendTipSuccessful={() => this.setState({ showTipView: false })}
|
onSendTipSuccessful={() => this.setState({ showTipView: false })}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{this.state.showRepostView && (
|
||||||
|
<ModalRepostView
|
||||||
|
claim={claim}
|
||||||
|
title={title}
|
||||||
|
onCancelPress={() => this.setState({ showRepostView: false })}
|
||||||
|
onOverlayPress={() => this.setState({ showRepostView: false })}
|
||||||
|
onRepostSuccessful={() => this.setState({ showRepostView: false })}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{!this.state.fullscreenMode &&
|
{!this.state.fullscreenMode &&
|
||||||
|
!this.state.showRepostView &&
|
||||||
!this.state.showTipView &&
|
!this.state.showTipView &&
|
||||||
!this.state.showImageViewer &&
|
!this.state.showImageViewer &&
|
||||||
!this.state.showWebView && <FloatingWalletBalance navigation={navigation} />}
|
!this.state.showWebView && <FloatingWalletBalance navigation={navigation} />}
|
||||||
|
|
|
@ -12,23 +12,22 @@ import {
|
||||||
doFetchInviteStatus,
|
doFetchInviteStatus,
|
||||||
doUserInviteNew,
|
doUserInviteNew,
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doUpdateChannelFormState, doClearChannelFormState } from 'redux/actions/form';
|
import { selectSdkReady } from 'redux/selectors/settings';
|
||||||
import { selectDrawerStack } from 'redux/selectors/drawer';
|
|
||||||
import { selectChannelFormState, selectHasChannelFormState } from 'redux/selectors/form';
|
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import InvitesPage from './view';
|
import InvitesPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
channels: selectMyChannelClaims(state),
|
channels: selectMyChannelClaims(state),
|
||||||
|
errorMessage: selectUserInviteNewErrorMessage(state),
|
||||||
fetchingChannels: selectFetchingMyChannels(state),
|
fetchingChannels: selectFetchingMyChannels(state),
|
||||||
fetchingInvitees: selectUserInviteStatusIsPending(state),
|
fetchingInvitees: selectUserInviteStatusIsPending(state),
|
||||||
errorMessage: selectUserInviteNewErrorMessage(state),
|
|
||||||
invitesRemaining: selectUserInvitesRemaining(state),
|
|
||||||
referralCode: selectUserInviteReferralCode(state),
|
|
||||||
isPending: selectUserInviteNewIsPending(state),
|
|
||||||
invitees: selectUserInvitees(state),
|
invitees: selectUserInvitees(state),
|
||||||
|
invitesRemaining: selectUserInvitesRemaining(state),
|
||||||
|
isPending: selectUserInviteNewIsPending(state),
|
||||||
|
referralCode: selectUserInviteReferralCode(state),
|
||||||
referralReward: selectReferralReward(state),
|
referralReward: selectReferralReward(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -40,7 +39,4 @@ const perform = dispatch => ({
|
||||||
notify: data => dispatch(doToast(data)),
|
notify: data => dispatch(doToast(data)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(InvitesPage);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(InvitesPage);
|
|
||||||
|
|
|
@ -11,14 +11,10 @@ import {
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from 'component/link';
|
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import ChannelSelector from 'component/channelSelector';
|
import ChannelSelector from 'component/channelSelector';
|
||||||
import PageHeader from 'component/pageHeader';
|
import EmptyStateView from 'component/emptyStateView';
|
||||||
import RewardCard from 'component/rewardCard';
|
|
||||||
import RewardEnrolment from 'component/rewardEnrolment';
|
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import invitesStyle from 'styles/invites';
|
import invitesStyle from 'styles/invites';
|
||||||
import { fetchReferralCode, logPublish } from 'utils/helper';
|
import { fetchReferralCode, logPublish } from 'utils/helper';
|
||||||
|
@ -134,10 +130,23 @@ class InvitesPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { fetchingInvitees, user, navigation, notify, isPending, invitees } = this.props;
|
const { fetchingInvitees, invitees, isPending, navigation, sdkReady } = this.props;
|
||||||
const { email, inviteLink } = this.state;
|
const { email } = this.state;
|
||||||
const hasInvitees = invitees && invitees.length > 0;
|
const hasInvitees = invitees && invitees.length > 0;
|
||||||
|
|
||||||
|
if (!sdkReady) {
|
||||||
|
return (
|
||||||
|
<View style={invitesStyle.container}>
|
||||||
|
<UriBar navigation={navigation} />
|
||||||
|
<EmptyStateView
|
||||||
|
message={__(
|
||||||
|
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={invitesStyle.container}>
|
<View style={invitesStyle.container}>
|
||||||
<UriBar navigation={navigation} />
|
<UriBar navigation={navigation} />
|
||||||
|
|
|
@ -38,15 +38,19 @@ class LiteFilePage extends React.PureComponent {
|
||||||
|
|
||||||
player = null;
|
player = null;
|
||||||
|
|
||||||
|
startTime = null;
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
channelName: null,
|
channelName: null,
|
||||||
channelUrl: null,
|
channelUrl: null,
|
||||||
title: null,
|
fileViewLogged: false,
|
||||||
fullscreenMode: false,
|
fullscreenMode: false,
|
||||||
|
playbackStarted: false,
|
||||||
playerHeight: null,
|
playerHeight: null,
|
||||||
isLandscape: false,
|
isLandscape: false,
|
||||||
sdkReady: false, // TODO: progressively enable features (e.g. tip) when sdk is ready
|
sdkReady: false, // TODO: progressively enable features (e.g. tip) when sdk is ready
|
||||||
showRecommended: false,
|
showRecommended: false,
|
||||||
|
title: null,
|
||||||
viewCount: 0,
|
viewCount: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,6 +131,10 @@ class LiteFilePage extends React.PureComponent {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.startTime = Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
const { navigation } = this.props;
|
const { navigation } = this.props;
|
||||||
const { uri } = navigation.state.params;
|
const { uri } = navigation.state.params;
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||||
import { doUpdatePublishFormState, doClearPublishFormState, doPendingPublishSuccess } from 'redux/actions/form';
|
import { doUpdatePublishFormState, doClearPublishFormState, doPendingPublishSuccess } from 'redux/actions/form';
|
||||||
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { selectPublishFormState, selectHasPublishFormState } from 'redux/selectors/form';
|
import { selectPublishFormState, selectHasPublishFormState } from 'redux/selectors/form';
|
||||||
|
import { selectSdkReady } from 'redux/selectors/settings';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import PublishPage from './view';
|
import PublishPage from './view';
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ const select = state => ({
|
||||||
myClaims: selectMyClaims(state),
|
myClaims: selectMyClaims(state),
|
||||||
publishFormState: selectPublishFormState(state),
|
publishFormState: selectPublishFormState(state),
|
||||||
publishFormValues: selectPublishFormValues(state),
|
publishFormValues: selectPublishFormValues(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -39,7 +41,4 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(PublishPage);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(PublishPage);
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ import Button from 'component/button';
|
||||||
import ChannelSelector from 'component/channelSelector';
|
import ChannelSelector from 'component/channelSelector';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
|
import EmptyStateView from 'component/emptyStateView';
|
||||||
import FastImage from 'react-native-fast-image';
|
import FastImage from 'react-native-fast-image';
|
||||||
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
|
@ -120,7 +121,7 @@ class PublishPage extends React.PureComponent {
|
||||||
|
|
||||||
// input data
|
// input data
|
||||||
hasEditedContentAddress: false,
|
hasEditedContentAddress: false,
|
||||||
bid: 0.1,
|
bid: 0.01,
|
||||||
description: null,
|
description: null,
|
||||||
title: null,
|
title: null,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
|
@ -974,7 +975,7 @@ class PublishPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { balance, navigation, notify, publishFormValues } = this.props;
|
const { balance, navigation, notify, sdkReady } = this.props;
|
||||||
const {
|
const {
|
||||||
allThumbnailsChecked,
|
allThumbnailsChecked,
|
||||||
canUseCamera,
|
canUseCamera,
|
||||||
|
@ -987,6 +988,19 @@ class PublishPage extends React.PureComponent {
|
||||||
videos,
|
videos,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
|
if (!sdkReady) {
|
||||||
|
return (
|
||||||
|
<View style={publishStyle.container}>
|
||||||
|
<UriBar navigation={navigation} />
|
||||||
|
<EmptyStateView
|
||||||
|
message={__(
|
||||||
|
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let content;
|
let content;
|
||||||
if (Constants.PHASE_SELECTOR === currentPhase) {
|
if (Constants.PHASE_SELECTOR === currentPhase) {
|
||||||
content = (
|
content = (
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
selectIsFetchingClaimListMine,
|
selectIsFetchingClaimListMine,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
|
import { selectSdkReady } from 'redux/selectors/settings';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import PublishesPage from './view';
|
import PublishesPage from './view';
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ const select = state => ({
|
||||||
uris: selectMyClaimUrisWithoutChannels(state),
|
uris: selectMyClaimUrisWithoutChannels(state),
|
||||||
fetching: selectIsFetchingClaimListMine(state),
|
fetching: selectIsFetchingClaimListMine(state),
|
||||||
pendingClaims: selectPendingClaims(state),
|
pendingClaims: selectPendingClaims(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -27,7 +29,4 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(PublishesPage);
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(PublishesPage);
|
|
||||||
|
|
|
@ -114,14 +114,27 @@ class PublishesPage extends React.PureComponent {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
{ cancelable: true }
|
{ cancelable: true },
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { fetching, navigation, uris } = this.props;
|
const { fetching, navigation, sdkReady, uris } = this.props;
|
||||||
const { selectionMode, selectedUris } = this.state;
|
const { selectionMode, selectedUris } = this.state;
|
||||||
|
|
||||||
|
if (!sdkReady) {
|
||||||
|
return (
|
||||||
|
<View style={publishStyle.container}>
|
||||||
|
<UriBar navigation={navigation} />
|
||||||
|
<EmptyStateView
|
||||||
|
message={__(
|
||||||
|
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={publishStyle.container}>
|
<View style={publishStyle.container}>
|
||||||
<UriBar
|
<UriBar
|
||||||
|
@ -181,7 +194,7 @@ class PublishesPage extends React.PureComponent {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// TODO: when shortUrl is available for my claims, navigate to that URL instead
|
// TODO: when shortUrl is available for my claims, navigate to that URL instead
|
||||||
navigateToUri(navigation, item);
|
navigateToUri(navigation, claim.permanent_url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -12,7 +12,8 @@ import {
|
||||||
import { doToast } from 'lbry-redux';
|
import { doToast } from 'lbry-redux';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||||
import Constants from 'constants';
|
import { selectSdkReady } from 'redux/selectors/settings';
|
||||||
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import RewardsPage from './view';
|
import RewardsPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
@ -22,6 +23,7 @@ const select = state => ({
|
||||||
emailVerifyPending: selectEmailVerifyIsPending(state),
|
emailVerifyPending: selectEmailVerifyIsPending(state),
|
||||||
fetching: selectFetchingRewards(state),
|
fetching: selectFetchingRewards(state),
|
||||||
rewards: selectUnclaimedRewards(state),
|
rewards: selectUnclaimedRewards(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -33,7 +35,4 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(RewardsPage);
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(RewardsPage);
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Lbry } from 'lbry-redux';
|
import { Lbryio } from 'lbryinc';
|
||||||
import { ActivityIndicator, NativeModules, ScrollView, Text, View } from 'react-native';
|
import { ActivityIndicator, NativeModules, ScrollView, Text, View } from 'react-native';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import CustomRewardCard from 'component/customRewardCard';
|
import CustomRewardCard from 'component/customRewardCard';
|
||||||
import PageHeader from 'component/pageHeader';
|
import EmptyStateView from 'component/emptyStateView';
|
||||||
import RewardCard from 'component/rewardCard';
|
import RewardCard from 'component/rewardCard';
|
||||||
import RewardEnrolment from 'component/rewardEnrolment';
|
import RewardEnrolment from 'component/rewardEnrolment';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
|
@ -17,13 +17,14 @@ const FILTER_CLAIMED = 'claimed';
|
||||||
|
|
||||||
class RewardsPage extends React.PureComponent {
|
class RewardsPage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
|
currentFilter: FILTER_AVAILABLE,
|
||||||
|
firstRewardClaimed: false,
|
||||||
isEmailVerified: false,
|
isEmailVerified: false,
|
||||||
isIdentityVerified: false,
|
isIdentityVerified: false,
|
||||||
isRewardApproved: false,
|
isRewardApproved: false,
|
||||||
verifyRequestStarted: false,
|
|
||||||
revealVerification: true,
|
revealVerification: true,
|
||||||
firstRewardClaimed: false,
|
usdExchangeRate: 0,
|
||||||
currentFilter: FILTER_AVAILABLE,
|
verifyRequestStarted: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
scrollView = null;
|
scrollView = null;
|
||||||
|
@ -48,6 +49,12 @@ class RewardsPage extends React.PureComponent {
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
NativeModules.Firebase.setCurrentScreen('Rewards');
|
NativeModules.Firebase.setCurrentScreen('Rewards');
|
||||||
|
|
||||||
|
Lbryio.getExchangeRates().then(rates => {
|
||||||
|
if (!isNaN(rates.LBC_USD)) {
|
||||||
|
this.setState({ usdExchangeRate: rates.LBC_USD });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
fetchRewards();
|
fetchRewards();
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -158,6 +165,7 @@ class RewardsPage extends React.PureComponent {
|
||||||
canClaim={!isNotEligible}
|
canClaim={!isNotEligible}
|
||||||
reward={reward}
|
reward={reward}
|
||||||
reward_type={reward.reward_type}
|
reward_type={reward.reward_type}
|
||||||
|
usdExchangeRate={this.state.usdExchangeRate}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<CustomRewardCard canClaim={!isNotEligible} showVerification={this.showVerification} />
|
<CustomRewardCard canClaim={!isNotEligible} showVerification={this.showVerification} />
|
||||||
|
@ -192,13 +200,28 @@ class RewardsPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { user, navigation } = this.props;
|
const { navigation, sdkReady } = this.props;
|
||||||
const { currentFilter } = this.state;
|
const { currentFilter } = this.state;
|
||||||
|
|
||||||
|
if (!sdkReady) {
|
||||||
|
return (
|
||||||
|
<View style={rewardStyle.container}>
|
||||||
|
<UriBar navigation={navigation} />
|
||||||
|
<EmptyStateView
|
||||||
|
message={__(
|
||||||
|
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={rewardStyle.container}>
|
<View style={rewardStyle.container}>
|
||||||
<UriBar navigation={navigation} />
|
<UriBar navigation={navigation} />
|
||||||
{(!this.state.isEmailVerified || !this.state.isRewardApproved) && <RewardEnrolment navigation={navigation} />}
|
{(!this.state.isEmailVerified || !this.state.isRewardApproved) && (
|
||||||
|
<RewardEnrolment usdExchangeRate={this.state.usdExchangeRate} navigation={navigation} />
|
||||||
|
)}
|
||||||
|
|
||||||
{this.state.isEmailVerified && this.state.isRewardApproved && (
|
{this.state.isEmailVerified && this.state.isRewardApproved && (
|
||||||
<ScrollView
|
<ScrollView
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SETTINGS } from 'lbry-redux';
|
import { SETTINGS } from 'lbry-redux';
|
||||||
import { ActivityIndicator, Picker, Platform, Text, View, ScrollView, Switch, NativeModules } from 'react-native';
|
import {
|
||||||
|
ActivityIndicator,
|
||||||
|
Picker,
|
||||||
|
Platform,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
View,
|
||||||
|
ScrollView,
|
||||||
|
Switch,
|
||||||
|
NativeModules,
|
||||||
|
} from 'react-native';
|
||||||
import { navigateBack } from 'utils/helper';
|
import { navigateBack } from 'utils/helper';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
|
@ -328,7 +338,9 @@ class SettingsPage extends React.PureComponent {
|
||||||
<View style={settingsStyle.switchText}>
|
<View style={settingsStyle.switchText}>
|
||||||
<Text style={settingsStyle.label}>{__('Participate in the data network')}</Text>
|
<Text style={settingsStyle.label}>{__('Participate in the data network')}</Text>
|
||||||
<Text style={settingsStyle.description}>
|
<Text style={settingsStyle.description}>
|
||||||
{__('Enable DHT (this will take effect upon app and background service restart)')}
|
{__(
|
||||||
|
'Enable peer-to-peer functionality (this will take effect upon app and background service restart)',
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={settingsStyle.switchContainer}>
|
<View style={settingsStyle.switchContainer}>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { SETTINGS, doBalanceSubscribe, doUpdateBlockHeight, doPopulateSharedUserState, doToast } from 'lbry-redux';
|
import { SETTINGS, doUpdateBlockHeight, doPopulateSharedUserState, doToast } from 'lbry-redux';
|
||||||
import {
|
import {
|
||||||
doAuthenticate,
|
doAuthenticate,
|
||||||
doInstallNew,
|
doClaimRewardType,
|
||||||
doInstallNewWithParams,
|
doInstallNewWithParams,
|
||||||
doBlackListedOutpointsSubscribe,
|
|
||||||
doFilteredOutpointsSubscribe,
|
|
||||||
doFetchMySubscriptions,
|
doFetchMySubscriptions,
|
||||||
doFetchRewardedContent,
|
doFetchRewardedContent,
|
||||||
doGetSync,
|
doGetSync,
|
||||||
|
@ -32,9 +30,6 @@ const perform = dispatch => ({
|
||||||
dispatch(doAuthenticate(appVersion, os, firebaseToken, true, null, callInstall)),
|
dispatch(doAuthenticate(appVersion, os, firebaseToken, true, null, callInstall)),
|
||||||
installNewWithParams: (appVersion, installationId, nodeId, lbrynetVersion, os, platform, firebaseToken) =>
|
installNewWithParams: (appVersion, installationId, nodeId, lbrynetVersion, os, platform, firebaseToken) =>
|
||||||
dispatch(doInstallNewWithParams(appVersion, installationId, nodeId, lbrynetVersion, os, platform, firebaseToken)),
|
dispatch(doInstallNewWithParams(appVersion, installationId, nodeId, lbrynetVersion, os, platform, firebaseToken)),
|
||||||
balanceSubscribe: () => dispatch(doBalanceSubscribe()),
|
|
||||||
blacklistedOutpointsSubscribe: () => dispatch(doBlackListedOutpointsSubscribe()),
|
|
||||||
filteredOutpointsSubscribe: () => dispatch(doFilteredOutpointsSubscribe()),
|
|
||||||
fetchRewardedContent: () => dispatch(doFetchRewardedContent()),
|
fetchRewardedContent: () => dispatch(doFetchRewardedContent()),
|
||||||
fetchSubscriptions: callback => dispatch(doFetchMySubscriptions(callback)),
|
fetchSubscriptions: callback => dispatch(doFetchMySubscriptions(callback)),
|
||||||
getSync: (password, callback) => dispatch(doGetSync(password, callback)),
|
getSync: (password, callback) => dispatch(doGetSync(password, callback)),
|
||||||
|
|
|
@ -23,6 +23,7 @@ class SplashScreen extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
authWithoutSdk: false,
|
||||||
accountUnlockFailed: false,
|
accountUnlockFailed: false,
|
||||||
appVersion: null,
|
appVersion: null,
|
||||||
daemonReady: false,
|
daemonReady: false,
|
||||||
|
@ -53,7 +54,7 @@ class SplashScreen extends React.PureComponent {
|
||||||
liteModeParams: {
|
liteModeParams: {
|
||||||
installationId: installIdContent,
|
installationId: installIdContent,
|
||||||
nodeId: null,
|
nodeId: null,
|
||||||
lbrynetVersion: '0.62.0',
|
lbrynetVersion: '0.64.0',
|
||||||
platform,
|
platform,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -66,26 +67,26 @@ class SplashScreen extends React.PureComponent {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
updateStatus() {
|
authenticateWithoutSdk() {
|
||||||
const { authenticate } = this.props;
|
const { authenticate } = this.props;
|
||||||
|
NativeModules.VersionInfo.getAppVersion().then(appVersion => {
|
||||||
|
this.setState({ appVersion, shouldAuthenticate: true, authWithoutSdk: true });
|
||||||
|
NativeModules.Firebase.getMessagingToken()
|
||||||
|
.then(firebaseToken => {
|
||||||
|
this.setState({ firebaseToken }, () => authenticate(appVersion, Platform.OS, firebaseToken, false));
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
authenticate(appVersion, Platform.OS, null, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStatus() {
|
||||||
const { liteMode } = this.state;
|
const { liteMode } = this.state;
|
||||||
|
|
||||||
if (liteMode) {
|
// authenticate immediately
|
||||||
// authenticate immediately
|
if (!NativeModules.UtilityModule.dhtEnabled) {
|
||||||
NativeModules.VersionInfo.getAppVersion().then(appVersion => {
|
this.authenticateWithoutSdk();
|
||||||
this.setState({ appVersion, shouldAuthenticate: true });
|
|
||||||
NativeModules.Firebase.getMessagingToken()
|
|
||||||
.then(firebaseToken => {
|
|
||||||
this.setState({ firebaseToken }, () => authenticate(appVersion, Platform.OS, firebaseToken, false));
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
authenticate(appVersion, Platform.OS, null, false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Lbry.status().then(status => {
|
|
||||||
this._updateStatusCallback(status);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,40 +122,51 @@ class SplashScreen extends React.PureComponent {
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { getSync, installNewWithParams } = this.props;
|
const { getSync, installNewWithParams } = this.props;
|
||||||
const { daemonReady, shouldAuthenticate, liteMode, liteModeParams, appVersion, firebaseToken } = this.state;
|
const {
|
||||||
|
daemonReady,
|
||||||
|
authWithoutSdk,
|
||||||
|
shouldAuthenticate,
|
||||||
|
liteMode,
|
||||||
|
liteModeParams,
|
||||||
|
appVersion,
|
||||||
|
firebaseToken,
|
||||||
|
} = this.state;
|
||||||
const { user } = nextProps;
|
const { user } = nextProps;
|
||||||
|
|
||||||
if (liteMode && user && user.id) {
|
if (liteMode && user && user.id) {
|
||||||
this.navigateToLiteMode();
|
this.navigateToLiteMode();
|
||||||
} else if (daemonReady && shouldAuthenticate && user && user.id) {
|
} else if (shouldAuthenticate && user && user.id) {
|
||||||
this.setState({ shouldAuthenticate: false }, () => {
|
if (daemonReady || authWithoutSdk) {
|
||||||
// call install new after successful authentication
|
this.setState({ shouldAuthenticate: false }, () => {
|
||||||
if (liteMode) {
|
// call install new after successful authentication
|
||||||
const { installationId, nodeId, lbrynetVersion, platform } = liteModeParams;
|
if (authWithoutSdk) {
|
||||||
installNewWithParams(
|
const { installationId, nodeId, lbrynetVersion, platform } = liteModeParams;
|
||||||
appVersion,
|
installNewWithParams(
|
||||||
installationId,
|
appVersion,
|
||||||
nodeId,
|
installationId,
|
||||||
lbrynetVersion,
|
nodeId,
|
||||||
Platform.OS,
|
lbrynetVersion,
|
||||||
platform,
|
Platform.OS,
|
||||||
firebaseToken,
|
platform,
|
||||||
);
|
firebaseToken,
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// user is authenticated, navigate to the main view
|
// user is authenticated, navigate to the main view
|
||||||
if (user.has_verified_email) {
|
if (user.has_verified_email) {
|
||||||
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(walletPassword => {
|
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(walletPassword => {
|
||||||
getSync(walletPassword, () => {
|
getSync(walletPassword, () => {
|
||||||
this.getUserSettings();
|
this.getUserSettings();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
this.navigateToMain();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.navigateToMain();
|
this.navigateToMain();
|
||||||
});
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.navigateToMain();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,22 +206,9 @@ class SplashScreen extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
finishSplashScreen = () => {
|
finishSplashScreen = () => {
|
||||||
const {
|
const { authenticate, getSync, user } = this.props;
|
||||||
authenticate,
|
|
||||||
balanceSubscribe,
|
|
||||||
blacklistedOutpointsSubscribe,
|
|
||||||
filteredOutpointsSubscribe,
|
|
||||||
getSync,
|
|
||||||
updateBlockHeight,
|
|
||||||
user,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
// Lbry.resolve({ urls: 'lbry://one' }).then(() => {
|
|
||||||
// Leave the splash screen
|
// Leave the splash screen
|
||||||
balanceSubscribe();
|
|
||||||
blacklistedOutpointsSubscribe();
|
|
||||||
filteredOutpointsSubscribe();
|
|
||||||
|
|
||||||
if (user && user.id && user.has_verified_email) {
|
if (user && user.id && user.has_verified_email) {
|
||||||
// user already authenticated
|
// user already authenticated
|
||||||
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(walletPassword => {
|
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(walletPassword => {
|
||||||
|
@ -229,31 +228,14 @@ class SplashScreen extends React.PureComponent {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleAccountUnlockFailed() {
|
handleAccountUnlockFailed() {
|
||||||
this.setState({ accountUnlockFailed: true });
|
this.setState({ accountUnlockFailed: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateStatusCallback(status) {
|
handleSdkReady = () => {
|
||||||
const { fetchSubscriptions, getSync, setClientSetting } = this.props;
|
this.setState({ daemonReady: true }, () => {
|
||||||
const startupStatus = status.startup_status;
|
|
||||||
const walletStatus = status.wallet;
|
|
||||||
|
|
||||||
// At the minimum, wallet should be started and blocks_behind equal to 0 before calling resolve
|
|
||||||
const hasStarted = startupStatus.stream_manager && startupStatus.wallet && status.wallet.blocks_behind <= 0;
|
|
||||||
if (hasStarted) {
|
|
||||||
// Wait until we are able to resolve a name before declaring
|
|
||||||
// that we are done.
|
|
||||||
// TODO: This is a hack, and the logic should live in the daemon
|
|
||||||
// to give us a better sense of when we are actually started
|
|
||||||
this.setState({
|
|
||||||
daemonReady: true,
|
|
||||||
isLagging: false,
|
|
||||||
isRunning: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.wallet_status().then(secureWalletStatus => {
|
Lbry.wallet_status().then(secureWalletStatus => {
|
||||||
// For now, automatically unlock the wallet if a password is set so that downloads work
|
// For now, automatically unlock the wallet if a password is set so that downloads work
|
||||||
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(password => {
|
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(password => {
|
||||||
|
@ -284,9 +266,12 @@ class SplashScreen extends React.PureComponent {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return;
|
handleSdkStatusResponse = evt => {
|
||||||
}
|
const { status } = evt;
|
||||||
|
const walletStatus = status.wallet;
|
||||||
|
|
||||||
const headerSyncProgress = walletStatus ? walletStatus.headers_synchronization_progress : null;
|
const headerSyncProgress = walletStatus ? walletStatus.headers_synchronization_progress : null;
|
||||||
if (headerSyncProgress && headerSyncProgress < 100) {
|
if (headerSyncProgress && headerSyncProgress < 100) {
|
||||||
|
@ -321,23 +306,25 @@ class SplashScreen extends React.PureComponent {
|
||||||
details: __('Initializing LBRY service'),
|
details: __('Initializing LBRY service'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
setTimeout(() => {
|
|
||||||
this.updateStatus();
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
DeviceEventEmitter.addListener('onNotificationTargetLaunch', this.onNotificationTargetLaunch);
|
DeviceEventEmitter.addListener('onNotificationTargetLaunch', this.onNotificationTargetLaunch);
|
||||||
|
DeviceEventEmitter.addListener('onSdkReady', this.handleSdkReady);
|
||||||
|
DeviceEventEmitter.addListener('onSdkStatusResponse', this.handleSdkStatusResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
DeviceEventEmitter.removeListener('onNotificationTargetLaunch', this.onNotificationTargetLaunch);
|
DeviceEventEmitter.removeListener('onNotificationTargetLaunch', this.onNotificationTargetLaunch);
|
||||||
|
DeviceEventEmitter.removeListener('onSdkReady', this.handleSdkReady);
|
||||||
|
DeviceEventEmitter.removeListener('onSdkStatusResponse', this.handleSdkStatusResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
NativeModules.Firebase.track('app_launch', null);
|
NativeModules.Firebase.track('app_launch', null);
|
||||||
NativeModules.Firebase.setCurrentScreen('Splash');
|
NativeModules.Firebase.setCurrentScreen('Splash');
|
||||||
|
NativeModules.UtilityModule.checkSdkReady();
|
||||||
|
|
||||||
const { navigation } = this.props;
|
const { navigation } = this.props;
|
||||||
const { resetUrl } = navigation.state.params;
|
const { resetUrl } = navigation.state.params;
|
||||||
const isResetUrlSet = !!resetUrl;
|
const isResetUrlSet = !!resetUrl;
|
||||||
|
@ -357,11 +344,7 @@ class SplashScreen extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only connect after checking initial launch url / notification launch target
|
// Only connect after checking initial launch url / notification launch target
|
||||||
if (liteMode) {
|
this.initLiteMode();
|
||||||
this.initLiteMode();
|
|
||||||
} else {
|
|
||||||
this.lbryConnect();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -377,19 +360,23 @@ class SplashScreen extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
lbryConnect = () => {
|
lbryConnect = () => {
|
||||||
Lbry.connect()
|
if (NativeModules.UtilityModule.dhtEnabled) {
|
||||||
.then(() => {
|
Lbry.connect()
|
||||||
this.updateStatus();
|
.then(() => {
|
||||||
})
|
this.updateStatus();
|
||||||
.catch(e => {
|
})
|
||||||
this.setState({
|
.catch(e => {
|
||||||
isLagging: true,
|
this.setState({
|
||||||
message: __('Connection Failure'),
|
isLagging: true,
|
||||||
details: __(
|
message: __('Connection Failure'),
|
||||||
'We could not establish a connection to the SDK. Your data connection may be preventing LBRY from connecting. Contact hello@lbry.com if you think this is a software bug.',
|
details: __(
|
||||||
),
|
'We could not establish a connection to the SDK. Your data connection may be preventing LBRY from connecting. Contact hello@lbry.com if you think this is a software bug.',
|
||||||
|
),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
} else {
|
||||||
|
this.updateStatus(); // skip lbry.connect for now (unless dht flag is enabled)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleContinueAnywayPressed = () => {
|
handleContinueAnywayPressed = () => {
|
||||||
|
|
|
@ -12,11 +12,13 @@ import {
|
||||||
selectViewMode,
|
selectViewMode,
|
||||||
selectFirstRunCompleted,
|
selectFirstRunCompleted,
|
||||||
selectShowSuggestedSubs,
|
selectShowSuggestedSubs,
|
||||||
|
selectUnclaimedRewardValue,
|
||||||
|
selectUser,
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { doToast, selectFetchingClaimSearch } from 'lbry-redux';
|
import { doToast, selectFetchingClaimSearch } from 'lbry-redux';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doSetClientSetting, doSetTimeItem } from 'redux/actions/settings';
|
import { doSetClientSetting, doSetTimeItem } from 'redux/actions/settings';
|
||||||
import { makeSelectClientSetting, selectTimeItem } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectSdkReady, selectTimeItem } from 'redux/selectors/settings';
|
||||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import SubscriptionsPage from './view';
|
import SubscriptionsPage from './view';
|
||||||
|
@ -32,8 +34,12 @@ const select = state => ({
|
||||||
unreadSubscriptions: selectUnreadSubscriptions(state),
|
unreadSubscriptions: selectUnreadSubscriptions(state),
|
||||||
viewMode: selectViewMode(state),
|
viewMode: selectViewMode(state),
|
||||||
firstRunCompleted: selectFirstRunCompleted(state),
|
firstRunCompleted: selectFirstRunCompleted(state),
|
||||||
|
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
||||||
showSuggestedSubs: selectShowSuggestedSubs(state),
|
showSuggestedSubs: selectShowSuggestedSubs(state),
|
||||||
timeItem: selectTimeItem(state),
|
timeItem: selectTimeItem(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
|
unclaimedRewardAmount: selectUnclaimedRewardValue(state),
|
||||||
|
user: selectUser(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
@ -48,7 +54,4 @@ const perform = dispatch => ({
|
||||||
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(SubscriptionsPage);
|
||||||
select,
|
|
||||||
perform,
|
|
||||||
)(SubscriptionsPage);
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { buildURI, parseURI } from 'lbry-redux';
|
import { buildURI, parseURI } from 'lbry-redux';
|
||||||
import { getOrderBy } from 'utils/helper';
|
import { formatUsd, getOrderBy } from 'utils/helper';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -30,16 +30,22 @@ import SubscribedChannelList from 'component/subscribedChannelList';
|
||||||
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
|
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
|
||||||
import SuggestedSubscriptionsGrid from 'component/suggestedSubscriptionsGrid';
|
import SuggestedSubscriptionsGrid from 'component/suggestedSubscriptionsGrid';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
|
import SdkLoadingStatus from 'component/sdkLoadingStatus';
|
||||||
|
import Snackbar from 'react-native-snackbar';
|
||||||
|
import { Lbryio } from 'lbryinc';
|
||||||
|
|
||||||
class SubscriptionsPage extends React.PureComponent {
|
class SubscriptionsPage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
|
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1], // should always default to sorting subscriptions by new
|
||||||
|
filteredChannels: [],
|
||||||
|
orderBy: ['release_time'],
|
||||||
|
showRewardsNag: true,
|
||||||
showingSuggestedSubs: false,
|
showingSuggestedSubs: false,
|
||||||
showSortPicker: false,
|
showSortPicker: false,
|
||||||
showTimePicker: false,
|
showTimePicker: false,
|
||||||
showModalSuggestedSubs: false,
|
showModalSuggestedSubs: false,
|
||||||
orderBy: ['release_time'],
|
usdExchangeRate: 0,
|
||||||
filteredChannels: [],
|
userEmailVerified: false,
|
||||||
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1], // should always default to sorting subscriptions by new
|
|
||||||
};
|
};
|
||||||
|
|
||||||
didFocusListener;
|
didFocusListener;
|
||||||
|
@ -56,15 +62,7 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
onComponentFocused = () => {
|
onComponentFocused = () => {
|
||||||
const {
|
const { currentRoute, doFetchMySubscriptions, pushDrawerStack, sdkReady, setPlayerVisible, user } = this.props;
|
||||||
currentRoute,
|
|
||||||
doFetchMySubscriptions,
|
|
||||||
doFetchRecommendedSubscriptions,
|
|
||||||
doSetViewMode,
|
|
||||||
pushDrawerStack,
|
|
||||||
setPlayerVisible,
|
|
||||||
subscriptionsViewMode,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (currentRoute === Constants.DRAWER_ROUTE_SUBSCRIPTIONS) {
|
if (currentRoute === Constants.DRAWER_ROUTE_SUBSCRIPTIONS) {
|
||||||
pushDrawerStack();
|
pushDrawerStack();
|
||||||
|
@ -72,6 +70,17 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
NativeModules.Firebase.setCurrentScreen('Subscriptions');
|
NativeModules.Firebase.setCurrentScreen('Subscriptions');
|
||||||
|
|
||||||
|
Lbryio.getExchangeRates().then(rates => {
|
||||||
|
if (!isNaN(rates.LBC_USD)) {
|
||||||
|
this.setState({ usdExchangeRate: rates.LBC_USD }, () => {
|
||||||
|
if (sdkReady && parseFloat(this.state.usdExchangeRate) > 0 && user && !user.is_reward_approved) {
|
||||||
|
this.showRewardsAvailable();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({ userEmailVerified: user && user.has_verified_email });
|
||||||
doFetchMySubscriptions();
|
doFetchMySubscriptions();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,15 +89,56 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { currentRoute } = nextProps;
|
const { currentRoute, user, sdkReady } = nextProps;
|
||||||
const { currentRoute: prevRoute } = this.props;
|
const { currentRoute: prevRoute, doFetchMySubscriptions } = this.props;
|
||||||
if (Constants.DRAWER_ROUTE_SUBSCRIPTIONS === currentRoute && currentRoute !== prevRoute) {
|
if (Constants.DRAWER_ROUTE_SUBSCRIPTIONS === currentRoute && currentRoute !== prevRoute) {
|
||||||
this.onComponentFocused();
|
this.onComponentFocused();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (user && user.has_verified_email && !this.state.userEmailVerified) {
|
||||||
|
// user just signed in
|
||||||
|
this.setState({ showingSuggestedSubs: false, userEmailVerified: true }, () => {
|
||||||
|
doFetchMySubscriptions();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
sdkReady &&
|
||||||
|
parseFloat(this.state.usdExchangeRate) > 0 &&
|
||||||
|
this.state.showRewardsNag &&
|
||||||
|
user &&
|
||||||
|
!user.is_reward_approved
|
||||||
|
) {
|
||||||
|
this.showRewardsAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
this.unsubscribeShortChannelUrls();
|
this.unsubscribeShortChannelUrls();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showRewardsAvailable = () => {
|
||||||
|
const { navigation, unclaimedRewardAmount, rewardsNotInterested } = this.props;
|
||||||
|
if (rewardsNotInterested) {
|
||||||
|
this.setState({ showRewardsNag: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ showRewardsNag: false }, () => {
|
||||||
|
Snackbar.show({
|
||||||
|
title: __('Did you know that you can earn free credits worth up to %amount%?', {
|
||||||
|
amount: formatUsd(parseFloat(this.state.usdExchangeRate) * parseFloat(unclaimedRewardAmount)),
|
||||||
|
}),
|
||||||
|
duration: Snackbar.LENGTH_LONG,
|
||||||
|
action: {
|
||||||
|
title: __('SHOW ME'),
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
onPress: () => {
|
||||||
|
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_REWARDS });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
handleSortByItemSelected = item => {
|
handleSortByItemSelected = item => {
|
||||||
this.setState({ currentSortByItem: item, orderBy: getOrderBy(item), showSortPicker: false });
|
this.setState({ currentSortByItem: item, orderBy: getOrderBy(item), showSortPicker: false });
|
||||||
};
|
};
|
||||||
|
@ -137,21 +187,7 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { subscribedChannels, loading, loadingSuggested, sdkReady, timeItem, navigation, notify } = this.props;
|
||||||
suggestedChannels,
|
|
||||||
subscribedChannels,
|
|
||||||
allSubscriptions,
|
|
||||||
doCompleteFirstRun,
|
|
||||||
doShowSuggestedSubs,
|
|
||||||
loading,
|
|
||||||
loadingSuggested,
|
|
||||||
firstRunCompleted,
|
|
||||||
showSuggestedSubs,
|
|
||||||
timeItem,
|
|
||||||
unreadSubscriptions,
|
|
||||||
navigation,
|
|
||||||
notify,
|
|
||||||
} = this.props;
|
|
||||||
const { currentSortByItem, filteredChannels, showModalSuggestedSubs, showSortPicker, showTimePicker } = this.state;
|
const { currentSortByItem, filteredChannels, showModalSuggestedSubs, showSortPicker, showTimePicker } = this.state;
|
||||||
|
|
||||||
const numberOfSubscriptions = subscribedChannels ? subscribedChannels.length : 0;
|
const numberOfSubscriptions = subscribedChannels ? subscribedChannels.length : 0;
|
||||||
|
@ -296,6 +332,8 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
onDonePress={() => this.setState({ showModalSuggestedSubs: false })}
|
onDonePress={() => this.setState({ showModalSuggestedSubs: false })}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{!sdkReady && <SdkLoadingStatus />}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,12 @@ import { selectFollowedTags, doToggleTagFollow } from 'lbry-redux';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
import { doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
||||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||||
import { selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
import { selectSdkReady, selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
||||||
import TagPage from './view';
|
import TagPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
currentRoute: selectCurrentRoute(state),
|
currentRoute: selectCurrentRoute(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
sortByItem: selectSortByItem(state),
|
sortByItem: selectSortByItem(state),
|
||||||
timeItem: selectTimeItem(state),
|
timeItem: selectTimeItem(state),
|
||||||
followedTags: selectFollowedTags(state),
|
followedTags: selectFollowedTags(state),
|
||||||
|
@ -21,7 +22,4 @@ const perform = dispatch => ({
|
||||||
toggleTagFollow: tag => dispatch(doToggleTagFollow(tag)),
|
toggleTagFollow: tag => dispatch(doToggleTagFollow(tag)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(TagPage);
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(TagPage);
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import ModalPicker from 'component/modalPicker';
|
import ModalPicker from 'component/modalPicker';
|
||||||
|
import SdkLoadingStatus from 'component/sdkLoadingStatus';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
|
|
||||||
class TagPage extends React.PureComponent {
|
class TagPage extends React.PureComponent {
|
||||||
|
@ -127,7 +128,7 @@ class TagPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { navigation, sortByItem, timeItem } = this.props;
|
const { navigation, sdkReady, sortByItem, timeItem } = this.props;
|
||||||
const { tag, showSortPicker, showTimePicker } = this.state;
|
const { tag, showSortPicker, showTimePicker } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -144,7 +145,7 @@ class TagPage extends React.PureComponent {
|
||||||
orientation={Constants.ORIENTATION_VERTICAL}
|
orientation={Constants.ORIENTATION_VERTICAL}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!showSortPicker && !showTimePicker && <FloatingWalletBalance navigation={navigation} />}
|
{sdkReady && !showSortPicker && !showTimePicker && <FloatingWalletBalance navigation={navigation} />}
|
||||||
{showSortPicker && (
|
{showSortPicker && (
|
||||||
<ModalPicker
|
<ModalPicker
|
||||||
title={__('Sort content by')}
|
title={__('Sort content by')}
|
||||||
|
@ -163,6 +164,7 @@ class TagPage extends React.PureComponent {
|
||||||
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{!sdkReady && <SdkLoadingStatus />}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectSdkReady } from 'redux/selectors/settings';
|
||||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||||
import { selectBalance } from 'lbry-redux';
|
import { selectBalance } from 'lbry-redux';
|
||||||
|
@ -15,6 +15,7 @@ const select = state => ({
|
||||||
deviceWalletSynced: makeSelectClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED)(state),
|
deviceWalletSynced: makeSelectClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED)(state),
|
||||||
hasSyncedWallet: selectHasSyncedWallet(state),
|
hasSyncedWallet: selectHasSyncedWallet(state),
|
||||||
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
||||||
|
sdkReady: selectSdkReady(state),
|
||||||
understandsRisks: makeSelectClientSetting(Constants.SETTING_ALPHA_UNDERSTANDS_RISKS)(state),
|
understandsRisks: makeSelectClientSetting(Constants.SETTING_ALPHA_UNDERSTANDS_RISKS)(state),
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
});
|
});
|
||||||
|
@ -27,7 +28,4 @@ const perform = dispatch => ({
|
||||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(WalletPage);
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(WalletPage);
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NativeModules, ScrollView, Text, View } from 'react-native';
|
import { NativeModules, ScrollView, Text, View } from 'react-native';
|
||||||
|
import EmptyStateView from 'component/emptyStateView';
|
||||||
import TransactionListRecent from 'component/transactionListRecent';
|
import TransactionListRecent from 'component/transactionListRecent';
|
||||||
import WalletAddress from 'component/walletAddress';
|
import WalletAddress from 'component/walletAddress';
|
||||||
import WalletBalance from 'component/walletBalance';
|
import WalletBalance from 'component/walletBalance';
|
||||||
|
@ -8,8 +9,6 @@ import WalletSend from 'component/walletSend';
|
||||||
import WalletRewardsDriver from 'component/walletRewardsDriver';
|
import WalletRewardsDriver from 'component/walletRewardsDriver';
|
||||||
import WalletSignIn from 'component/walletSignIn';
|
import WalletSignIn from 'component/walletSignIn';
|
||||||
import WalletSyncDriver from 'component/walletSyncDriver';
|
import WalletSyncDriver from 'component/walletSyncDriver';
|
||||||
import Button from 'component/button';
|
|
||||||
import Link from 'component/link';
|
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import walletStyle from 'styles/wallet';
|
import walletStyle from 'styles/wallet';
|
||||||
|
@ -60,16 +59,20 @@ class WalletPage extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { balance, rewardsNotInterested, understandsRisks, navigation, sdkReady, user } = this.props;
|
||||||
balance,
|
|
||||||
backupDismissed,
|
if (!sdkReady) {
|
||||||
hasSyncedWallet,
|
return (
|
||||||
rewardsNotInterested,
|
<View style={walletStyle.container}>
|
||||||
understandsRisks,
|
<UriBar navigation={navigation} />
|
||||||
setClientSetting,
|
<EmptyStateView
|
||||||
navigation,
|
message={__(
|
||||||
user,
|
'The background service is still initializing. You can still explore and watch content during the initialization process.',
|
||||||
} = this.props;
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const signedIn = user && user.has_verified_email;
|
const signedIn = user && user.has_verified_email;
|
||||||
if (!signedIn && !understandsRisks) {
|
if (!signedIn && !understandsRisks) {
|
||||||
|
@ -91,7 +94,7 @@ class WalletPage extends React.PureComponent {
|
||||||
>
|
>
|
||||||
{!rewardsNotInterested && (!balance || balance === 0) && <WalletRewardsDriver navigation={navigation} />}
|
{!rewardsNotInterested && (!balance || balance === 0) && <WalletRewardsDriver navigation={navigation} />}
|
||||||
<WalletBalance />
|
<WalletBalance />
|
||||||
<WalletBalanceExtra />
|
<WalletBalanceExtra navigation={navigation} />
|
||||||
<WalletAddress />
|
<WalletAddress />
|
||||||
<WalletSend />
|
<WalletSend />
|
||||||
<TransactionListRecent navigation={navigation} />
|
<TransactionListRecent navigation={navigation} />
|
||||||
|
|
|
@ -17,6 +17,14 @@ export function doSetClientSetting(key, value) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function doSetSdkReady() {
|
||||||
|
return dispatch => {
|
||||||
|
dispatch({
|
||||||
|
type: Constants.ACTION_SDK_READY,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function doSetSortByItem(item) {
|
export function doSetSortByItem(item) {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
clientSettings: {},
|
clientSettings: {},
|
||||||
|
sdkReady: false,
|
||||||
sortByItemName: Constants.SORT_BY_HOT,
|
sortByItemName: Constants.SORT_BY_HOT,
|
||||||
timeItemName: Constants.TIME_WEEK,
|
timeItemName: Constants.TIME_WEEK,
|
||||||
fullscreenMode: false,
|
fullscreenMode: false,
|
||||||
|
@ -20,6 +21,11 @@ reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
reducers[Constants.ACTION_SDK_READY] = (state, action) =>
|
||||||
|
Object.assign({}, state, {
|
||||||
|
sdkReady: true,
|
||||||
|
});
|
||||||
|
|
||||||
reducers[Constants.ACTION_SORT_BY_ITEM_CHANGED] = (state, action) =>
|
reducers[Constants.ACTION_SORT_BY_ITEM_CHANGED] = (state, action) =>
|
||||||
Object.assign({}, state, {
|
Object.assign({}, state, {
|
||||||
sortByItemName: action.data.name,
|
sortByItemName: action.data.name,
|
||||||
|
|
|
@ -4,38 +4,22 @@ import { getSortByItemForName, getTimeItemForName } from 'utils/helper';
|
||||||
|
|
||||||
const selectState = state => state.settings || {};
|
const selectState = state => state.settings || {};
|
||||||
|
|
||||||
export const selectDaemonSettings = createSelector(
|
export const selectDaemonSettings = createSelector(selectState, state => state.daemonSettings);
|
||||||
selectState,
|
|
||||||
state => state.daemonSettings
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectClientSettings = createSelector(
|
export const selectClientSettings = createSelector(selectState, state => state.clientSettings || {});
|
||||||
selectState,
|
|
||||||
state => state.clientSettings || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectSortByItem = createSelector(
|
export const selectSortByItem = createSelector(selectState, state => getSortByItemForName(state.sortByItemName));
|
||||||
selectState,
|
|
||||||
state => getSortByItemForName(state.sortByItemName)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectTimeItem = createSelector(
|
export const selectTimeItem = createSelector(selectState, state => getTimeItemForName(state.timeItemName));
|
||||||
selectState,
|
|
||||||
state => getTimeItemForName(state.timeItemName)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const makeSelectClientSetting = setting =>
|
export const makeSelectClientSetting = setting =>
|
||||||
createSelector(
|
createSelector(selectClientSettings, settings => (settings ? settings[setting] : undefined));
|
||||||
selectClientSettings,
|
|
||||||
settings => (settings ? settings[setting] : undefined)
|
|
||||||
);
|
|
||||||
|
|
||||||
// refactor me
|
// refactor me
|
||||||
export const selectShowNsfw = makeSelectClientSetting(SETTINGS.SHOW_NSFW);
|
export const selectShowNsfw = makeSelectClientSetting(SETTINGS.SHOW_NSFW);
|
||||||
|
|
||||||
export const selectKeepDaemonRunning = makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING);
|
export const selectKeepDaemonRunning = makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING);
|
||||||
|
|
||||||
export const selectFullscreenMode = createSelector(
|
export const selectFullscreenMode = createSelector(selectState, state => state.fullscreenMode);
|
||||||
selectState,
|
|
||||||
state => state.fullscreenMode
|
export const selectSdkReady = createSelector(selectState, state => state.sdkReady);
|
||||||
);
|
|
||||||
|
|
|
@ -398,6 +398,23 @@ const discoverStyle = StyleSheet.create({
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
|
sdkLoading: {
|
||||||
|
position: 'absolute',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
padding: 8,
|
||||||
|
backgroundColor: Colors.LbryGreen,
|
||||||
|
},
|
||||||
|
sdkLoadingText: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.White,
|
||||||
|
marginLeft: 8,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default discoverStyle;
|
export default discoverStyle;
|
||||||
|
|
93
src/styles/modalRepost.js
Normal file
93
src/styles/modalRepost.js
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
import Colors from './colors';
|
||||||
|
|
||||||
|
const modalRepostStyle = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 24,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
amountRow: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginRight: 24,
|
||||||
|
},
|
||||||
|
depositAmountInput: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
textAlign: 'right',
|
||||||
|
width: 80,
|
||||||
|
letterSpacing: 1,
|
||||||
|
},
|
||||||
|
currency: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 12,
|
||||||
|
marginLeft: 4,
|
||||||
|
},
|
||||||
|
buttonRow: {
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginTop: 16,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
backgroundColor: Colors.LbryGreen,
|
||||||
|
},
|
||||||
|
cancelLink: {
|
||||||
|
color: Colors.Grey,
|
||||||
|
},
|
||||||
|
advancedLink: {
|
||||||
|
color: Colors.Grey,
|
||||||
|
marginRight: 16,
|
||||||
|
},
|
||||||
|
balance: {
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginLeft: 24,
|
||||||
|
},
|
||||||
|
balanceText: {
|
||||||
|
fontFamily: 'Inter-SemiBold',
|
||||||
|
fontSize: 14,
|
||||||
|
marginLeft: 4,
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
marginTop: 4,
|
||||||
|
},
|
||||||
|
infoText: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.DescriptionGrey,
|
||||||
|
},
|
||||||
|
learnMoreLink: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
nameRow: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
rightButtonRow: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default modalRepostStyle;
|
|
@ -411,6 +411,7 @@ const publishStyle = StyleSheet.create({
|
||||||
marginTop: 60,
|
marginTop: 60,
|
||||||
},
|
},
|
||||||
publishesScrollPadding: {
|
publishesScrollPadding: {
|
||||||
|
paddingTop: 16,
|
||||||
paddingBottom: 16,
|
paddingBottom: 16,
|
||||||
},
|
},
|
||||||
listItem: {
|
listItem: {
|
||||||
|
@ -418,8 +419,9 @@ const publishStyle = StyleSheet.create({
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
marginTop: 8,
|
marginTop: 8,
|
||||||
marginLeft: 8,
|
marginLeft: 16,
|
||||||
marginRight: 8,
|
marginRight: 16,
|
||||||
|
marginBottom: 12,
|
||||||
},
|
},
|
||||||
noVideos: {
|
noVideos: {
|
||||||
color: Colors.White,
|
color: Colors.White,
|
||||||
|
@ -449,7 +451,7 @@ const publishStyle = StyleSheet.create({
|
||||||
publishesFooterButton: {
|
publishesFooterButton: {
|
||||||
alignSelf: 'flex-start',
|
alignSelf: 'flex-start',
|
||||||
backgroundColor: Colors.LbryGreen,
|
backgroundColor: Colors.LbryGreen,
|
||||||
marginTop: 16,
|
marginTop: 8,
|
||||||
},
|
},
|
||||||
thumbnailEditOverlay: {
|
thumbnailEditOverlay: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|
|
@ -147,6 +147,10 @@ const rewardStyle = StyleSheet.create({
|
||||||
width: '18%',
|
width: '18%',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
|
rightColHeader: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
rewardAmount: {
|
rewardAmount: {
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
fontSize: 26,
|
fontSize: 26,
|
||||||
|
@ -154,6 +158,7 @@ const rewardStyle = StyleSheet.create({
|
||||||
},
|
},
|
||||||
rewardCurrency: {
|
rewardCurrency: {
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 12,
|
||||||
},
|
},
|
||||||
rewardTitle: {
|
rewardTitle: {
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
|
@ -322,6 +327,12 @@ const rewardStyle = StyleSheet.create({
|
||||||
activeFilterLink: {
|
activeFilterLink: {
|
||||||
fontFamily: 'Inter-SemiBold',
|
fontFamily: 'Inter-SemiBold',
|
||||||
},
|
},
|
||||||
|
rewardUsd: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.DescriptionGrey,
|
||||||
|
marginTop: 6,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default rewardStyle;
|
export default rewardStyle;
|
||||||
|
|
|
@ -192,8 +192,6 @@ const subscriptionsStyle = StyleSheet.create({
|
||||||
suggestedItem: {
|
suggestedItem: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
marginLeft: 16,
|
|
||||||
marginRight: 16,
|
|
||||||
height: 140,
|
height: 140,
|
||||||
},
|
},
|
||||||
suggestedItemThumbnailContainer: {
|
suggestedItemThumbnailContainer: {
|
||||||
|
@ -209,8 +207,8 @@ const subscriptionsStyle = StyleSheet.create({
|
||||||
height: '100%',
|
height: '100%',
|
||||||
},
|
},
|
||||||
suggestedItemDetails: {
|
suggestedItemDetails: {
|
||||||
marginLeft: 16,
|
marginLeft: 8,
|
||||||
marginRight: 16,
|
marginRight: 8,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
suggestedItemSubscribe: {
|
suggestedItemSubscribe: {
|
||||||
|
@ -229,7 +227,7 @@ const subscriptionsStyle = StyleSheet.create({
|
||||||
suggestedItemTitle: {
|
suggestedItemTitle: {
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontSize: 14,
|
fontSize: 13,
|
||||||
marginTop: 4,
|
marginTop: 4,
|
||||||
marginBottom: 2,
|
marginBottom: 2,
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,7 +23,7 @@ const tagStyle = StyleSheet.create({
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
fontSize: 14,
|
fontSize: 12,
|
||||||
marginRight: 8,
|
marginRight: 8,
|
||||||
},
|
},
|
||||||
tagResultsList: {
|
tagResultsList: {
|
||||||
|
|
|
@ -103,10 +103,12 @@ const walletStyle = StyleSheet.create({
|
||||||
marginLeft: 16,
|
marginLeft: 16,
|
||||||
marginRight: 16,
|
marginRight: 16,
|
||||||
},
|
},
|
||||||
balanceExtraCard: {
|
balanceExtra: {
|
||||||
backgroundColor: Colors.White,
|
|
||||||
marginLeft: 16,
|
marginLeft: 16,
|
||||||
marginRight: 16,
|
marginRight: 16,
|
||||||
|
},
|
||||||
|
balanceExtraCard: {
|
||||||
|
backgroundColor: Colors.White,
|
||||||
padding: 16,
|
padding: 16,
|
||||||
},
|
},
|
||||||
balanceBackground: {
|
balanceBackground: {
|
||||||
|
@ -135,6 +137,13 @@ const walletStyle = StyleSheet.create({
|
||||||
fontFamily: 'Inter-Bold',
|
fontFamily: 'Inter-Bold',
|
||||||
fontSize: 36,
|
fontSize: 36,
|
||||||
marginLeft: 16,
|
marginLeft: 16,
|
||||||
|
},
|
||||||
|
usdBalance: {
|
||||||
|
color: Colors.White,
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 20,
|
||||||
|
marginLeft: 16,
|
||||||
|
marginTop: 2,
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
},
|
},
|
||||||
balanceFocus: {
|
balanceFocus: {
|
||||||
|
@ -252,6 +261,22 @@ const walletStyle = StyleSheet.create({
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
borderBottomColor: Colors.PageBackground,
|
borderBottomColor: Colors.PageBackground,
|
||||||
},
|
},
|
||||||
|
syncDriverCustody: {
|
||||||
|
backgroundColor: Colors.LbryGreen,
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
syncInfoText: {
|
||||||
|
color: Colors.White,
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 16,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
syncInfoLink: {
|
||||||
|
color: Colors.White,
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
textDecorationLine: 'underline',
|
||||||
|
},
|
||||||
syncDriverLink: {
|
syncDriverLink: {
|
||||||
color: Colors.LbryGreen,
|
color: Colors.LbryGreen,
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
|
@ -384,6 +409,11 @@ const walletStyle = StyleSheet.create({
|
||||||
fontFamily: 'Inter-SemiBold',
|
fontFamily: 'Inter-SemiBold',
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
},
|
},
|
||||||
|
usdWalletExtraBalance: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.DescriptionGrey,
|
||||||
|
},
|
||||||
balanceRow: {
|
balanceRow: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
@ -406,6 +436,34 @@ const walletStyle = StyleSheet.create({
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
},
|
},
|
||||||
|
usdInfoCard: {
|
||||||
|
backgroundColor: Colors.White,
|
||||||
|
padding: 16,
|
||||||
|
borderBottomColor: Colors.VeryLightGrey,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
},
|
||||||
|
usdInfoText: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
usdConvertLink: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
},
|
||||||
|
usdConvertFaqLink: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
},
|
||||||
|
earnTipsLink: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
marginTop: 12,
|
||||||
|
marginRight: 16,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default walletStyle;
|
export default walletStyle;
|
||||||
|
|
|
@ -436,3 +436,10 @@ export function fetchReferralCode(successCallback, errorCallback) {
|
||||||
export function decode(value) {
|
export function decode(value) {
|
||||||
return decodeURIComponent(value).replace(/\+/g, ' ');
|
return decodeURIComponent(value).replace(/\+/g, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatUsd(value) {
|
||||||
|
if (isNaN(parseFloat(value))) {
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
return '$' + parseFloat(value).toFixed(2);
|
||||||
|
}
|
||||||
|
|
|
@ -4591,17 +4591,17 @@ latest-version@^3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
package-json "^4.0.0"
|
package-json "^4.0.0"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#84e697079968364fe526020086c8a44f4d2ef391:
|
lbry-redux@lbryio/lbry-redux#69ffd110dbf3633e5847f61f008751edec033017:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/84e697079968364fe526020086c8a44f4d2ef391"
|
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/69ffd110dbf3633e5847f61f008751edec033017"
|
||||||
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#28afb9b06c3d142bad8347939c043a21b6cb1ae1:
|
lbryinc@lbryio/lbryinc#667024ebb7cb207609273174ca422cee47469270:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/28afb9b06c3d142bad8347939c043a21b6cb1ae1"
|
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/667024ebb7cb207609273174ca422cee47469270"
|
||||||
dependencies:
|
dependencies:
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue