suggested grid vertical scrolling. semi-infinite scroll

This commit is contained in:
Akinwale Ariwodola 2020-02-21 00:21:19 +01:00
parent dbaaf66bb0
commit 647d7e6a93
7 changed files with 103 additions and 51 deletions

View file

@ -72,7 +72,15 @@ class SuggestedSubscriptionItem extends React.PureComponent {
tags
.slice(0, 1)
.map(tag => (
<Tag style={subscriptionsStyle.tag} key={tag} name={tag} navigation={navigation} truncate />
<Tag
numberOfLines={1}
onPress={this.handleItemPress}
style={subscriptionsStyle.tag}
key={tag}
name={tag}
navigation={navigation}
truncate
/>
))}
</View>
)}

View file

@ -1,5 +1,11 @@
import { connect } from 'react-redux';
import { doClaimSearch, selectFetchingClaimSearch, selectClaimSearchByQuery, selectFollowedTags } from 'lbry-redux';
import {
doClaimSearch,
selectFetchingClaimSearch,
selectClaimSearchByQuery,
selectClaimSearchByQueryLastPageReached,
selectFollowedTags,
} from 'lbry-redux';
import { selectSuggestedChannels, selectIsFetchingSuggested } from 'lbryinc';
import { selectShowNsfw } from 'redux/selectors/settings';
import SuggestedSubscriptionsGrid from './view';
@ -9,6 +15,7 @@ const select = state => ({
suggested: selectSuggestedChannels(state),
loading: selectIsFetchingSuggested(state) || selectFetchingClaimSearch(state),
claimSearchByQuery: selectClaimSearchByQuery(state),
lastPageReached: selectClaimSearchByQueryLastPageReached(state),
showNsfwContent: selectShowNsfw(state),
});

View file

@ -6,50 +6,76 @@ import { FlatGrid } from 'react-native-super-grid';
import SubscribeButton from 'component/subscribeButton';
import SuggestedSubscriptionItem from 'component/suggestedSubscriptionItem';
import Colors from 'styles/colors';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import discoverStyle from 'styles/discover';
import subscriptionsStyle from 'styles/subscriptions';
import Link from 'component/link';
import _ from 'lodash';
const suggestedPageSize = 24;
const softLimit = 2400;
class SuggestedSubscriptionsGrid extends React.PureComponent {
state = {
currentPage: 1,
options: {},
};
componentDidMount() {
const { claimSearch, followedTags, showNsfwContent } = this.props;
buildClaimSearchOptions() {
const { showNsfwContent } = this.props;
const { currentPage } = this.state;
const options = {
page: 1,
page_size: 99,
no_totals: true,
page: currentPage,
page_size: suggestedPageSize,
claim_type: 'channel',
order_by: ['trending_global', 'trending_mixed'],
order_by: [Constants.ORDER_BY_EFFECTIVE_AMOUNT],
};
if (!showNsfwContent) {
options.not_tags = MATURE_TAGS;
}
this.setState({ options });
return options;
}
doClaimSearch() {
const { claimSearch } = this.props;
const options = this.buildClaimSearchOptions();
claimSearch(options);
}
render() {
const { claimSearchByQuery, suggested, inModal, loading, navigation } = this.props;
const claimSearchKey = createNormalizedClaimSearchKey(this.state.options);
const claimSearchUris = claimSearchByQuery[claimSearchKey];
handleVerticalEndReached = () => {
// fetch more content
const { claimSearchByQuery, lastPageReached } = this.props;
if (loading) {
return (
<View style={subscriptionsStyle.centered}>
<ActivityIndicator size="large" color={Colors.NextLbryGreen} />
</View>
);
const options = this.buildClaimSearchOptions();
const claimSearchKey = createNormalizedClaimSearchKey(options);
const uris = claimSearchByQuery[claimSearchKey];
if (
lastPageReached[claimSearchKey] ||
((uris.length > 0 && uris.length < suggestedPageSize) || uris.length >= softLimit)
) {
return;
}
this.setState({ currentPage: this.state.currentPage + 1 }, () => this.doClaimSearch());
};
componentDidMount() {
const { claimSearch, followedTags, showNsfwContent } = this.props;
this.doClaimSearch();
}
render() {
const { claimSearchByQuery, suggested, inModal, navigation } = this.props;
const options = this.buildClaimSearchOptions();
const claimSearchKey = createNormalizedClaimSearchKey(options);
const claimSearchUris = claimSearchByQuery[claimSearchKey];
return (
<FlatGrid
horizontal
initialNumToRender={18}
maxToRenderPerBatch={24}
initialNumToRender={24}
maxToRenderPerBatch={48}
removeClippedSubviews
itemDimension={120}
spacing={2}
@ -61,6 +87,8 @@ class SuggestedSubscriptionsGrid extends React.PureComponent {
renderItem={({ item, index }) => (
<SuggestedSubscriptionItem key={item} uri={normalizeURI(item)} navigation={navigation} />
)}
onEndReached={this.handleVerticalEndReached}
onEndReachedThreshold={0.2}
/>
);
}

View file

@ -30,7 +30,7 @@ export default class Tag extends React.PureComponent {
};
render() {
const { name, onPress, style, type, truncate } = this.props;
const { name, numberOfLines, onPress, style, type, truncate } = this.props;
let styles = [];
if (style) {
@ -50,7 +50,9 @@ export default class Tag extends React.PureComponent {
return (
<TouchableOpacity style={styles} onPress={onPress || this.onPressDefault}>
<View style={tagStyle.content}>
<Text style={tagStyle.text}>{truncate ? formatTagName(name) : name}</Text>
<Text style={tagStyle.text} numberOfLines={numberOfLines}>
{truncate ? formatTagName(name) : name}
</Text>
{type && <Icon style={tagStyle.icon} name={type === 'add' ? 'plus' : 'times'} size={8} />}
</View>
</TouchableOpacity>

View file

@ -7,14 +7,13 @@ import {
selectSubscriptionClaims,
selectSubscriptions,
selectIsFetchingSubscriptions,
selectIsFetchingSuggested,
selectSuggestedChannels,
selectUnreadSubscriptions,
selectViewMode,
selectFirstRunCompleted,
selectShowSuggestedSubs,
} from 'lbryinc';
import { doToast } from 'lbry-redux';
import { doToast, selectFetchingClaimSearch } from 'lbry-redux';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { doSetClientSetting, doSetTimeItem } from 'redux/actions/settings';
import { makeSelectClientSetting, selectTimeItem } from 'redux/selectors/settings';
@ -25,7 +24,7 @@ import SubscriptionsPage from './view';
const select = state => ({
currentRoute: selectCurrentRoute(state),
loading: selectIsFetchingSubscriptions(state),
loadingSuggested: selectIsFetchingSuggested(state),
loadingSuggested: selectFetchingClaimSearch(state),
subscribedChannels: selectSubscriptions(state),
suggestedChannels: selectSuggestedChannels(state),
subscriptionsViewMode: makeSelectClientSetting(Constants.SETTING_SUBSCRIPTIONS_VIEW_MODE)(state),

View file

@ -178,7 +178,9 @@ class SubscriptionsPage extends React.PureComponent {
<UriBar navigation={navigation} belowOverlay={this.state.showSortPicker} />
<View style={subscriptionsStyle.titleRow}>
<Text style={subscriptionsStyle.pageTitle}>
{hasSubscriptions ? __('Channels you follow') : __('Find Channels to follow')}
{hasSubscriptions && !this.state.showingSuggestedSubs
? __('Channels you follow')
: __('Find Channels to follow')}
</Text>
</View>
{!this.state.showingSuggestedSubs && hasSubscriptions && (
@ -239,29 +241,31 @@ class SubscriptionsPage extends React.PureComponent {
<Text style={subscriptionsStyle.infoText}>
{__('LBRY works better if you find and follow at least 5 creators you like.')}
</Text>
<Button
style={subscriptionsStyle.suggestedDoneButton}
text={
numberOfSubscriptions < 5
? __('%remaining% more...', { remaining: 5 - numberOfSubscriptions })
: __('Done')
}
onPress={() => {
if (!hasSubscriptions) {
notify({ message: __('Tap on any channel to follow') });
} else {
this.setState({ showingSuggestedSubs: false });
}
}}
/>
</View>
<View style={subscriptionsStyle.mainSuggested}>
<SuggestedSubscriptionsGrid navigation={navigation} />
</View>
<Button
style={subscriptionsStyle.suggestedDoneButton}
text={
numberOfSubscriptions < 5
? __('%remaining% more...', { remaining: 5 - numberOfSubscriptions })
: __('Done')
}
onPress={() => {
if (!hasSubscriptions) {
notify({ message: __('Tap on any channel to follow') });
} else {
this.setState({ showingSuggestedSubs: false });
}
}}
/>
{loadingSuggested && (
<View style={subscriptionsStyle.centered}>
<ActivityIndicator size="large" colors={Colors.NextLbryGreen} style={subscriptionsStyle.loading} />
</View>
<ActivityIndicator size="small" color={Colors.White} style={subscriptionsStyle.suggestedLoading} />
)}
{!loadingSuggested && <SuggestedSubscriptionsGrid navigation={navigation} />}
</View>
)}

View file

@ -41,7 +41,6 @@ const subscriptionsStyle = StyleSheet.create({
fontSize: 16,
marginTop: 8,
marginBottom: 8,
flex: 0.7,
},
infoArea: {
flexDirection: 'row',
@ -195,7 +194,7 @@ const subscriptionsStyle = StyleSheet.create({
marginBottom: 16,
marginLeft: 16,
marginRight: 16,
width: 120,
height: 120,
},
suggestedItemThumbnailContainer: {
width: 70,
@ -275,10 +274,15 @@ const subscriptionsStyle = StyleSheet.create({
},
suggestedDoneButton: {
backgroundColor: Colors.LbryGreen,
margin: 16,
},
mainSuggested: {
flex: 1,
},
suggestedLoading: {
position: 'absolute',
right: 8,
top: 8,
zIndex: 100,
right: 24,
bottom: 22,
},
});