Compare commits

...

2 commits

Author SHA1 Message Date
Akinwale Ariwodola
1290b19c19 update page layout 2020-04-01 16:17:09 +01:00
Akinwale Ariwodola
f16d068a7d Editor's Choice page 2020-04-01 15:59:37 +01:00
10 changed files with 283 additions and 5 deletions

@ -1 +1 @@
Subproject commit ff30e7f6a4358fd997a9e6d9f75bfe6959eafcb6 Subproject commit cc3055f1c98c4dd5e5bbccdd9d4a39a5a37fdf82

View file

@ -4,6 +4,7 @@ import ChannelCreatorPage from 'page/channelCreator';
import DiscoverPage from 'page/discover'; import DiscoverPage from 'page/discover';
import DownloadsPage from 'page/downloads'; import DownloadsPage from 'page/downloads';
import DrawerContent from 'component/drawerContent'; import DrawerContent from 'component/drawerContent';
import EditorsChoicePage from 'page/editorsChoice';
import FilePage from 'page/file'; import FilePage from 'page/file';
import LiteFilePage from 'page/liteFile'; import LiteFilePage from 'page/liteFile';
import FirstRunScreen from 'page/firstRun'; import FirstRunScreen from 'page/firstRun';
@ -164,6 +165,13 @@ const drawer = createDrawerNavigator(
drawerIcon: ({ tintColor }) => <Icon name="home" size={drawerIconSize} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => <Icon name="home" size={drawerIconSize} style={{ color: tintColor }} />,
}, },
}, },
EditorsChoice: {
screen: EditorsChoicePage,
navigationOptions: {
title: "Editors' Choice",
drawerIcon: ({ tintColor }) => <Icon name="star" size={drawerIconSize} style={{ color: tintColor }} />,
},
},
Discover: { Discover: {
screen: DiscoverPage, screen: DiscoverPage,
navigationOptions: ({ navigation }) => ({ navigationOptions: ({ navigation }) => ({

View file

@ -3,6 +3,7 @@ import NavigationActions from 'react-navigation';
import { ActivityIndicator, FlatList, Text, TouchableOpacity, View } from 'react-native'; import { ActivityIndicator, FlatList, Text, TouchableOpacity, View } from 'react-native';
import { MATURE_TAGS, normalizeURI, createNormalizedClaimSearchKey } from 'lbry-redux'; import { MATURE_TAGS, normalizeURI, createNormalizedClaimSearchKey } from 'lbry-redux';
import _ from 'lodash'; import _ from 'lodash';
import EditorsChoiceItem from 'component/editorsChoiceItem';
import FileItem from 'component/fileItem'; import FileItem from 'component/fileItem';
import FileListItem from 'component/fileListItem'; import FileListItem from 'component/fileListItem';
import Icon from 'react-native-vector-icons/FontAwesome5'; import Icon from 'react-native-vector-icons/FontAwesome5';
@ -72,7 +73,7 @@ class ClaimList extends React.PureComponent {
buildClaimSearchOptions() { buildClaimSearchOptions() {
const { orderBy, channelIds, showNsfwContent, tags, time } = this.props; const { orderBy, channelIds, showNsfwContent, tags, time } = this.props;
const { currentPage, subscriptionsView } = this.state; const { currentPage } = this.state;
const options = { const options = {
order_by: orderBy, order_by: orderBy,
@ -101,7 +102,7 @@ class ClaimList extends React.PureComponent {
return `>${Math.floor( return `>${Math.floor(
moment() moment()
.subtract(1, time) .subtract(1, time)
.unix() .unix(),
)}`; )}`;
}; };
@ -120,7 +121,7 @@ class ClaimList extends React.PureComponent {
const uris = claimSearchByQuery[claimSearchKey]; const uris = claimSearchByQuery[claimSearchKey];
if ( if (
lastPageReached[claimSearchKey] || lastPageReached[claimSearchKey] ||
((uris.length > 0 && uris.length < Constants.DEFAULT_PAGE_SIZE) || uris.length >= softLimit) (uris.length > 0 && uris.length < Constants.DEFAULT_PAGE_SIZE) || uris.length >= softLimit
) { ) {
return; return;
} }
@ -174,6 +175,12 @@ class ClaimList extends React.PureComponent {
); );
}; };
renderEditorsChoiceItem = ({ item }) => {
const { navigation } = this.props;
return <EditorsChoiceItem style={discoverStyle.fileItem} key={item} uri={normalizeURI(item)} />;
};
renderHorizontalItem = ({ item }) => { renderHorizontalItem = ({ item }) => {
const { navigation } = this.props; const { navigation } = this.props;
@ -195,6 +202,7 @@ class ClaimList extends React.PureComponent {
render() { render() {
const { const {
ListHeaderComponent, ListHeaderComponent,
editorsChoice,
loading, loading,
morePlaceholder, morePlaceholder,
navigation, navigation,
@ -226,7 +234,7 @@ class ClaimList extends React.PureComponent {
initialNumToRender={10} initialNumToRender={10}
maxToRenderPerBatch={20} maxToRenderPerBatch={20}
removeClippedSubviews removeClippedSubviews
renderItem={this.renderVerticalItem} renderItem={editorsChoice ? this.renderEditorsChoiceItem : this.renderVerticalItem}
data={uris} data={uris}
keyExtractor={(item, index) => item} keyExtractor={(item, index) => item}
onEndReached={this.handleVerticalEndReached} onEndReached={this.handleVerticalEndReached}

View file

@ -12,6 +12,7 @@ import { formatUsd } from 'utils/helper';
const groupedMenuItems = { const groupedMenuItems = {
'Find content': [ 'Find content': [
{ icon: 'heart', solid: true, label: 'Following', route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS }, { icon: 'heart', solid: true, label: 'Following', route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS },
{ icon: 'star', solid: true, label: "Editor's Choice", route: Constants.DRAWER_ROUTE_EDITORS_CHOICE },
{ icon: 'hashtag', label: 'Your Tags', route: Constants.DRAWER_ROUTE_DISCOVER }, { icon: 'hashtag', label: 'Your Tags', route: Constants.DRAWER_ROUTE_DISCOVER },
{ icon: 'globe-americas', label: 'All Content', route: Constants.DRAWER_ROUTE_TRENDING }, { icon: 'globe-americas', label: 'All Content', route: Constants.DRAWER_ROUTE_TRENDING },
], ],

View file

@ -0,0 +1,22 @@
import { connect } from 'react-redux';
import {
doResolveUri,
makeSelectClaimForUri,
makeSelectMetadataForUri,
makeSelectTitleForUri,
makeSelectThumbnailForUri,
} from 'lbry-redux';
import EditorsChoiceItem from './view';
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
metadata: makeSelectMetadataForUri(props.uri)(state),
title: makeSelectTitleForUri(props.uri)(state),
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
});
const perform = dispatch => ({
resolveUri: uri => dispatch(doResolveUri(uri)),
});
export default connect(select, perform)(EditorsChoiceItem);

View file

@ -0,0 +1,67 @@
import React from 'react';
import { normalizeURI, parseURI } from 'lbry-redux';
import { ActivityIndicator, Platform, 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 Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import DateTime from 'component/dateTime';
import FastImage from 'react-native-fast-image';
import FileItemMedia from 'component/fileItemMedia';
import FilePrice from 'component/filePrice';
import Icon from 'react-native-vector-icons/FontAwesome5';
import Link from 'component/link';
import NsfwOverlay from 'component/nsfwOverlay';
import ProgressBar from 'component/progressBar';
import editorsChoiceStyle from 'styles/editorsChoice';
class EditorsChoiceItem extends React.PureComponent {
componentDidMount() {
const { claim, resolveUri, uri, batchResolve } = this.props;
if (!claim && !batchResolve) {
resolveUri(uri);
}
}
defaultOnPress = () => {
const { autoplay, claim, navigation, uri } = this.props;
navigateToUri(navigation, uri, { autoplay }, false, claim ? claim.permanent_url : null);
};
onPressHandler = () => {
const { claim, onPress } = this.props;
if (onPress) {
onPress(claim);
} else {
this.defaultOnPress();
}
};
render() {
const { metadata, title, thumbnail } = this.props;
return (
<TouchableOpacity style={editorsChoiceStyle.item}>
<Text style={editorsChoiceStyle.title} numberOfLines={1}>
{title}
</Text>
<View style={editorsChoiceStyle.itemRow}>
<FastImage
style={editorsChoiceStyle.thumbnail}
resizeMode={FastImage.resizeMode.cover}
source={{ uri: thumbnail }}
/>
<View style={editorsChoiceStyle.detailsContainer}>
<Text style={editorsChoiceStyle.description} numberOfLines={5}>
{metadata.description ? metadata.description : __('No description available')}
</Text>
</View>
</View>
</TouchableOpacity>
);
}
}
export default EditorsChoiceItem;

View file

@ -81,6 +81,7 @@ const Constants = {
PAGE_WALLET: 'wallet', PAGE_WALLET: 'wallet',
DRAWER_ROUTE_DISCOVER: 'Discover', DRAWER_ROUTE_DISCOVER: 'Discover',
DRAWER_ROUTE_EDITORS_CHOICE: 'EditorsChoice',
DRAWER_ROUTE_TRENDING: 'Trending', DRAWER_ROUTE_TRENDING: 'Trending',
DRAWER_ROUTE_SUBSCRIPTIONS: 'Subscriptions', DRAWER_ROUTE_SUBSCRIPTIONS: 'Subscriptions',
DRAWER_ROUTE_MY_LBRY: 'Downloads', DRAWER_ROUTE_MY_LBRY: 'Downloads',
@ -159,6 +160,7 @@ export default Constants;
export const DrawerRoutes = [ export const DrawerRoutes = [
Constants.DRAWER_ROUTE_DISCOVER, Constants.DRAWER_ROUTE_DISCOVER,
Constants.DRAWER_ROUTE_EDITORS_CHOICE,
Constants.DRAWER_ROUTE_TRENDING, Constants.DRAWER_ROUTE_TRENDING,
Constants.DRAWER_ROUTE_SUBSCRIPTIONS, Constants.DRAWER_ROUTE_SUBSCRIPTIONS,
Constants.DRAWER_ROUTE_MY_LBRY, Constants.DRAWER_ROUTE_MY_LBRY,

View file

@ -0,0 +1,16 @@
import { connect } from 'react-redux';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { selectCurrentRoute } from 'redux/selectors/drawer';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import EditorsChoicePage from './view';
const select = state => ({
currentRoute: selectCurrentRoute(state),
});
const perform = dispatch => ({
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_EDITORS_CHOICE)),
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
});
export default connect(select, perform)(EditorsChoicePage);

View file

@ -0,0 +1,90 @@
import React from 'react';
import { ActivityIndicator, NativeModules, FlatList, Text, TouchableOpacity, ScrollView, View } from 'react-native';
import { DEFAULT_FOLLOWED_TAGS, normalizeURI } from 'lbry-redux';
import { formatTagTitle, getOrderBy } from 'utils/helper';
import AsyncStorage from '@react-native-community/async-storage';
import moment from 'moment';
import ClaimList from 'component/claimList';
import FileItem from 'component/fileItem';
import Icon from 'react-native-vector-icons/FontAwesome5';
import discoverStyle from 'styles/discover';
import fileListStyle from 'styles/fileList';
import Colors from 'styles/colors';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import FloatingWalletBalance from 'component/floatingWalletBalance';
import Link from 'component/link';
import ModalPicker from 'component/modalPicker';
import SdkLoadingStatus from 'component/sdkLoadingStatus';
import UriBar from 'component/uriBar';
import editorsChoiceStyle from 'styles/editorsChoice';
class EditorsChoicePage extends React.PureComponent {
onComponentFocused = () => {
const { pushDrawerStack, setPlayerVisible } = this.props;
pushDrawerStack();
setPlayerVisible();
NativeModules.Firebase.setCurrentScreen('EditorsChoice');
};
componentDidMount() {
this.onComponentFocused();
}
componentWillReceiveProps(nextProps) {
const { currentRoute } = nextProps;
const { currentRoute: prevRoute } = this.props;
if (Constants.DRAWER_ROUTE_EDITORS_CHOICE === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
}
}
render() {
const { navigation } = this.props;
return (
<View style={editorsChoiceStyle.container}>
<UriBar navigation={navigation} />
<ScrollView style={editorsChoiceStyle.categories} contentContainerStyle={editorsChoiceStyle.categoriesContent}>
<Text style={editorsChoiceStyle.category}>{__('Short Films')}</Text>
<ClaimList
style={editorsChoiceStyle.claimList}
channelIds={['7056f8267188fc49cd3f7162b4115d9e3c8216f6']}
editorsChoice
navigation={navigation}
orientation={Constants.ORIENTATION_VERTICAL}
/>
<Text style={editorsChoiceStyle.category}>{__('Feature-Length Films')}</Text>
<ClaimList
style={editorsChoiceStyle.claimList}
channelIds={['7aad6f36f61da95cb02471fae55f736b28e3bca7']}
editorsChoice
navigation={navigation}
orientation={Constants.ORIENTATION_VERTICAL}
/>
<Text style={editorsChoiceStyle.category}>{__('Documentaries')}</Text>
<ClaimList
style={editorsChoiceStyle.claimList}
channelIds={['d57c606e11462e821d5596430c336b58716193bb']}
editorsChoice
navigation={navigation}
orientation={Constants.ORIENTATION_VERTICAL}
/>
<Text style={editorsChoiceStyle.category}>{__('Episodic Content')}</Text>
<ClaimList
style={editorsChoiceStyle.claimList}
channelIds={['ea5fc1bd3e1335776fe2641a539a47850606d7db']}
editorsChoice
navigation={navigation}
orientation={Constants.ORIENTATION_VERTICAL}
/>
</ScrollView>
</View>
);
}
}
export default EditorsChoicePage;

View file

@ -0,0 +1,64 @@
import { Dimensions, PixelRatio, StyleSheet } from 'react-native';
import { mediaWidth, mediaHeight } from './discover';
import Colors from './colors';
const screenDimension = Dimensions.get('window');
const screenWidth = screenDimension.width;
const screenHeight = screenDimension.height;
const screenWidthPixels = PixelRatio.getPixelSizeForLayoutSize(screenWidth);
const screenHeightPixels = PixelRatio.getPixelSizeForLayoutSize(screenHeight);
const verticalAdjust = screenHeightPixels > 1280 && screenHeightPixels <= 1920 ? 6 : 0;
const thumbnailWidth = screenWidthPixels <= 720 ? 144 : 156;
// taller thumbnails
const thumbnailHeight = (screenWidth / screenHeight) * thumbnailWidth - verticalAdjust;
const editorsChoiceStyle = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.PageBackground,
},
categories: {
marginTop: 60,
},
categoriesContent: {
padding: 16,
},
item: {
flex: 1,
marginTop: 8,
marginBottom: 12,
},
itemRow: {
alignItems: 'center',
flexDirection: 'row',
},
category: {
fontFamily: 'Inter-SemiBold',
fontSize: 20,
color: Colors.LbryGreen,
},
thumbnail: {
width: thumbnailWidth,
height: thumbnailHeight,
marginRight: screenWidthPixels <= 720 ? 10 : 12,
alignItems: 'center',
justifyContent: 'center',
},
detailsContainer: {
flex: 1,
paddingLeft: 2,
paddingRight: 2,
},
title: {
fontFamily: 'Inter-SemiBold',
fontSize: 16,
marginBottom: 4,
},
description: {
fontFamily: 'Inter-Regular',
fontSize: 12,
marginTop: 2,
},
});
export default editorsChoiceStyle;