Unverified Commit 12d7fbd4 authored by Akinwale Ariwodola's avatar Akinwale Ariwodola Committed by GitHub
Browse files

lbry.tv hybrid mode (#132)

* use lbry.tv for resolve and claim_search
* gracefully handle dynamic sdk ready state
* update pinned lbry-redux commit
* use empty state view when sdk is not ready
* traditional mode if dht is enabled
parent 4645a8f4
......@@ -176,9 +176,7 @@ export default class ChannelCreator extends React.PureComponent {
NativeModules.Firebase.setCurrentScreen('Channels').then(result => {
pushDrawerStack(Constants.DRAWER_ROUTE_CHANNEL_CREATOR, navigation.state.params ? navigation.state.params : null);
setPlayerVisible();
if (!fetchingChannels) {
fetchChannelListMine();
}
fetchChannelListMine();
DeviceEventEmitter.addListener('onDocumentPickerFilePicked', this.onFilePicked);
DeviceEventEmitter.addListener('onDocumentPickerCanceled', this.onPickerCanceled);
......@@ -802,7 +800,15 @@ export default class ChannelCreator extends React.PureComponent {
};
render() {
const { abandoningClaimIds, balance, fetchingChannels, updatingChannel, channels = [], navigation } = this.props;
const {
abandoningClaimIds,
balance,
fetchingChannels,
sdkReady,
updatingChannel,
channels = [],
navigation,
} = this.props;
const {
autoStyle,
autoStyles,
......@@ -826,6 +832,19 @@ export default class ChannelCreator extends React.PureComponent {
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 (
<View style={channelCreatorStyle.container}>
<UriBar
......
......@@ -13,7 +13,7 @@ import {
} from 'lbryinc';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
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 DiscoverPage from './view';
......@@ -27,6 +27,7 @@ const select = state => ({
followedTags: selectFollowedTags(state),
ratingReminderDisabled: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED)(state),
ratingReminderLastShown: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_LAST_SHOWN)(state),
sdkReady: selectSdkReady(state),
sortByItem: selectSortByItem(state),
timeItem: selectTimeItem(state),
unreadSubscriptions: selectUnreadSubscriptions(state),
......@@ -46,7 +47,4 @@ const perform = dispatch => ({
setTimeItem: item => dispatch(doSetTimeItem(item)),
});
export default connect(
select,
perform,
)(DiscoverPage);
export default connect(select, perform)(DiscoverPage);
......@@ -23,6 +23,7 @@ import Icon from 'react-native-vector-icons/FontAwesome5';
import Link from 'component/link';
import ModalTagSelector from 'component/modalTagSelector';
import ModalPicker from 'component/modalPicker';
import SdkLoadingStatus from 'component/sdkLoadingStatus';
import UriBar from 'component/uriBar';
import _ from 'lodash';
......@@ -268,8 +269,8 @@ class DiscoverPage extends React.PureComponent {
);
render() {
const { currentRoute, navigation, sortByItem, timeItem } = this.props;
const { orderBy, showModalTagSelector, showSortPicker, showTimePicker } = this.state;
const { currentRoute, navigation, sdkReady, sortByItem, timeItem } = this.props;
const { showModalTagSelector, showSortPicker, showTimePicker } = this.state;
return (
<View style={discoverStyle.container}>
......@@ -289,7 +290,7 @@ class DiscoverPage extends React.PureComponent {
keyExtractor={(item, index) => item}
/>
)}
{!showModalTagSelector && !showSortPicker && !showTimePicker && (
{sdkReady && !showModalTagSelector && !showSortPicker && !showTimePicker && (
<FloatingWalletBalance navigation={navigation} />
)}
{showModalTagSelector && (
......@@ -316,6 +317,8 @@ class DiscoverPage extends React.PureComponent {
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
/>
)}
{!sdkReady && <SdkLoadingStatus />}
</View>
);
}
......
......@@ -11,15 +11,17 @@ import {
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { doDeleteFile } from 'redux/actions/file';
import { selectCurrentRoute } from 'redux/selectors/drawer';
import { selectSdkReady } from 'redux/selectors/settings';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import DownloadsPage from './view';
const select = state => ({
claims: selectMyClaimsWithoutChannels(state),
currentRoute: selectCurrentRoute(state),
fileInfos: selectFileInfosDownloaded(state),
downloadedUris: selectDownloadedUris(state),
fileInfos: selectFileInfosDownloaded(state),
fetching: selectIsFetchingFileList(state) || selectIsFetchingClaimListMine(state),
sdkReady: selectSdkReady(state),
});
const perform = dispatch => ({
......@@ -32,7 +34,4 @@ const perform = dispatch => ({
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
});
export default connect(
select,
perform
)(DownloadsPage);
export default connect(select, perform)(DownloadsPage);
......@@ -144,11 +144,24 @@ class DownloadsPage extends React.PureComponent {
};
render() {
const { fetching, claims, downloadedUris, fileInfos, navigation } = this.props;
const { downloadedUris, fetching, navigation, sdkReady } = this.props;
const { selectionMode, selectedUris } = this.state;
const filteredUris = this.getFilteredUris();
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 (
<View style={downloadsStyle.container}>
<UriBar
......
......@@ -41,6 +41,7 @@ import { doDeleteFile, doStopDownloadingFile } from 'redux/actions/file';
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { doToggleFullscreenMode } from 'redux/actions/settings';
import { selectDrawerStack, makeSelectPlayerVisible } from 'redux/selectors/drawer';
import { selectSdkReady } from 'redux/selectors/settings';
import FilePage from './view';
const select = (state, props) => {
......@@ -66,6 +67,7 @@ const select = (state, props) => {
failedPurchaseUris: selectFailedPurchaseUris(state),
myClaimUris: selectMyClaimUrisWithoutChannels(state),
purchaseUriErrorMessage: selectPurchaseUriErrorMessage(state),
sdkReady: selectSdkReady(state),
streamingUrl: makeSelectStreamingUrlForUri(contentUri)(state),
thumbnail: makeSelectThumbnailForUri(contentUri)(state),
title: makeSelectTitleForUri(contentUri)(state),
......@@ -99,7 +101,4 @@ const perform = dispatch => ({
toggleFullscreenMode: mode => dispatch(doToggleFullscreenMode(mode)),
});
export default connect(
select,
perform,
)(FilePage);
export default connect(select, perform)(FilePage);
......@@ -43,7 +43,6 @@ import RelatedContent from 'component/relatedContent';
import SubscribeButton from 'component/subscribeButton';
import SubscribeNotificationButton from 'component/subscribeNotificationButton';
import UriBar from 'component/uriBar';
import Video from 'react-native-video';
import FileRewardsDriver from 'component/fileRewardsDriver';
import filePageStyle from 'styles/filePage';
import uriBarStyle from 'styles/uriBar';
......@@ -73,7 +72,7 @@ class FilePage extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
attemptAutoGet: false,
autoGetAttempted: false,
autoOpened: false,
autoDownloadStarted: false,
autoPlayMedia: false,
......@@ -297,7 +296,17 @@ class FilePage extends React.PureComponent {
}
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;
if (!isResolvingUri && claim === undefined && uri) {
resolveUri(uri);
......@@ -323,10 +332,12 @@ class FilePage extends React.PureComponent {
const isPlayable = mediaType === 'video' || mediaType === 'audio';
const isViewable = mediaType === 'image' || mediaType === 'text';
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 });
}
......@@ -706,7 +717,7 @@ class FilePage extends React.PureComponent {
};
confirmPurchaseUri = (uri, costInfo, download) => {
const { notify, purchaseUri, title } = this.props;
const { notify, purchaseUri, sdkReady, title } = this.props;
if (!costInfo) {
notify({ message: __('This content cannot be viewed at this time. Please try again in a bit.'), isError: true });
this.setState({ downloadPressed: false });
......@@ -715,6 +726,11 @@ class FilePage extends React.PureComponent {
}
const { cost } = costInfo;
if (!NativeModules.UtilityModule.dhtEnabled && !sdkReady && parseFloat(cost) === 0) {
this.attemptLbryTvPlayback();
return;
}
if (costInfo.cost > 0) {
Alert.alert(
__('Confirm Purchase'),
......@@ -742,22 +758,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 = () => {
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 isPlayable = mediaType === 'video' || mediaType === 'audio';
const isViewable = mediaType === 'image' || mediaType === 'text';
const purchaseUrl = this.getPurchaseUrl();
NativeModules.Firebase.track('purchase_uri', { uri: purchaseUrl });
if (!isPlayable) {
if (!sdkReady) {
notify({
message: __('The LBRY background service is still initializing. Please wait a few moments and try again.'),
});
return;
}
this.onDownloadPressed();
} else {
this.confirmPurchaseUri(purchaseUrl, costInfo, !isPlayable);
}
NativeModules.Firebase.track('purchase_uri', { uri: purchaseUrl });
if (isPlayable) {
this.setState({ downloadPressed: true, autoPlayMedia: true, stopDownloadConfirmed: false });
}
......@@ -1177,7 +1211,7 @@ class FilePage extends React.PureComponent {
style={filePageStyle.mediaContainer}
onPress={this.onFileDownloadButtonPressed}
>
{(canOpen || (!fileInfo || (isPlayable && !canLoadMedia)) || (!canOpen && fileInfo)) && (
{(canOpen || !fileInfo || (isPlayable && !canLoadMedia) || (!canOpen && fileInfo)) && (
<FileItemMedia
duration={duration}
style={filePageStyle.thumbnail}
......
......@@ -12,23 +12,22 @@ import {
doFetchInviteStatus,
doUserInviteNew,
} from 'lbryinc';
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { doUpdateChannelFormState, doClearChannelFormState } from 'redux/actions/form';
import { selectDrawerStack } from 'redux/selectors/drawer';
import { selectChannelFormState, selectHasChannelFormState } from 'redux/selectors/form';
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 InvitesPage from './view';
const select = state => ({
channels: selectMyChannelClaims(state),
errorMessage: selectUserInviteNewErrorMessage(state),
fetchingChannels: selectFetchingMyChannels(state),
fetchingInvitees: selectUserInviteStatusIsPending(state),
errorMessage: selectUserInviteNewErrorMessage(state),
invitees: selectUserInvitees(state),
invitesRemaining: selectUserInvitesRemaining(state),
referralCode: selectUserInviteReferralCode(state),
isPending: selectUserInviteNewIsPending(state),
invitees: selectUserInvitees(state),
referralCode: selectUserInviteReferralCode(state),
referralReward: selectReferralReward(state),
sdkReady: selectSdkReady(state),
});
const perform = dispatch => ({
......@@ -40,7 +39,4 @@ const perform = dispatch => ({
notify: data => dispatch(doToast(data)),
});
export default connect(
select,
perform,
)(InvitesPage);
export default connect(select, perform)(InvitesPage);
......@@ -11,14 +11,10 @@ import {
View,
} from 'react-native';
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 Button from 'component/button';
import ChannelSelector from 'component/channelSelector';
import PageHeader from 'component/pageHeader';
import RewardCard from 'component/rewardCard';
import RewardEnrolment from 'component/rewardEnrolment';
import EmptyStateView from 'component/emptyStateView';
import UriBar from 'component/uriBar';
import invitesStyle from 'styles/invites';
import { fetchReferralCode, logPublish } from 'utils/helper';
......@@ -134,10 +130,23 @@ class InvitesPage extends React.PureComponent {
};
render() {
const { fetchingInvitees, user, navigation, notify, isPending, invitees } = this.props;
const { email, inviteLink } = this.state;
const { fetchingInvitees, invitees, isPending, navigation, sdkReady } = this.props;
const { email } = this.state;
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 (
<View style={invitesStyle.container}>
<UriBar navigation={navigation} />
......
......@@ -13,6 +13,7 @@ import { selectDrawerStack } from 'redux/selectors/drawer';
import { doUpdatePublishFormState, doClearPublishFormState, doPendingPublishSuccess } from 'redux/actions/form';
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
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 PublishPage from './view';
......@@ -23,6 +24,7 @@ const select = state => ({
myClaims: selectMyClaims(state),
publishFormState: selectPublishFormState(state),
publishFormValues: selectPublishFormValues(state),
sdkReady: selectSdkReady(state),
});
const perform = dispatch => ({
......@@ -39,7 +41,4 @@ const perform = dispatch => ({
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
});
export default connect(
select,
perform,
)(PublishPage);
export default connect(select, perform)(PublishPage);
......@@ -37,6 +37,7 @@ import Button from 'component/button';
import ChannelSelector from 'component/channelSelector';
import Colors from 'styles/colors';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import EmptyStateView from 'component/emptyStateView';
import FastImage from 'react-native-fast-image';
import FloatingWalletBalance from 'component/floatingWalletBalance';
import Icon from 'react-native-vector-icons/FontAwesome5';
......@@ -974,7 +975,7 @@ class PublishPage extends React.PureComponent {
};
render() {
const { balance, navigation, notify, publishFormValues } = this.props;
const { balance, navigation, notify, sdkReady } = this.props;
const {
allThumbnailsChecked,
canUseCamera,
......@@ -987,6 +988,19 @@ class PublishPage extends React.PureComponent {
videos,
} = 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;
if (Constants.PHASE_SELECTOR === currentPhase) {
content = (
......
......@@ -9,6 +9,7 @@ import {
selectIsFetchingClaimListMine,
} from 'lbry-redux';
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 PublishesPage from './view';
......@@ -16,6 +17,7 @@ const select = state => ({
uris: selectMyClaimUrisWithoutChannels(state),
fetching: selectIsFetchingClaimListMine(state),
pendingClaims: selectPendingClaims(state),
sdkReady: selectSdkReady(state),
});
const perform = dispatch => ({
......@@ -27,7 +29,4 @@ const perform = dispatch => ({
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
});
export default connect(
select,
perform
)(PublishesPage);
export default connect(select, perform)(PublishesPage);
......@@ -114,14 +114,27 @@ class PublishesPage extends React.PureComponent {
},
},
],
{ cancelable: true }
{ cancelable: true },
);
};
render() {
const { fetching, navigation, uris } = this.props;
const { fetching, navigation, sdkReady, uris } = this.props;
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 (
<View style={publishStyle.container}>
<UriBar
......
......@@ -12,7 +12,8 @@ import {
import { doToast } from 'lbry-redux';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/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';
const select = state => ({
......@@ -22,6 +23,7 @@ const select = state => ({
emailVerifyPending: selectEmailVerifyIsPending(state),
fetching: selectFetchingRewards(state),
rewards: selectUnclaimedRewards(state),
sdkReady: selectSdkReady(state),
user: selectUser(state),
});
......@@ -33,7 +35,4 @@ const perform = dispatch => ({
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
});
export default connect(
select,
perform
)(RewardsPage);
export default connect(select, perform)(RewardsPage);
......@@ -5,7 +5,7 @@ import Colors from 'styles/colors';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import Link from 'component/link';
import CustomRewardCard from 'component/customRewardCard';
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';
......@@ -192,9 +192,22 @@ class RewardsPage extends React.PureComponent {
};
render() {
const { user, navigation } = this.props;
const { navigation, sdkReady } = this.props;
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 (
<View style={rewardStyle.container}>
<UriBar navigation={navigation} />
......
import React from 'react';
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 AsyncStorage from '@react-native-community/async-storage';
import Colors from 'styles/colors';
......@@ -328,7 +338,9 @@ class SettingsPage extends React.PureComponent {
<View style={settingsStyle.switchText}>
<Text style={settingsStyle.label}>{__('Participate in the data network')}</Text>
<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>
</View>
<View style={settingsStyle.switchContainer}>
......
import { connect } from 'react-redux';
import { SETTINGS, doBalanceSubscribe, doUpdateBlockHeight, doPopulateSharedUserState, doToast } from 'lbry-redux';
import { SETTINGS, doUpdateBlockHeight, doPopulateSharedUserState, doToast } from 'lbry-redux';
import {
doAuthenticate,
doInstallNew,
doInstallNewWithParams,