Following rework (#124)

* make following the default page. add suggested grd.
* suggested grid vertical scrolling. semi-infinite scroll
* search and related content fixes
This commit is contained in:
Akinwale Ariwodola 2020-02-24 15:20:03 +01:00 committed by GitHub
parent 1f649b9d38
commit f05d357fa7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 359 additions and 100 deletions

8
package-lock.json generated
View file

@ -7067,8 +7067,8 @@
}
},
"lbry-redux": {
"version": "github:lbryio/lbry-redux#1de1d534c982db913f145a6171f39d7b8ebd61af",
"from": "github:lbryio/lbry-redux#1de1d534c982db913f145a6171f39d7b8ebd61af",
"version": "github:lbryio/lbry-redux#5c874e921769093428966fa7ecdf723719cb9067",
"from": "github:lbryio/lbry-redux#5c874e921769093428966fa7ecdf723719cb9067",
"requires": {
"proxy-polyfill": "0.1.6",
"reselect": "^3.0.0",
@ -7076,8 +7076,8 @@
}
},
"lbryinc": {
"version": "github:lbryio/lbryinc#138a053754ec8e3da8e9bf153d32f527c962f25c",
"from": "github:lbryio/lbryinc#138a053754ec8e3da8e9bf153d32f527c962f25c",
"version": "github:lbryio/lbryinc#0dc8829a319a708f45a855765f70a193ccb72676",
"from": "github:lbryio/lbryinc#0dc8829a319a708f45a855765f70a193ccb72676",
"requires": {
"reselect": "^3.0.0"
}

View file

@ -12,8 +12,8 @@
"base-64": "^0.1.0",
"@expo/vector-icons": "^8.1.0",
"gfycat-style-urls": "^1.0.3",
"lbry-redux": "lbryio/lbry-redux#1de1d534c982db913f145a6171f39d7b8ebd61af",
"lbryinc": "lbryio/lbryinc#138a053754ec8e3da8e9bf153d32f527c962f25c",
"lbry-redux": "lbryio/lbry-redux#5c874e921769093428966fa7ecdf723719cb9067",
"lbryinc": "lbryio/lbryinc#0dc8829a319a708f45a855765f70a193ccb72676",
"lodash": ">=4.17.11",
"merge": ">=1.2.1",
"moment": "^2.22.1",

View file

@ -88,12 +88,13 @@ const menuNavigationButton = navigation => (
const discoverStack = createStackNavigator(
{
Discover: {
screen: DiscoverPage,
navigationOptions: ({ navigation }) => ({
title: 'Explore',
Subscriptions: {
screen: SubscriptionsPage,
navigationOptions: {
title: 'Following',
header: null,
}),
drawerIcon: ({ tintColor }) => <Icon name="heart" solid size={drawerIconSize} style={{ color: tintColor }} />,
},
},
File: {
screen: FilePage,
@ -160,10 +161,17 @@ const drawer = createDrawerNavigator(
DiscoverStack: {
screen: discoverStack,
navigationOptions: {
title: 'Explore',
title: 'Following',
drawerIcon: ({ tintColor }) => <Icon name="home" size={drawerIconSize} style={{ color: tintColor }} />,
},
},
Discover: {
screen: DiscoverPage,
navigationOptions: ({ navigation }) => ({
title: 'Your Tags',
header: null,
}),
},
Trending: {
screen: TrendingPage,
navigationOptions: {
@ -171,13 +179,6 @@ const drawer = createDrawerNavigator(
drawerIcon: ({ tintColor }) => <Icon name="fire" size={drawerIconSize} style={{ color: tintColor }} />,
},
},
Subscriptions: {
screen: SubscriptionsPage,
navigationOptions: {
title: 'Subscriptions',
drawerIcon: ({ tintColor }) => <Icon name="heart" solid size={drawerIconSize} style={{ color: tintColor }} />,
},
},
WalletStack: {
screen: walletStack,
navigationOptions: {

View file

@ -9,8 +9,8 @@ import discoverStyle from 'styles/discover';
const groupedMenuItems = {
'Find content': [
{ icon: 'hashtag', label: 'Your Tags', route: Constants.DRAWER_ROUTE_DISCOVER },
{ icon: 'heart', solid: true, label: 'Following', route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS },
{ icon: 'hashtag', label: 'Your Tags', route: Constants.DRAWER_ROUTE_DISCOVER },
{ icon: 'globe-americas', label: 'All Content', route: Constants.DRAWER_ROUTE_TRENDING },
],
'Your content': [
@ -145,7 +145,7 @@ class DrawerContent extends React.PureComponent {
const focused =
activeItemKey === item.route ||
(activeItemKey === Constants.FULL_ROUTE_NAME_DISCOVER &&
item.route === Constants.DRAWER_ROUTE_DISCOVER) ||
item.route === Constants.DRAWER_ROUTE_SUBSCRIPTIONS) ||
(activeItemKey === Constants.FULL_ROUTE_NAME_WALLET &&
item.route === Constants.DRAWER_ROUTE_WALLET);
return (

View file

@ -1,4 +1,9 @@
import { connect } from 'react-redux';
import { selectFetchingClaimSearch } from 'lbry-redux';
import ModalSuggestedSubscriptions from './view';
export default connect()(ModalSuggestedSubscriptions);
const select = state => ({
loadingSuggested: selectFetchingClaimSearch(state),
});
export default connect(select)(ModalSuggestedSubscriptions);

View file

@ -1,23 +1,26 @@
import React from 'react';
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
import { ActivityIndicator, ScrollView, Text, TouchableOpacity, View } from 'react-native';
import modalStyle from 'styles/modal';
import subscriptionsStyle from 'styles/subscriptions';
import Button from 'component/button';
import Colors from 'styles/colors';
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
import SuggestedSubscriptionsGrid from 'component/suggestedSubscriptionsGrid';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import Icon from 'react-native-vector-icons/FontAwesome5';
export default class ModalSuggestedSubcriptions extends React.PureComponent {
render() {
const { navigation, onDonePress, onOverlayPress } = this.props;
const { loadingSuggested, navigation, onDonePress, onOverlayPress } = this.props;
return (
<TouchableOpacity style={modalStyle.overlay} activeOpacity={1} onPress={onOverlayPress}>
<TouchableOpacity style={[modalStyle.container, subscriptionsStyle.modalContainer]} activeOpacity={1}>
<SuggestedSubscriptions inModal navigation={navigation} />
<View style={modalStyle.buttons}>
<Button style={modalStyle.doneButton} text={__('Done')} onPress={onDonePress} />
<SuggestedSubscriptionsGrid inModal navigation={navigation} />
<View style={modalStyle.wideButtons}>
<Button style={modalStyle.wideDoneButton} text={__('Done')} onPress={onDonePress} />
{loadingSuggested && (
<ActivityIndicator size="small" color={Colors.White} style={subscriptionsStyle.modalLoading} />
)}
</View>
</TouchableOpacity>
</TouchableOpacity>

View file

@ -0,0 +1,18 @@
import { connect } from 'react-redux';
import { doChannelSubscribe, doChannelUnsubscribe, selectSubscriptions, makeSelectIsSubscribed } from 'lbryinc';
import { doToast } from 'lbry-redux';
import SubscribeButtonOverlay from './view';
const select = (state, props) => ({
subscriptions: selectSubscriptions(state),
isSubscribed: makeSelectIsSubscribed(props.uri, true)(state),
});
export default connect(
select,
{
doChannelSubscribe,
doChannelUnsubscribe,
doToast,
},
)(SubscribeButtonOverlay);

View file

@ -0,0 +1,36 @@
import React from 'react';
import { normalizeURI, parseURI } from 'lbry-redux';
import { NativeModules, Text, View, TouchableOpacity } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome5';
import Button from 'component/button';
import Colors from 'styles/colors';
class SubscribeButtonOverlay extends React.PureComponent {
handlePress = () => {
const { claim, isSubscribed, doChannelSubscribe, doChannelUnsubscribe, uri } = this.props;
if (!claim) {
return;
}
const subscriptionHandler = isSubscribed ? doChannelUnsubscribe : doChannelSubscribe;
const { name: claimName } = claim;
subscriptionHandler({
channelName: claimName,
uri: normalizeURI(uri),
});
};
render() {
const { uri, isSubscribed, style } = this.props;
let styles = style.length ? style : [style];
return (
<TouchableOpacity style={styles} opacity={0.7} onPress={this.handlePress}>
{isSubscribed && <Icon name={'heart'} size={20} solid color={Colors.Red} />}
{!isSubscribed && <Icon name={'heart'} size={20} color={Colors.Red} />}
</TouchableOpacity>
);
}
}
export default SubscribeButtonOverlay;

View file

@ -6,6 +6,7 @@ import {
makeSelectTitleForUri,
makeSelectIsUriResolving,
} from 'lbry-redux';
import { doChannelSubscribe, doChannelUnsubscribe, makeSelectIsSubscribed } from 'lbryinc';
import SuggestedSubscriptionItem from './view';
const select = (state, props) => ({
@ -13,13 +14,16 @@ const select = (state, props) => ({
title: makeSelectTitleForUri(props.uri)(state),
claim: makeSelectClaimForUri(props.uri)(state),
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
isSubscribed: makeSelectIsSubscribed(props.uri, true)(state),
});
const perform = dispatch => ({
resolveUri: uri => dispatch(doResolveUri(uri)),
subscribe: subscription => doChannelSubscribe(subscription),
unsubscribe: subscription => doChannelUnsubscribe(subscription),
});
export default connect(
select,
perform
perform,
)(SuggestedSubscriptionItem);

View file

@ -1,13 +1,13 @@
import React from 'react';
import { buildURI, normalizeURI } from 'lbry-redux';
import { ActivityIndicator, FlatList, Image, Text, View } from 'react-native';
import { ActivityIndicator, FlatList, Image, Text, TouchableOpacity, View } from 'react-native';
import { navigateToUri } from 'utils/helper';
import Colors from 'styles/colors';
import ChannelIconItem from 'component/channelIconItem';
import channelIconStyle from 'styles/channelIcon';
import discoverStyle from 'styles/discover';
import FileItem from 'component/fileItem';
import SubscribeButton from 'component/subscribeButton';
import SubscribeButtonOverlay from 'component/subscribeButtonOverlay';
import subscriptionsStyle from 'styles/subscriptions';
import Link from 'component/link';
import Tag from 'component/tag';
@ -31,6 +31,7 @@ class SuggestedSubscriptionItem extends React.PureComponent {
render() {
const { claim, isResolvingUri, navigation, thumbnail, title, uri } = this.props;
let shortUrl, tags;
if (claim) {
shortUrl = claim.short_url;
@ -49,7 +50,7 @@ class SuggestedSubscriptionItem extends React.PureComponent {
}
return (
<View style={subscriptionsStyle.suggestedItem}>
<TouchableOpacity style={subscriptionsStyle.suggestedItem}>
<View style={[subscriptionsStyle.suggestedItemThumbnailContainer, this.state.autoStyle]}>
{hasThumbnail && (
<Image style={subscriptionsStyle.suggestedItemThumbnail} resizeMode={'cover'} source={{ uri: thumbnail }} />
@ -62,35 +63,37 @@ class SuggestedSubscriptionItem extends React.PureComponent {
</View>
<View style={subscriptionsStyle.suggestedItemDetails}>
{title && (
<Text style={subscriptionsStyle.suggestedItemTitle} numberOfLines={1}>
{title}
</Text>
)}
{claim && (
<Link
style={subscriptionsStyle.suggestedItemName}
numberOfLines={1}
text={claim.name}
onPress={() => navigateToUri(navigation, normalizeURI(shortUrl || uri), null, false, claim.permanent_url)}
/>
)}
<Text style={subscriptionsStyle.suggestedItemTitle} numberOfLines={2}>
{title || claim.name}
</Text>
{tags && (
<View style={subscriptionsStyle.suggestedItemTagList}>
{tags &&
tags
.slice(0, 3)
.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>
{claim && (
<SubscribeButton style={subscriptionsStyle.suggestedItemSubscribe} uri={normalizeURI(claim.permanent_url)} />
<SubscribeButtonOverlay
claim={claim}
style={subscriptionsStyle.suggestedItemSubscribeOverlay}
uri={normalizeURI(claim.permanent_url)}
/>
)}
</View>
</TouchableOpacity>
);
}
}

View file

@ -0,0 +1,30 @@
import { connect } from 'react-redux';
import {
doClaimSearch,
selectFetchingClaimSearch,
selectClaimSearchByQuery,
selectClaimSearchByQueryLastPageReached,
selectFollowedTags,
} from 'lbry-redux';
import { selectSubscriptions, selectSuggestedChannels, selectIsFetchingSuggested } from 'lbryinc';
import { selectShowNsfw } from 'redux/selectors/settings';
import SuggestedSubscriptionsGrid from './view';
const select = state => ({
followedTags: selectFollowedTags(state),
subscriptions: selectSubscriptions(state),
suggested: selectSuggestedChannels(state),
loading: selectIsFetchingSuggested(state) || selectFetchingClaimSearch(state),
claimSearchByQuery: selectClaimSearchByQuery(state),
lastPageReached: selectClaimSearchByQueryLastPageReached(state),
showNsfwContent: selectShowNsfw(state),
});
const perform = dispatch => ({
claimSearch: options => dispatch(doClaimSearch(options)),
});
export default connect(
select,
perform,
)(SuggestedSubscriptionsGrid);

View file

@ -0,0 +1,100 @@
import React from 'react';
import { ActivityIndicator, SectionList, Text, View } from 'react-native';
import { MATURE_TAGS, createNormalizedClaimSearchKey, normalizeURI } from 'lbry-redux';
import { navigateToUri } from 'utils/helper';
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: {},
};
buildClaimSearchOptions() {
const { showNsfwContent, subscriptions } = this.props;
const { currentPage } = this.state;
const options = {
no_totals: true,
page: currentPage,
page_size: suggestedPageSize,
claim_type: 'channel',
order_by: [Constants.ORDER_BY_EFFECTIVE_AMOUNT],
};
if (!showNsfwContent) {
options.not_tags = MATURE_TAGS;
}
/* if (subscriptions && subscriptions.length > 0) {
options.not_channel_ids = subscriptions.map(subscription => subscription.uri.split('#')[1]);
} */
return options;
}
doClaimSearch() {
const { claimSearch } = this.props;
const options = this.buildClaimSearchOptions();
claimSearch(options);
}
handleVerticalEndReached = () => {
// fetch more content
const { claimSearchByQuery, lastPageReached } = this.props;
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
initialNumToRender={24}
maxToRenderPerBatch={48}
removeClippedSubviews
itemDimension={120}
spacing={2}
items={claimSearchUris}
style={inModal ? subscriptionsStyle.modalScrollContainer : subscriptionsStyle.scrollContainer}
contentContainerStyle={
inModal ? subscriptionsStyle.modalSuggestedScrollContent : subscriptionsStyle.suggestedScrollContent
}
renderItem={({ item, index }) => (
<SuggestedSubscriptionItem key={item} uri={normalizeURI(item)} navigation={navigation} />
)}
onEndReached={this.handleVerticalEndReached}
onEndReachedThreshold={0.2}
/>
);
}
}
export default SuggestedSubscriptionsGrid;

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

@ -64,9 +64,7 @@ class DiscoverPage extends React.PureComponent {
onComponentFocused = () => {
const { pushDrawerStack, setPlayerVisible, currentRoute } = this.props;
if (currentRoute === Constants.DRAWER_ROUTE_DISCOVER) {
pushDrawerStack();
}
pushDrawerStack();
NativeModules.Firebase.setCurrentScreen('Your tags');
setPlayerVisible();

View file

@ -26,10 +26,14 @@ const select = state => ({
query: selectSearchValue(state),
resolvingUris: selectResolvingUris(state),
showNsfwContent: selectShowNsfw(state),
uris: makeSelectSearchUris(makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state))(state),
results: makeSelectResolvedSearchResults(makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state))(state),
uris: makeSelectSearchUris(
makeSelectQueryWithOptions(null, { size: Constants.DEFAULT_PAGE_SIZE, isBackgroundSearch: false })(state),
)(state),
results: makeSelectResolvedSearchResults(
makeSelectQueryWithOptions(null, { size: Constants.DEFAULT_PAGE_SIZE, isBackgroundSearch: false })(state),
)(state),
lastPageReached: makeSelectResolvedSearchResultsLastPageReached(
makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state),
makeSelectQueryWithOptions(null, { size: Constants.DEFAULT_PAGE_SIZE, isBackgroundSearch: false })(state),
)(state),
});

View file

@ -7,13 +7,13 @@ import {
selectSubscriptionClaims,
selectSubscriptions,
selectIsFetchingSubscriptions,
selectIsFetchingSuggested,
selectSuggestedChannels,
selectUnreadSubscriptions,
selectViewMode,
selectFirstRunCompleted,
selectShowSuggestedSubs,
} from 'lbryinc';
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';
@ -24,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),
@ -41,6 +41,7 @@ const perform = dispatch => ({
doFetchMySubscriptions: () => dispatch(doFetchMySubscriptions()),
doFetchRecommendedSubscriptions: () => dispatch(doFetchRecommendedSubscriptions()),
doSetViewMode: viewMode => dispatch(doSetViewMode(viewMode)),
notify: data => dispatch(doToast(data)),
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SUBSCRIPTIONS)),
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
@ -49,5 +50,5 @@ const perform = dispatch => ({
export default connect(
select,
perform
perform,
)(SubscriptionsPage);

View file

@ -28,6 +28,7 @@ import ModalPicker from 'component/modalPicker';
import ModalSuggestedSubscriptions from 'component/modalSuggestedSubscriptions';
import SubscribedChannelList from 'component/subscribedChannelList';
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
import SuggestedSubscriptionsGrid from 'component/suggestedSubscriptionsGrid';
import UriBar from 'component/uriBar';
class SubscriptionsPage extends React.PureComponent {
@ -56,6 +57,7 @@ class SubscriptionsPage extends React.PureComponent {
onComponentFocused = () => {
const {
currentRoute,
doFetchMySubscriptions,
doFetchRecommendedSubscriptions,
doSetViewMode,
@ -64,12 +66,13 @@ class SubscriptionsPage extends React.PureComponent {
subscriptionsViewMode,
} = this.props;
pushDrawerStack();
if (currentRoute === Constants.DRAWER_ROUTE_SUBSCRIPTIONS) {
pushDrawerStack();
}
setPlayerVisible();
NativeModules.Firebase.setCurrentScreen('Subscriptions');
doFetchMySubscriptions();
doFetchRecommendedSubscriptions();
};
componentDidMount() {
@ -90,6 +93,15 @@ class SubscriptionsPage extends React.PureComponent {
this.setState({ currentSortByItem: item, orderBy: getOrderBy(item), showSortPicker: false });
};
shouldComponentUpdate(nextProps, nextState) {
const { showModalSuggestedSubs: prevShowModalSuggestedSubs } = this.state;
const { showModalSuggestedSubs } = this.state;
if (prevShowModalSuggestedSubs && showModalSuggestedSubs) {
return false;
}
return true;
}
handleTimeItemSelected = item => {
const { setTimeItem } = this.props;
setTimeItem(item);
@ -138,6 +150,7 @@ class SubscriptionsPage extends React.PureComponent {
timeItem,
unreadSubscriptions,
navigation,
notify,
} = this.props;
const { currentSortByItem, filteredChannels, showModalSuggestedSubs, showSortPicker, showTimePicker } = this.state;
@ -164,7 +177,11 @@ class SubscriptionsPage extends React.PureComponent {
<View style={subscriptionsStyle.container}>
<UriBar navigation={navigation} belowOverlay={this.state.showSortPicker} />
<View style={subscriptionsStyle.titleRow}>
<Text style={subscriptionsStyle.pageTitle}>{__('Channels you follow')}</Text>
<Text style={subscriptionsStyle.pageTitle}>
{hasSubscriptions && !this.state.showingSuggestedSubs
? __('Channels you follow')
: __('Find Channels to follow')}
</Text>
</View>
{!this.state.showingSuggestedSubs && hasSubscriptions && (
<View style={subscriptionsStyle.pickerRow}>
@ -190,7 +207,7 @@ class SubscriptionsPage extends React.PureComponent {
<Link
style={subscriptionsStyle.suggestedLink}
text={__('Suggested')}
text={__('Discover')}
onPress={() => this.setState({ showModalSuggestedSubs: true })}
/>
</View>
@ -220,39 +237,38 @@ class SubscriptionsPage extends React.PureComponent {
{this.state.showingSuggestedSubs && (
<View style={subscriptionsStyle.suggestedSubsContainer}>
{!hasSubscriptions && (
<View style={subscriptionsStyle.infoArea}>
<Text style={subscriptionsStyle.infoText}>
{__('You are not subscribed to any channels at the moment.')}
</Text>
</View>
)}
<View style={subscriptionsStyle.infoArea}>
<Text style={subscriptionsStyle.infoText}>
{__('LBRY works better if you follow at least 5 creators you like.')}
</Text>
</View>
{hasSubscriptions && (
<View style={subscriptionsStyle.infoArea}>
<Text style={subscriptionsStyle.infoText}>
You are currently subscribed to {numberOfSubscriptions} channel{numberOfSubscriptions > 1 ? 's' : ''}.
</Text>
<Button
style={subscriptionsStyle.button}
text={__('View my subscriptions')}
onPress={() => 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 && <SuggestedSubscriptions navigation={navigation} />}
</View>
)}
{!showSortPicker && !showTimePicker && !showModalSuggestedSubs && (
<FloatingWalletBalance navigation={navigation} />
)}
{showSortPicker && (
<ModalPicker
title={__('Sort content by')}

View file

@ -2,7 +2,7 @@ import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
const reducers = {};
const defaultState = {
stack: [{ route: Constants.DRAWER_ROUTE_DISCOVER, params: {} }], // Discover is always the first drawer route
stack: [{ route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS, params: {} }], // Following is always the first drawer route
lastRouteInStack: {},
playerVisible: false,
playerVisibleByUri: {},
@ -42,7 +42,7 @@ reducers[Constants.ACTION_PUSH_DRAWER_STACK] = (state, action) => {
if (lastRoute === Constants.DRAWER_ROUTE_PUBLISH_FORM && routeName === Constants.DRAWER_ROUTE_PUBLISH) {
canPushStack = false;
}
if (routeName === Constants.DRAWER_ROUTE_DISCOVER && newStack.length === 1) {
if (routeName === Constants.DRAWER_ROUTE_SUBSCRIPTIONS && newStack.length === 1) {
canPushStack = false;
}

View file

@ -37,12 +37,24 @@ const modalPickerStyle = StyleSheet.create({
bottom: 8,
position: 'absolute',
},
wideButtons: {
marginTop: 16,
left: 8,
bottom: 8,
right: 8,
position: 'absolute',
},
doneButton: {
alignSelf: 'flex-start',
backgroundColor: Colors.LbryGreen,
paddingLeft: 16,
paddingRight: 16,
},
wideDoneButton: {
backgroundColor: Colors.LbryGreen,
paddingLeft: 16,
paddingRight: 16,
},
});
export default modalPickerStyle;

View file

@ -38,11 +38,13 @@ const subscriptionsStyle = StyleSheet.create({
},
infoText: {
fontFamily: 'Inter-Regular',
fontSize: 16,
fontSize: 14,
marginTop: 8,
marginBottom: 8,
},
infoArea: {
flexDirection: 'row',
justifyContent: 'space-between',
marginLeft: 16,
marginRight: 16,
paddingBottom: 4,
@ -188,11 +190,11 @@ const subscriptionsStyle = StyleSheet.create({
justifyContent: 'center',
},
suggestedItem: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 16,
marginLeft: 16,
marginRight: 16,
height: 140,
},
suggestedItemThumbnailContainer: {
width: 70,
@ -209,30 +211,37 @@ const subscriptionsStyle = StyleSheet.create({
suggestedItemDetails: {
marginLeft: 16,
marginRight: 16,
flex: 0.8,
alignItems: 'center',
},
suggestedItemSubscribe: {
backgroundColor: Colors.White,
},
suggestedItemSubscribeOverlay: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
alignItems: 'center',
justifyContent: 'flex-end',
paddingBottom: 4,
height: 70,
},
suggestedItemTitle: {
fontFamily: 'Inter-Regular',
fontSize: 16,
marginBottom: 4,
width: '85%',
textAlign: 'center',
fontSize: 14,
marginTop: 4,
marginBottom: 2,
},
suggestedItemName: {
fontFamily: 'Inter-SemiBold',
fontSize: 14,
marginBottom: 4,
color: Colors.LbryGreen,
width: '95%',
},
suggestedItemTagList: {
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center',
},
suggestedSubTitle: {
fontFamily: 'Inter-Regular',
@ -266,6 +275,23 @@ const subscriptionsStyle = StyleSheet.create({
modalSuggestedScrollContent: {
paddingTop: 16,
},
suggestedDoneButton: {
backgroundColor: Colors.LbryGreen,
margin: 16,
},
mainSuggested: {
flex: 1,
},
suggestedLoading: {
position: 'absolute',
right: 24,
bottom: 22,
},
modalLoading: {
position: 'absolute',
right: 7,
bottom: 7,
},
});
export default subscriptionsStyle;