refactor and batch-resolve for related content component #81

Merged
akinwale merged 2 commits from related-batch-resolve into master 2019-11-18 06:48:55 +01:00
7 changed files with 48 additions and 136 deletions

View file

@ -40,8 +40,8 @@ class FileListItem extends React.PureComponent {
}; };
componentDidMount() { componentDidMount() {
const { claim, resolveUri, uri } = this.props; const { claim, resolveUri, uri, batchResolve } = this.props;
if (!claim) { if (!claim && !batchResolve) {
resolveUri(uri); resolveUri(uri);
} }
} }

View file

@ -1,11 +1,11 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
doResolveUris,
makeSelectClaimForUri, makeSelectClaimForUri,
makeSelectRecommendedContentForUri, makeSelectRecommendedContentForUri,
makeSelectTitleForUri, makeSelectTitleForUri,
selectIsSearching, selectIsSearching,
} from 'lbry-redux'; } from 'lbry-redux';
import { doNativeSearch } from 'redux/actions/performance';
import RelatedContent from './view'; import RelatedContent from './view';
const select = (state, props) => ({ const select = (state, props) => ({
@ -16,7 +16,7 @@ const select = (state, props) => ({
}); });
const perform = dispatch => ({ const perform = dispatch => ({
search: query => dispatch(doNativeSearch(query, 20, undefined, true)), resolveUris: uris => dispatch(doResolveUris(uris)),
}); });
export default connect( export default connect(

View file

@ -8,45 +8,23 @@ import fileListStyle from 'styles/fileList';
import relatedContentStyle from 'styles/relatedContent'; import relatedContentStyle from 'styles/relatedContent';
export default class RelatedContent extends React.PureComponent { export default class RelatedContent extends React.PureComponent {
constructor() { state = {
super(); urlsResolved: false,
};
this.didSearch = undefined;
}
componentDidMount() {
this.getRecommendedContent();
}
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
const { claim, uri } = this.props; const { resolveUris, recommendedContent } = this.props;
if (uri !== prevProps.uri) { if (recommendedContent && recommendedContent.length > 0 && !this.state.urisResolved) {
this.didSearch = false; this.setState({ urisResolved: true }, () => {
} // batch resolve the uris
resolveUris(recommendedContent);
if (claim && !this.didSearch) { });
this.getRecommendedContent();
} }
} }
getRecommendedContent() {
const { search, title } = this.props;
if (title) {
search(title);
this.didSearch = true;
}
}
didSearch;
render() { render() {
const { recommendedContent, isSearching, navigation, uri, fullUri } = this.props; const { recommendedContent, navigation, uri, fullUri } = this.props;
if (!isSearching && (!recommendedContent || recommendedContent.length === 0)) {
return null;
}
return ( return (
<View style={relatedContentStyle.container}> <View style={relatedContentStyle.container}>
@ -59,13 +37,11 @@ export default class RelatedContent extends React.PureComponent {
style={fileListStyle.item} style={fileListStyle.item}
key={recommendedUri} key={recommendedUri}
uri={recommendedUri} uri={recommendedUri}
batchResolve
navigation={navigation} navigation={navigation}
autoplay autoplay
/> />
))} ))}
{isSearching && (
<ActivityIndicator size="small" color={Colors.NextLbryGreen} style={relatedContentStyle.loading} />
)}
</View> </View>
); );
} }

View file

@ -8,6 +8,7 @@ import {
doPurchaseUri, doPurchaseUri,
doDeletePurchasedUri, doDeletePurchasedUri,
doResolveUri, doResolveUri,
doSearch,
doSendTip, doSendTip,
doToast, doToast,
makeSelectIsUriResolving, makeSelectIsUriResolving,
@ -17,6 +18,7 @@ import {
makeSelectContentPositionForUri, makeSelectContentPositionForUri,
makeSelectContentTypeForUri, makeSelectContentTypeForUri,
makeSelectMetadataForUri, makeSelectMetadataForUri,
makeSelectRecommendedContentForUri,
makeSelectStreamingUrlForUri, makeSelectStreamingUrlForUri,
makeSelectThumbnailForUri, makeSelectThumbnailForUri,
makeSelectTitleForUri, makeSelectTitleForUri,
@ -26,6 +28,7 @@ import {
selectPurchasedUris, selectPurchasedUris,
selectFailedPurchaseUris, selectFailedPurchaseUris,
selectPurchaseUriErrorMessage, selectPurchaseUriErrorMessage,
selectIsSearching,
} from 'lbry-redux'; } from 'lbry-redux';
import { import {
doClaimEligiblePurchaseRewards, doClaimEligiblePurchaseRewards,
@ -70,6 +73,8 @@ const select = (state, props) => {
streamingUrl: makeSelectStreamingUrlForUri(contentUri)(state), streamingUrl: makeSelectStreamingUrlForUri(contentUri)(state),
thumbnail: makeSelectThumbnailForUri(contentUri)(state), thumbnail: makeSelectThumbnailForUri(contentUri)(state),
title: makeSelectTitleForUri(contentUri)(state), title: makeSelectTitleForUri(contentUri)(state),
recommendedContent: makeSelectRecommendedContentForUri(contentUri)(state),
isSearchingRecommendContent: selectIsSearching(state),
}; };
}; };
@ -89,6 +94,7 @@ const perform = dispatch => ({
purchaseUri: (uri, costInfo, saveFile) => dispatch(doPurchaseUri(uri, costInfo, saveFile)), purchaseUri: (uri, costInfo, saveFile) => dispatch(doPurchaseUri(uri, costInfo, saveFile)),
deletePurchasedUri: uri => dispatch(doDeletePurchasedUri(uri)), deletePurchasedUri: uri => dispatch(doDeletePurchasedUri(uri)),
resolveUri: uri => dispatch(doResolveUri(uri)), resolveUri: uri => dispatch(doResolveUri(uri)),
searchRecommended: query => dispatch(doSearch(query, 20, undefined, true)),
sendTip: (amount, claimId, isSupport, successCallback, errorCallback) => sendTip: (amount, claimId, isSupport, successCallback, errorCallback) =>
dispatch(doSendTip(amount, claimId, isSupport, successCallback, errorCallback)), dispatch(doSendTip(amount, claimId, isSupport, successCallback, errorCallback)),
setPlayerVisible: () => dispatch(doSetPlayerVisible(true)), setPlayerVisible: () => dispatch(doSetPlayerVisible(true)),

View file

@ -85,6 +85,7 @@ class FilePage extends React.PureComponent {
uriVars: null, uriVars: null,
stopDownloadConfirmed: false, stopDownloadConfirmed: false,
streamingMode: false, streamingMode: false,
didSearchRecommended: false,
}; };
} }
@ -185,12 +186,25 @@ class FilePage extends React.PureComponent {
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
const { claim, contentType, fileInfo, isResolvingUri, resolveUri, navigation } = this.props; const {
claim,
contentType,
fileInfo,
isResolvingUri,
resolveUri,
navigation,
searchRecommended,
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);
} }
if (title && !this.state.didSearchRecommended) {
this.setState({ didSearchRecommended: true }, () => searchRecommended(title));
}
// Returned to the page. If mediaLoaded, and currentMediaInfo is different, update // Returned to the page. If mediaLoaded, and currentMediaInfo is different, update
if (this.state.mediaLoaded && window.currentMediaInfo && window.currentMediaInfo.uri !== this.state.uri) { if (this.state.mediaLoaded && window.currentMediaInfo && window.currentMediaInfo.uri !== this.state.uri) {
const { metadata } = this.props; const { metadata } = this.props;
@ -607,6 +621,8 @@ class FilePage extends React.PureComponent {
navigation, navigation,
position, position,
purchaseUri, purchaseUri,
isSearchingRecommendContent,
recommendedContent,
thumbnail, thumbnail,
title, title,
} = this.props; } = this.props;
@ -1105,7 +1121,13 @@ class FilePage extends React.PureComponent {
)} )}
<View onLayout={this.setRelatedContentPosition} /> <View onLayout={this.setRelatedContentPosition} />
{isSearchingRecommendContent && (
<ActivityIndicator size="small" color={Colors.NextLbryGreen} style={filePageStyle.relatedLoading} />
)}
{!isSearchingRecommendContent && recommendedContent && recommendedContent.length > 0 && (
<RelatedContent navigation={navigation} uri={uri} fullUri={fullUri} /> <RelatedContent navigation={navigation} uri={uri} fullUri={fullUri} />
)}
</ScrollView> </ScrollView>
</View> </View>
)} )}

View file

@ -1,95 +0,0 @@
// @flow
import { NativeModules } from 'react-native';
import {
ACTIONS,
batchActions,
buildURI,
doResolveUri,
doUpdateSearchQuery,
makeSelectSearchUris,
selectSuggestions,
makeSelectQueryWithOptions,
selectSearchValue,
} from 'lbry-redux';
let CONNECTION_STRING = 'https://lighthouse.lbry.com/';
const handleNativeFetchResponse = str => {
const json = JSON.parse(str);
if (json.error) {
return Promise.reject(new Error(json.error));
}
return Promise.resolve(json);
};
// Use a native asyncTask to call the lighthouse api
export const doNativeSearch = (
rawQuery: string, // pass in a query if you don't want to search for what's in the search bar
size: ?number, // only pass in if you don't want to use the users setting (ex: related content)
from: ?number,
isBackgroundSearch: boolean = false
) => (dispatch: Dispatch, getState: GetState) => {
const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' ');
if (!query) {
dispatch({
type: ACTIONS.SEARCH_FAIL,
});
return;
}
const state = getState();
const queryWithOptions = makeSelectQueryWithOptions(query, size, from, isBackgroundSearch)(state);
// If we have already searched for something, we don't need to do anything
const urisForQuery = makeSelectSearchUris(queryWithOptions)(state);
if (urisForQuery && !!urisForQuery.length) {
return;
}
dispatch({
type: ACTIONS.SEARCH_START,
});
// If the user is on the file page with a pre-populated uri and they select
// the search option without typing anything, searchQuery will be empty
// We need to populate it so the input is filled on the search page
// isBackgroundSearch means the search is happening in the background, don't update the search query
if (!state.search.searchQuery && !isBackgroundSearch) {
dispatch(doUpdateSearchQuery(query));
}
const url = `${CONNECTION_STRING}search?${queryWithOptions}`;
NativeModules.Requests.get(url)
.then(handleNativeFetchResponse)
.then((data: Array<{ name: String, claimId: string }>) => {
const uris = [];
const actions = [];
data.forEach(result => {
if (result.name) {
const uri = buildURI({
claimName: result.name,
claimId: result.claimId,
});
actions.push(doResolveUri(uri));
uris.push(uri);
}
});
actions.push({
type: ACTIONS.SEARCH_SUCCESS,
data: {
query: queryWithOptions,
uris,
},
});
dispatch(batchActions(...actions));
})
.catch(e => {
dispatch({
type: ACTIONS.SEARCH_FAIL,
});
});
};

View file

@ -435,6 +435,9 @@ const filePageStyle = StyleSheet.create({
fontSize: 16, fontSize: 16,
marginTop: 4, marginTop: 4,
}, },
relatedLoading: {
marginTop: 16,
},
}); });
export default filePageStyle; export default filePageStyle;