rework discovery views with new/top/trending sorting #25
38 changed files with 670 additions and 291 deletions
src
component
constants.jsindex.jspage
about
channel
discover
downloads
file
firstRun
publish
publishes
rewards
search
settings
splash
subscriptions
tag
transactionHistory
trending
verification
wallet
redux
styles
utils
|
@ -141,7 +141,7 @@ const drawer = createDrawerNavigator(
|
|||
Trending: {
|
||||
screen: TrendingPage,
|
||||
navigationOptions: {
|
||||
title: 'Trending',
|
||||
title: 'All Content',
|
||||
drawerIcon: ({ tintColor }) => <Icon name="fire" size={drawerIconSize} style={{ color: tintColor }} />,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -34,14 +34,14 @@ export default class Button extends React.PureComponent {
|
|||
}
|
||||
|
||||
let renderIcon = (
|
||||
<Icon name={icon} size={18} color={iconColor ? iconColor : 'light' === theme ? Colors.DarkGrey : Colors.White} />
|
||||
<Icon name={icon} size={16} color={iconColor || (theme === 'light' ? Colors.DarkGrey : Colors.White)} />
|
||||
);
|
||||
if (solid) {
|
||||
renderIcon = (
|
||||
<Icon
|
||||
name={icon}
|
||||
size={18}
|
||||
color={iconColor ? iconColor : 'light' === theme ? Colors.DarkGrey : Colors.White}
|
||||
size={16}
|
||||
color={iconColor || (theme === 'light' ? Colors.DarkGrey : Colors.White)}
|
||||
solid
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -21,17 +21,14 @@ class ClaimList extends React.PureComponent {
|
|||
state = {
|
||||
currentPage: 1, // initial page load is page 1
|
||||
subscriptionsView: false, // whether or not this claim list is for subscriptions
|
||||
trendingForAllView: false,
|
||||
lastPageReached: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { channelIds, trendingForAll } = this.props;
|
||||
const { channelIds } = this.props;
|
||||
|
||||
if (channelIds) {
|
||||
this.setState({ subscriptionsView: true });
|
||||
} else if (trendingForAll) {
|
||||
this.setState({ trendingForAllView: true });
|
||||
}
|
||||
|
||||
this.doClaimSearch();
|
||||
|
@ -44,18 +41,16 @@ class ClaimList extends React.PureComponent {
|
|||
searchByTags,
|
||||
tags: prevTags,
|
||||
channelIds: prevChannelIds,
|
||||
trendingForAll: prevTrendingForAll,
|
||||
time: prevTime,
|
||||
showNsfwContent,
|
||||
} = prevProps;
|
||||
const { claimSearchByQuery, orderBy, tags, channelIds, trendingForAll, time } = this.props;
|
||||
const { claimSearchByQuery, orderBy, tags, channelIds, time } = this.props;
|
||||
|
||||
if (
|
||||
!_.isEqual(orderBy, prevOrderBy) ||
|
||||
!_.isEqual(tags, prevTags) ||
|
||||
!_.isEqual(channelIds, prevChannelIds) ||
|
||||
time !== prevTime ||
|
||||
trendingForAll !== prevTrendingForAll
|
||||
time !== prevTime
|
||||
) {
|
||||
// reset to page 1 because the order, tags or channelIds changed
|
||||
this.setState({ currentPage: 1 }, () => {
|
||||
|
@ -63,15 +58,12 @@ class ClaimList extends React.PureComponent {
|
|||
this.scrollView.scrollToOffset({ animated: true, offset: 0 });
|
||||
}
|
||||
|
||||
if (trendingForAll || (prevChannelIds && channelIds)) {
|
||||
if (prevChannelIds && channelIds) {
|
||||
if (channelIds) {
|
||||
this.setState({ subscriptionsView: true });
|
||||
}
|
||||
if (trendingForAll) {
|
||||
this.setState({ trendingForAllView: true });
|
||||
}
|
||||
} else if (tags && tags.length > 0) {
|
||||
this.setState({ subscriptionsView: false, trendingForAllView: false });
|
||||
this.setState({ subscriptionsView: false });
|
||||
}
|
||||
|
||||
this.doClaimSearch();
|
||||
|
@ -80,15 +72,8 @@ class ClaimList extends React.PureComponent {
|
|||
}
|
||||
|
||||
buildClaimSearchOptions() {
|
||||
const {
|
||||
orderBy = Constants.DEFAULT_ORDER_BY,
|
||||
channelIds,
|
||||
showNsfwContent,
|
||||
tags,
|
||||
time,
|
||||
trendingForAll,
|
||||
} = this.props;
|
||||
const { currentPage, subscriptionsView, trendingForAllView } = this.state;
|
||||
const { orderBy = Constants.DEFAULT_ORDER_BY, channelIds, showNsfwContent, tags, time } = this.props;
|
||||
const { currentPage, subscriptionsView } = this.state;
|
||||
|
||||
const options = {
|
||||
order_by: orderBy,
|
||||
|
@ -99,7 +84,7 @@ class ClaimList extends React.PureComponent {
|
|||
|
||||
if (channelIds) {
|
||||
options.channel_ids = channelIds;
|
||||
} else if (!trendingForAll && !trendingForAllView && tags && tags.length > 0) {
|
||||
} else if (tags && tags.length > 0) {
|
||||
options.any_tags = tags;
|
||||
}
|
||||
if (!showNsfwContent) {
|
||||
|
@ -156,7 +141,7 @@ class ClaimList extends React.PureComponent {
|
|||
if (tags.length === 1) {
|
||||
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TAG, key: 'tagPage', params: { tag: tags[0] } });
|
||||
} else {
|
||||
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TRENDING });
|
||||
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TRENDING, params: { filterForTags: true } });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -176,8 +161,16 @@ class ClaimList extends React.PureComponent {
|
|||
};
|
||||
|
||||
renderVerticalItem = ({ item }) => {
|
||||
const { navigation } = this.props;
|
||||
return <FileListItem key={item} uri={item} style={claimListStyle.verticalListItem} navigation={navigation} />;
|
||||
const { hideChannel, navigation } = this.props;
|
||||
return (
|
||||
<FileListItem
|
||||
key={item}
|
||||
uri={item}
|
||||
hideChannel={hideChannel}
|
||||
style={claimListStyle.verticalListItem}
|
||||
navigation={navigation}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
renderHorizontalItem = ({ item }) => {
|
||||
|
@ -208,7 +201,7 @@ class ClaimList extends React.PureComponent {
|
|||
style,
|
||||
claimSearchByQuery,
|
||||
} = this.props;
|
||||
const { subscriptionsView, trendingForAllView } = this.state;
|
||||
const { subscriptionsView } = this.state;
|
||||
|
||||
const options = this.buildClaimSearchOptions();
|
||||
const claimSearchKey = createNormalizedClaimSearchKey(options);
|
||||
|
|
|
@ -1,34 +1,76 @@
|
|||
import React from 'react';
|
||||
import { DrawerItems, SafeAreaView } from 'react-navigation';
|
||||
import { ScrollView } from 'react-native';
|
||||
import Constants from 'constants';
|
||||
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import discoverStyle from 'styles/discover';
|
||||
|
||||
const groupedMenuItems = {
|
||||
'Find content': [
|
||||
{ icon: 'hashtag', label: 'Your tags', route: Constants.FULL_ROUTE_NAME_DISCOVER },
|
||||
{ icon: 'heart', solid: true, label: 'Subscriptions', route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS },
|
||||
{ icon: 'globe-americas', label: 'All content', route: Constants.DRAWER_ROUTE_TRENDING },
|
||||
],
|
||||
'Your content': [
|
||||
{ icon: 'download', label: 'Library', route: Constants.DRAWER_ROUTE_MY_LBRY },
|
||||
{ icon: 'cloud-upload-alt', label: 'Publishes', route: Constants.DRAWER_ROUTE_PUBLISHES },
|
||||
{ icon: 'upload', label: 'New publish', route: Constants.DRAWER_ROUTE_PUBLISH },
|
||||
],
|
||||
Wallet: [
|
||||
{ icon: 'wallet', label: 'Wallet', route: Constants.FULL_ROUTE_NAME_WALLET },
|
||||
{ icon: 'award', label: 'Rewards', route: Constants.DRAWER_ROUTE_REWARDS },
|
||||
],
|
||||
Settings: [
|
||||
{ icon: 'cog', label: 'Settings', route: Constants.DRAWER_ROUTE_SETTINGS },
|
||||
{ icon: 'info', label: 'About', route: Constants.DRAWER_ROUTE_ABOUT },
|
||||
],
|
||||
};
|
||||
|
||||
const groupNames = Object.keys(groupedMenuItems);
|
||||
|
||||
class DrawerContent extends React.PureComponent {
|
||||
render() {
|
||||
const props = this.props;
|
||||
const { navigation, onItemPress } = props;
|
||||
const { activeTintColor, navigation, onItemPress } = this.props;
|
||||
const { state } = navigation;
|
||||
|
||||
const activeItemKey = state.routes[state.index] ? state.routes[state.index].key : null;
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
<ScrollView contentContainerStyle={discoverStyle.menuScrollContent}>
|
||||
<SafeAreaView style={discoverStyle.drawerContentContainer} forceInset={{ top: 'always', horizontal: 'never' }}>
|
||||
<DrawerItems
|
||||
{...props}
|
||||
onItemPress={route => {
|
||||
const { routeName } = route.route;
|
||||
if (Constants.FULL_ROUTE_NAME_DISCOVER === routeName) {
|
||||
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_DISCOVER });
|
||||
return;
|
||||
}
|
||||
{groupNames.map(groupName => {
|
||||
const menuItems = groupedMenuItems[groupName];
|
||||
|
||||
if (Constants.FULL_ROUTE_NAME_WALLET === routeName) {
|
||||
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_WALLET });
|
||||
return;
|
||||
}
|
||||
|
||||
onItemPress(route);
|
||||
}}
|
||||
/>
|
||||
return (
|
||||
<View key={groupName} style={discoverStyle.menuGroup}>
|
||||
{groupNames[3] !== groupName && (
|
||||
<Text key={`${groupName}-title`} style={discoverStyle.menuGroupName}>
|
||||
{groupName}
|
||||
</Text>
|
||||
)}
|
||||
{menuItems.map(item => {
|
||||
const focused = activeItemKey === item.route;
|
||||
return (
|
||||
<TouchableOpacity
|
||||
accessible
|
||||
accessibilityLabel={item.label}
|
||||
style={[discoverStyle.menuItemTouchArea, focused ? discoverStyle.menuItemTouchAreaFocused : null]}
|
||||
key={item.label}
|
||||
onPress={() => navigation.navigate({ routeName: item.route })}
|
||||
delayPressIn={0}
|
||||
>
|
||||
<View style={discoverStyle.menuItemIcon}>
|
||||
<Icon name={item.icon} size={16} solid={item.solid} color={focused ? activeTintColor : null} />
|
||||
</View>
|
||||
<Text style={[discoverStyle.menuItem, focused ? discoverStyle.menuItemFocused : null]}>
|
||||
{item.label}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</SafeAreaView>
|
||||
</ScrollView>
|
||||
);
|
||||
|
|
|
@ -54,6 +54,7 @@ const Constants = {
|
|||
ACTION_REACT_NAVIGATION_REPLACE: 'Navigation/REPLACE',
|
||||
|
||||
ACTION_SORT_BY_ITEM_CHANGED: 'SORT_BY_ITEM_CHANGED',
|
||||
ACTION_TIME_ITEM_CHANGED: 'TIME_ITEM_CHANGED',
|
||||
|
||||
ORIENTATION_HORIZONTAL: 'horizontal',
|
||||
ORIENTATION_VERTICAL: 'vertical',
|
||||
|
|
|
@ -43,6 +43,7 @@ import thunk from 'redux-thunk';
|
|||
|
||||
const globalExceptionHandler = (error, isFatal) => {
|
||||
if (error && NativeModules.Firebase) {
|
||||
console.log(error);
|
||||
NativeModules.Firebase.logException(isFatal, error.message ? error.message : 'No message', JSON.stringify(error));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -43,6 +43,7 @@ class AboutPage extends React.PureComponent {
|
|||
const { pushDrawerStack, setPlayerVisible } = this.props;
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('About');
|
||||
|
||||
if (NativeModules.VersionInfo) {
|
||||
NativeModules.VersionInfo.getAppVersion().then(version => {
|
||||
|
|
|
@ -1,26 +1,23 @@
|
|||
import { connect } from 'react-redux';
|
||||
import {
|
||||
doFetchClaimsByChannel,
|
||||
makeSelectClaimForUri,
|
||||
makeSelectClaimsInChannelForCurrentPageState,
|
||||
makeSelectFetchingChannelClaims,
|
||||
makeSelectTotalPagesForChannel,
|
||||
} from 'lbry-redux';
|
||||
import { doFetchClaimsByChannel, makeSelectClaimForUri } from 'lbry-redux';
|
||||
import { doPopDrawerStack } from 'redux/actions/drawer';
|
||||
import { doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
||||
import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||
import { selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
||||
import ChannelPage from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
claimsInChannel: makeSelectClaimsInChannelForCurrentPageState(props.uri)(state),
|
||||
drawerStack: selectDrawerStack(state),
|
||||
fetching: makeSelectFetchingChannelClaims(props.uri)(state),
|
||||
totalPages: makeSelectTotalPagesForChannel(props.uri, 10)(state), // Update to use a default PAGE_SIZE constant
|
||||
sortByItem: selectSortByItem(state),
|
||||
timeItem: selectTimeItem(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)),
|
||||
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
||||
setSortByItem: item => dispatch(doSetSortByItem(item)),
|
||||
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -1,113 +1,111 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { ActivityIndicator, Dimensions, Image, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Dimensions,
|
||||
Image,
|
||||
NativeModules,
|
||||
ScrollView,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { TabView, SceneMap } from 'react-native-tab-view';
|
||||
import { normalizeURI } from 'lbry-redux';
|
||||
import { navigateBack } from 'utils/helper';
|
||||
import { navigateBack, getOrderBy } from 'utils/helper';
|
||||
import ChannelIconItem from 'component/channelIconItem';
|
||||
import ClaimList from 'component/claimList';
|
||||
import Colors from 'styles/colors';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import Button from 'component/button';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import Link from 'component/link';
|
||||
import FileList from 'component/fileList';
|
||||
import ModalPicker from 'component/modalPicker';
|
||||
import PageHeader from 'component/pageHeader';
|
||||
import SubscribeButton from 'component/subscribeButton';
|
||||
import SubscribeNotificationButton from 'component/subscribeNotificationButton';
|
||||
import UriBar from 'component/uriBar';
|
||||
import channelIconStyle from 'styles/channelIcon';
|
||||
import channelPageStyle from 'styles/channelPage';
|
||||
import discoverStyle from 'styles/discover';
|
||||
|
||||
class ChannelPage extends React.PureComponent {
|
||||
state = {
|
||||
page: 1,
|
||||
showPageButtons: false,
|
||||
autoStyle: null,
|
||||
showSortPicker: false,
|
||||
showTimePicker: false,
|
||||
orderBy: Constants.DEFAULT_ORDER_BY,
|
||||
activeTab: Constants.CONTENT_TAB,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { uri, page, claimsInChannel, fetchClaims, fetchClaimCount } = this.props;
|
||||
|
||||
if (!claimsInChannel || !claimsInChannel.length) {
|
||||
fetchClaims(uri, page || this.state.page);
|
||||
}
|
||||
componentWillMount() {
|
||||
this.setState({
|
||||
autoStyle:
|
||||
ChannelIconItem.AUTO_THUMB_STYLES[Math.floor(Math.random() * ChannelIconItem.AUTO_THUMB_STYLES.length)],
|
||||
});
|
||||
}
|
||||
|
||||
handlePreviousPage = () => {
|
||||
const { uri, fetchClaims } = this.props;
|
||||
if (this.state.page > 1) {
|
||||
this.setState({ page: this.state.page - 1, showPageButtons: false }, () => {
|
||||
fetchClaims(uri, this.state.page);
|
||||
});
|
||||
}
|
||||
componentDidMount() {
|
||||
NativeModules.Firebase.setCurrentScreen('Channel');
|
||||
}
|
||||
|
||||
handleSortByItemSelected = item => {
|
||||
const { setSortByItem } = this.props;
|
||||
setSortByItem(item);
|
||||
this.setState({ orderBy: getOrderBy(item), showSortPicker: false });
|
||||
};
|
||||
|
||||
handleNextPage = () => {
|
||||
const { uri, fetchClaims, totalPages } = this.props;
|
||||
if (this.state.page < totalPages) {
|
||||
this.setState({ page: this.state.page + 1, showPageButtons: false }, () => {
|
||||
fetchClaims(uri, this.state.page);
|
||||
});
|
||||
}
|
||||
handleTimeItemSelected = item => {
|
||||
const { setTimeItem } = this.props;
|
||||
setTimeItem(item);
|
||||
this.setState({ showTimePicker: false });
|
||||
};
|
||||
|
||||
listHeader = () => {
|
||||
const { sortByItem, timeItem } = this.props;
|
||||
|
||||
return (
|
||||
<View style={channelPageStyle.listHeader}>
|
||||
<View style={discoverStyle.pickerRow}>
|
||||
<View style={discoverStyle.leftPickerRow}>
|
||||
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
|
||||
<Text style={discoverStyle.tagSortText}>{sortByItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
{Constants.SORT_BY_TOP === sortByItem.name && (
|
||||
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
||||
<Text style={discoverStyle.tagSortText}>{timeItem.label}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
renderContent = () => {
|
||||
const { fetching, claimsInChannel, totalPages, navigation } = this.props;
|
||||
const { claim, navigation, timeItem } = this.props;
|
||||
|
||||
let contentList;
|
||||
if (fetching) {
|
||||
contentList = (
|
||||
<View style={channelPageStyle.busyContainer}>
|
||||
<ActivityIndicator size="large" color={Colors.NextLbryGreen} />
|
||||
<Text style={channelPageStyle.infoText}>Fetching content...</Text>
|
||||
</View>
|
||||
);
|
||||
} else {
|
||||
contentList =
|
||||
claimsInChannel && claimsInChannel.length ? (
|
||||
<FileList
|
||||
sortByHeight
|
||||
hideFilter
|
||||
fileInfos={claimsInChannel}
|
||||
navigation={navigation}
|
||||
style={channelPageStyle.fileList}
|
||||
contentContainerStyle={channelPageStyle.fileListContent}
|
||||
onEndReached={() => this.setState({ showPageButtons: true })}
|
||||
/>
|
||||
) : (
|
||||
<View style={channelPageStyle.busyContainer}>
|
||||
<Text style={channelPageStyle.infoText}>No content found.</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
let pageButtons;
|
||||
if (totalPages > 1 && this.state.showPageButtons) {
|
||||
pageButtons = (
|
||||
<View style={channelPageStyle.pageButtons}>
|
||||
<View>
|
||||
{this.state.page > 1 && (
|
||||
<Button
|
||||
style={channelPageStyle.button}
|
||||
text={'Previous'}
|
||||
disabled={!!fetching}
|
||||
onPress={this.handlePreviousPage}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
{this.state.page < totalPages && (
|
||||
<Button
|
||||
style={[channelPageStyle.button, channelPageStyle.nextButton]}
|
||||
text={'Next'}
|
||||
disabled={!!fetching}
|
||||
onPress={this.handleNextPage}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
let channelId;
|
||||
if (claim) {
|
||||
channelId = claim.claim_id;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={channelPageStyle.contentTab}>
|
||||
{contentList}
|
||||
{pageButtons}
|
||||
{channelId && (
|
||||
<ClaimList
|
||||
ListHeaderComponent={this.listHeader}
|
||||
hideChannel
|
||||
orderBy={this.state.orderBy}
|
||||
time={timeItem.name}
|
||||
navigation={navigation}
|
||||
orientation={Constants.ORIENTATION_VERTICAL}
|
||||
channelIds={[channelId]}
|
||||
style={channelPageStyle.claimList}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
@ -162,10 +160,16 @@ class ChannelPage extends React.PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { fetching, claimsInChannel, claim, navigation, totalPages, uri, drawerStack, popDrawerStack } = this.props;
|
||||
const { claim, navigation, uri, drawerStack, popDrawerStack, sortByItem, timeItem } = this.props;
|
||||
const { name, permanent_url: permanentUrl } = claim;
|
||||
const { autoStyle, showSortPicker, showTimePicker } = this.state;
|
||||
|
||||
let thumbnailUrl, coverUrl, title, fullUri;
|
||||
let thumbnailUrl,
|
||||
coverUrl,
|
||||
title,
|
||||
fullUri,
|
||||
displayName = null,
|
||||
substrIndex = 0;
|
||||
if (claim) {
|
||||
if (claim.value) {
|
||||
title = claim.value.title;
|
||||
|
@ -177,6 +181,8 @@ class ChannelPage extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
displayName = title || claim.name;
|
||||
substrIndex = displayName.startsWith('@') ? 1 : 0;
|
||||
fullUri = normalizeURI(`${claim.name}#${claim.claim_id}`);
|
||||
}
|
||||
|
||||
|
@ -200,16 +206,15 @@ class ChannelPage extends React.PureComponent {
|
|||
<Text style={channelPageStyle.channelName}>{title && title.trim().length > 0 ? title : name}</Text>
|
||||
</View>
|
||||
|
||||
<View style={channelPageStyle.avatarImageContainer}>
|
||||
<Image
|
||||
style={channelPageStyle.avatarImage}
|
||||
resizeMode={'cover'}
|
||||
source={
|
||||
thumbnailUrl && thumbnailUrl.trim().length > 0
|
||||
? { uri: thumbnailUrl }
|
||||
: require('../../assets/default_avatar.jpg')
|
||||
}
|
||||
/>
|
||||
<View style={[channelPageStyle.avatarImageContainer, autoStyle]}>
|
||||
{thumbnailUrl && (
|
||||
<Image style={channelPageStyle.avatarImage} resizeMode={'cover'} source={{ uri: thumbnailUrl }} />
|
||||
)}
|
||||
{(!thumbnailUrl || thumbnailUrl.trim().length === 0) && (
|
||||
<Text style={channelIconStyle.autothumbCharacter}>
|
||||
{displayName.substring(substrIndex, substrIndex + 1).toUpperCase()}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={channelPageStyle.subscribeButtonContainer}>
|
||||
|
@ -242,6 +247,25 @@ class ChannelPage extends React.PureComponent {
|
|||
{Constants.CONTENT_TAB === this.state.activeTab && this.renderContent()}
|
||||
{Constants.ABOUT_TAB === this.state.activeTab && this.renderAbout()}
|
||||
</View>
|
||||
|
||||
{showSortPicker && (
|
||||
<ModalPicker
|
||||
title={__('Sort content by')}
|
||||
onOverlayPress={() => this.setState({ showSortPicker: false })}
|
||||
onItemSelected={this.handleSortByItemSelected}
|
||||
selectedItem={sortByItem}
|
||||
items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS}
|
||||
/>
|
||||
)}
|
||||
{showTimePicker && (
|
||||
<ModalPicker
|
||||
title={__('Content from')}
|
||||
onOverlayPress={() => this.setState({ showTimePicker: false })}
|
||||
onItemSelected={this.handleTimeItemSelected}
|
||||
selectedItem={timeItem}
|
||||
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ import {
|
|||
selectSubscriptionClaims,
|
||||
selectUnreadSubscriptions,
|
||||
} from 'lbryinc';
|
||||
import { doSetClientSetting, doSetSortByItem } from 'redux/actions/settings';
|
||||
import { makeSelectClientSetting, selectSortByItem } from 'redux/selectors/settings';
|
||||
import { doSetClientSetting, doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
||||
import { makeSelectClientSetting, 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 => ({
|
|||
ratingReminderDisabled: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED)(state),
|
||||
ratingReminderLastShown: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_LAST_SHOWN)(state),
|
||||
sortByItem: selectSortByItem(state),
|
||||
timeItem: selectTimeItem(state),
|
||||
unreadSubscriptions: selectUnreadSubscriptions(state),
|
||||
});
|
||||
|
||||
|
@ -39,6 +40,7 @@ const perform = dispatch => ({
|
|||
removeUnreadSubscriptions: () => dispatch(doRemoveUnreadSubscriptions()),
|
||||
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
|
||||
setSortByItem: item => dispatch(doSetSortByItem(item)),
|
||||
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -33,10 +33,13 @@ class DiscoverPage extends React.PureComponent {
|
|||
remainingTags: [],
|
||||
showModalTagSelector: false,
|
||||
showSortPicker: false,
|
||||
showTimePicker: false,
|
||||
orderBy: Constants.DEFAULT_ORDER_BY,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
NativeModules.Firebase.setCurrentScreen('Your tags');
|
||||
|
||||
// Track the total time taken if this is the first launch
|
||||
AsyncStorage.getItem('firstLaunchTime').then(startTime => {
|
||||
if (startTime !== null && !isNaN(parseInt(startTime, 10))) {
|
||||
|
@ -78,6 +81,12 @@ class DiscoverPage extends React.PureComponent {
|
|||
this.setState({ orderBy, showSortPicker: false });
|
||||
};
|
||||
|
||||
handleTimeItemSelected = item => {
|
||||
const { setTimeItem } = this.props;
|
||||
setTimeItem(item);
|
||||
this.setState({ showTimePicker: false });
|
||||
};
|
||||
|
||||
subscriptionForUri = (uri, channelName) => {
|
||||
const { allSubscriptions } = this.props;
|
||||
const { claimId, claimName } = parseURI(uri);
|
||||
|
@ -230,26 +239,41 @@ class DiscoverPage extends React.PureComponent {
|
|||
});
|
||||
} else {
|
||||
// navigate to the trending page
|
||||
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TRENDING });
|
||||
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TRENDING, params: { filterForTags: true } });
|
||||
}
|
||||
};
|
||||
|
||||
sectionListHeader = () => (
|
||||
<View style={discoverStyle.titleRow}>
|
||||
<Text style={discoverStyle.pageTitle}>Explore</Text>
|
||||
<View style={discoverStyle.rightTitleRow}>
|
||||
<Link
|
||||
style={discoverStyle.customizeLink}
|
||||
text={'Customize'}
|
||||
onPress={() => this.setState({ showModalTagSelector: true })}
|
||||
/>
|
||||
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
|
||||
<Text style={discoverStyle.tagSortText}>{this.props.sortByItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
sectionListHeader = () => {
|
||||
const { sortByItem, timeItem } = this.props;
|
||||
return (
|
||||
<View style={discoverStyle.listHeader}>
|
||||
<View style={discoverStyle.titleRow}>
|
||||
<Text style={discoverStyle.pageTitle}>Your tags</Text>
|
||||
</View>
|
||||
<View style={discoverStyle.pickerRow}>
|
||||
<View style={discoverStyle.leftPickerRow}>
|
||||
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
|
||||
<Text style={discoverStyle.tagSortText}>{sortByItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
|
||||
{Constants.SORT_BY_TOP === sortByItem.name && (
|
||||
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
||||
<Text style={discoverStyle.tagSortText}>{timeItem.label}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<Link
|
||||
style={discoverStyle.customizeLink}
|
||||
text={'Customize'}
|
||||
onPress={() => this.setState({ showModalTagSelector: true })}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
sectionListFooter = () => {
|
||||
const { remainingTags } = this.state;
|
||||
|
@ -279,7 +303,7 @@ class DiscoverPage extends React.PureComponent {
|
|||
<ClaimList
|
||||
key={item.sort().join(',')}
|
||||
orderBy={this.state.orderBy}
|
||||
time={Constants.TIME_WEEK}
|
||||
time={this.props.timeItem.name}
|
||||
tags={item}
|
||||
morePlaceholder
|
||||
navigation={this.props.navigation}
|
||||
|
@ -299,8 +323,8 @@ class DiscoverPage extends React.PureComponent {
|
|||
);
|
||||
|
||||
render() {
|
||||
const { navigation, sortByItem } = this.props;
|
||||
const { orderBy, showModalTagSelector, showSortPicker } = this.state;
|
||||
const { navigation, sortByItem, timeItem } = this.props;
|
||||
const { orderBy, showModalTagSelector, showSortPicker, showTimePicker } = this.state;
|
||||
|
||||
return (
|
||||
<View style={discoverStyle.container}>
|
||||
|
@ -318,7 +342,9 @@ class DiscoverPage extends React.PureComponent {
|
|||
sections={this.buildSections()}
|
||||
keyExtractor={(item, index) => item}
|
||||
/>
|
||||
{!showModalTagSelector && !showSortPicker && <FloatingWalletBalance navigation={navigation} />}
|
||||
{!showModalTagSelector && !showSortPicker && !showTimePicker && (
|
||||
<FloatingWalletBalance navigation={navigation} />
|
||||
)}
|
||||
{showModalTagSelector && (
|
||||
<ModalTagSelector
|
||||
onOverlayPress={() => this.setState({ showModalTagSelector: false })}
|
||||
|
@ -334,6 +360,15 @@ class DiscoverPage extends React.PureComponent {
|
|||
items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS}
|
||||
/>
|
||||
)}
|
||||
{showTimePicker && (
|
||||
<ModalPicker
|
||||
title={__('Content from')}
|
||||
onOverlayPress={() => this.setState({ showTimePicker: false })}
|
||||
onItemSelected={this.handleTimeItemSelected}
|
||||
selectedItem={timeItem}
|
||||
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Lbry, buildURI, normalizeURI } from 'lbry-redux';
|
||||
import { ActivityIndicator, Button, FlatList, Text, TextInput, View, ScrollView } from 'react-native';
|
||||
import { ActivityIndicator, Button, FlatList, NativeModules, Text, TextInput, View, ScrollView } from 'react-native';
|
||||
import { navigateToUri, uriFromFileInfo } from 'utils/helper';
|
||||
import Colors from 'styles/colors';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
|
@ -34,6 +34,8 @@ class DownloadsPage extends React.PureComponent {
|
|||
const { fetchMyClaims, fileList, pushDrawerStack, setPlayerVisible } = this.props;
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Library');
|
||||
|
||||
fetchMyClaims();
|
||||
fileList();
|
||||
};
|
||||
|
|
|
@ -93,6 +93,7 @@ class FilePage extends React.PureComponent {
|
|||
|
||||
onComponentFocused = () => {
|
||||
StatusBar.setHidden(false);
|
||||
NativeModules.Firebase.setCurrentScreen('File');
|
||||
|
||||
DeviceEventEmitter.addListener('onDownloadStarted', this.handleDownloadStarted);
|
||||
DeviceEventEmitter.addListener('onDownloadUpdated', this.handleDownloadUpdated);
|
||||
|
|
|
@ -45,6 +45,8 @@ class FirstRunScreen extends React.PureComponent {
|
|||
});
|
||||
|
||||
if (NativeModules.FirstRun) {
|
||||
NativeModules.Firebase.setCurrentScreen('First Run');
|
||||
|
||||
NativeModules.FirstRun.isFirstRun().then(firstRun => {
|
||||
AsyncStorage.removeItem(Constants.KEY_FIRST_RUN_EMAIL);
|
||||
AsyncStorage.removeItem(Constants.KEY_EMAIL_VERIFY_PENDING);
|
||||
|
|
|
@ -79,6 +79,7 @@ class PublishPage extends React.PureComponent {
|
|||
canUseCamera: false,
|
||||
titleFocused: false,
|
||||
descriptionFocused: false,
|
||||
loadingVideos: false,
|
||||
|
||||
// gallery videos
|
||||
videos: null,
|
||||
|
@ -151,13 +152,20 @@ class PublishPage extends React.PureComponent {
|
|||
|
||||
onComponentFocused = () => {
|
||||
const { pushDrawerStack, setPlayerVisible } = this.props;
|
||||
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Publish');
|
||||
|
||||
NativeModules.Gallery.canUseCamera().then(canUseCamera => this.setState({ canUseCamera }));
|
||||
NativeModules.Gallery.getThumbnailPath().then(thumbnailPath => this.setState({ thumbnailPath }));
|
||||
NativeModules.Gallery.getVideos().then(videos => this.setState({ videos }));
|
||||
this.setState(
|
||||
{
|
||||
loadingVideos: true,
|
||||
},
|
||||
() => {
|
||||
NativeModules.Gallery.getVideos().then(videos => this.setState({ videos, loadingVideos: false }));
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
getNewUri(name, channel) {
|
||||
|
@ -586,7 +594,7 @@ class PublishPage extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
const { balance, navigation, notify, publishFormValues } = this.props;
|
||||
const { canUseCamera, currentPhase, checkedThumbnails, thumbnailPath, videos } = this.state;
|
||||
const { canUseCamera, currentPhase, checkedThumbnails, loadingVideos, thumbnailPath, videos } = this.state;
|
||||
|
||||
let content;
|
||||
if (Constants.PHASE_SELECTOR === currentPhase) {
|
||||
|
@ -625,13 +633,13 @@ class PublishPage extends React.PureComponent {
|
|||
</View>
|
||||
</View>
|
||||
</View>
|
||||
{(!videos || !thumbnailPath || checkedThumbnails.length === 0) && (
|
||||
{(loadingVideos || !thumbnailPath || checkedThumbnails.length === 0) && (
|
||||
<View style={publishStyle.loadingView}>
|
||||
<ActivityIndicator size="large" color={Colors.NextLbryGreen} />
|
||||
</View>
|
||||
)}
|
||||
{thumbnailPath && (!videos || videos.length === 0) && (
|
||||
<View style={publishStyle.centered}>
|
||||
{!loadingVideos && (!videos || videos.length === 0) && (
|
||||
<View style={publishStyle.relativeCentered}>
|
||||
<Text style={publishStyle.noVideos}>
|
||||
We could not find any videos on your device. Take a photo or record a video to get started.
|
||||
</Text>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { ActivityIndicator, Alert, FlatList, Text, TouchableOpacity, View } from 'react-native';
|
||||
import { ActivityIndicator, Alert, FlatList, NativeModules, Text, TouchableOpacity, View } from 'react-native';
|
||||
import Button from 'component/button';
|
||||
import Colors from 'styles/colors';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
|
@ -35,9 +35,10 @@ class PublishesPage extends React.PureComponent {
|
|||
|
||||
onComponentFocused = () => {
|
||||
const { checkPendingPublishes, fetchMyClaims, pushDrawerStack, setPlayerVisible } = this.props;
|
||||
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Publishes');
|
||||
|
||||
fetchMyClaims();
|
||||
checkPendingPublishes();
|
||||
};
|
||||
|
|
|
@ -42,6 +42,8 @@ class RewardsPage extends React.PureComponent {
|
|||
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Rewards');
|
||||
|
||||
fetchRewards();
|
||||
|
||||
this.setState({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Lbry, parseURI, normalizeURI, isURIValid } from 'lbry-redux';
|
||||
import { ActivityIndicator, Button, Text, TextInput, View, ScrollView } from 'react-native';
|
||||
import { ActivityIndicator, Button, NativeModules, Text, TextInput, View, ScrollView } from 'react-native';
|
||||
import { navigateToUri } from 'utils/helper';
|
||||
import Colors from 'styles/colors';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
|
@ -37,6 +37,7 @@ class SearchPage extends React.PureComponent {
|
|||
const { pushDrawerStack, setPlayerVisible, query, search } = this.props;
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Search');
|
||||
|
||||
const searchQuery = query || this.getSearchQuery();
|
||||
if (searchQuery && searchQuery.trim().length > 0) {
|
||||
|
|
|
@ -28,6 +28,7 @@ class SettingsPage extends React.PureComponent {
|
|||
const { pushDrawerStack, setPlayerVisible } = this.props;
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Settings');
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
|
|
|
@ -239,6 +239,8 @@ class SplashScreen extends React.PureComponent {
|
|||
NativeModules.Firebase.track('app_launch', null);
|
||||
}
|
||||
|
||||
NativeModules.Firebase.setCurrentScreen('Splash');
|
||||
|
||||
this.props.fetchRewardedContent();
|
||||
Linking.getInitialURL().then(url => {
|
||||
if (url) {
|
||||
|
|
|
@ -14,8 +14,8 @@ import {
|
|||
selectShowSuggestedSubs,
|
||||
} from 'lbryinc';
|
||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||
import { doSetClientSetting } from 'redux/actions/settings';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { doSetClientSetting, doSetTimeItem } from 'redux/actions/settings';
|
||||
import { makeSelectClientSetting, selectTimeItem } from 'redux/selectors/settings';
|
||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import SubscriptionsPage from './view';
|
||||
|
@ -32,6 +32,7 @@ const select = state => ({
|
|||
viewMode: selectViewMode(state),
|
||||
firstRunCompleted: selectFirstRunCompleted(state),
|
||||
showSuggestedSubs: selectShowSuggestedSubs(state),
|
||||
timeItem: selectTimeItem(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
@ -41,6 +42,7 @@ const perform = dispatch => ({
|
|||
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SUBSCRIPTIONS)),
|
||||
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
|
||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
View,
|
||||
} from 'react-native';
|
||||
import { buildURI, parseURI } from 'lbry-redux';
|
||||
import { __, uriFromFileInfo } from 'utils/helper';
|
||||
import { __, getOrderBy } from 'utils/helper';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import moment from 'moment';
|
||||
import Button from 'component/button';
|
||||
|
@ -33,6 +33,7 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
state = {
|
||||
showingSuggestedSubs: false,
|
||||
showSortPicker: false,
|
||||
showTimePicker: false,
|
||||
orderBy: ['release_time'],
|
||||
filteredChannels: [],
|
||||
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1], // should always default to sorting subscriptions by new
|
||||
|
@ -63,6 +64,8 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Subscriptions');
|
||||
|
||||
doFetchMySubscriptions();
|
||||
doFetchRecommendedSubscriptions();
|
||||
};
|
||||
|
@ -80,22 +83,13 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
handleSortByItemSelected = item => {
|
||||
let orderBy = [];
|
||||
switch (item.name) {
|
||||
case Constants.SORT_BY_HOT:
|
||||
orderBy = Constants.DEFAULT_ORDER_BY;
|
||||
break;
|
||||
this.setState({ currentSortByItem: item, orderBy: getOrderBy(item), showSortPicker: false });
|
||||
};
|
||||
|
||||
case Constants.SORT_BY_NEW:
|
||||
orderBy = ['release_time'];
|
||||
break;
|
||||
|
||||
case Constants.SORT_BY_TOP:
|
||||
orderBy = ['effective_amount'];
|
||||
break;
|
||||
}
|
||||
|
||||
this.setState({ currentSortByItem: item, orderBy, showSortPicker: false });
|
||||
handleTimeItemSelected = item => {
|
||||
const { setTimeItem } = this.props;
|
||||
setTimeItem(item);
|
||||
this.setState({ showTimePicker: false });
|
||||
};
|
||||
|
||||
handleChannelSelected = channelUri => {
|
||||
|
@ -118,18 +112,17 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
suggestedChannels,
|
||||
subscribedChannels,
|
||||
allSubscriptions,
|
||||
viewMode,
|
||||
doSetViewMode,
|
||||
doCompleteFirstRun,
|
||||
doShowSuggestedSubs,
|
||||
loading,
|
||||
loadingSuggested,
|
||||
firstRunCompleted,
|
||||
doCompleteFirstRun,
|
||||
doShowSuggestedSubs,
|
||||
showSuggestedSubs,
|
||||
timeItem,
|
||||
unreadSubscriptions,
|
||||
navigation,
|
||||
} = this.props;
|
||||
const { currentSortByItem, filteredChannels } = this.state;
|
||||
const { currentSortByItem, filteredChannels, showSortPicker, showTimePicker } = this.state;
|
||||
|
||||
const numberOfSubscriptions = subscribedChannels ? subscribedChannels.length : 0;
|
||||
const hasSubscriptions = numberOfSubscriptions > 0;
|
||||
|
@ -155,7 +148,9 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
<UriBar navigation={navigation} belowOverlay={this.state.showSortPicker} />
|
||||
<View style={subscriptionsStyle.titleRow}>
|
||||
<Text style={subscriptionsStyle.pageTitle}>Channels you follow</Text>
|
||||
{!this.state.showingSuggestedSubs && hasSubscriptions && (
|
||||
</View>
|
||||
{!this.state.showingSuggestedSubs && hasSubscriptions && (
|
||||
<View style={subscriptionsStyle.pickerRow}>
|
||||
<TouchableOpacity
|
||||
style={subscriptionsStyle.tagSortBy}
|
||||
onPress={() => this.setState({ showSortPicker: true })}
|
||||
|
@ -163,8 +158,18 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
<Text style={subscriptionsStyle.tagSortText}>{currentSortByItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={subscriptionsStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{Constants.SORT_BY_TOP === currentSortByItem.name && (
|
||||
<TouchableOpacity
|
||||
style={subscriptionsStyle.tagSortBy}
|
||||
onPress={() => this.setState({ showTimePicker: true })}
|
||||
>
|
||||
<Text style={subscriptionsStyle.tagSortText}>{timeItem.label}</Text>
|
||||
<Icon style={subscriptionsStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
{!this.state.showingSuggestedSubs && hasSubscriptions && !loading && (
|
||||
<View style={subscriptionsStyle.subContainer}>
|
||||
<SubscribedChannelList
|
||||
|
@ -175,6 +180,7 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
style={subscriptionsStyle.claimList}
|
||||
channelIds={channelIds}
|
||||
orderBy={this.state.orderBy}
|
||||
time={timeItem.name}
|
||||
navigation={navigation}
|
||||
orientation={Constants.ORIENTATION_VERTICAL}
|
||||
/>
|
||||
|
@ -217,8 +223,8 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
</View>
|
||||
)}
|
||||
|
||||
{!this.state.showSortPicker && <FloatingWalletBalance navigation={navigation} />}
|
||||
{this.state.showSortPicker && (
|
||||
{!showSortPicker && !showTimePicker && <FloatingWalletBalance navigation={navigation} />}
|
||||
{showSortPicker && (
|
||||
<ModalPicker
|
||||
title={__('Sort content by')}
|
||||
onOverlayPress={() => this.setState({ showSortPicker: false })}
|
||||
|
@ -227,6 +233,15 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS}
|
||||
/>
|
||||
)}
|
||||
{showTimePicker && (
|
||||
<ModalPicker
|
||||
title={__('Content from')}
|
||||
onOverlayPress={() => this.setState({ showTimePicker: false })}
|
||||
onItemSelected={this.handleTimeItemSelected}
|
||||
selectedItem={timeItem}
|
||||
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectFollowedTags, doToggleTagFollow } from 'lbry-redux';
|
||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||
import { doSetSortByItem } from 'redux/actions/settings';
|
||||
import { doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||
import { selectSortByItem } from 'redux/selectors/settings';
|
||||
import { selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
||||
import TagPage from './view';
|
||||
|
||||
const select = state => ({
|
||||
currentRoute: selectCurrentRoute(state),
|
||||
sortByItem: selectSortByItem(state),
|
||||
timeItem: selectTimeItem(state),
|
||||
followedTags: selectFollowedTags(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
pushDrawerStack: (routeName, params) => dispatch(doPushDrawerStack(routeName, params)),
|
||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||
setSortByItem: item => dispatch(doSetSortByItem(item)),
|
||||
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
||||
toggleTagFollow: tag => dispatch(doToggleTagFollow(tag)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -12,6 +12,7 @@ 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 UriBar from 'component/uriBar';
|
||||
|
||||
|
@ -21,8 +22,6 @@ class TagPage extends React.PureComponent {
|
|||
showSortPicker: false,
|
||||
showTimePicker: false,
|
||||
orderBy: Constants.DEFAULT_ORDER_BY,
|
||||
time: Constants.TIME_WEEK,
|
||||
currentTimeItem: Constants.CLAIM_SEARCH_TIME_ITEMS[1],
|
||||
};
|
||||
|
||||
didFocusListener;
|
||||
|
@ -41,9 +40,10 @@ class TagPage extends React.PureComponent {
|
|||
onComponentFocused = () => {
|
||||
const { navigation, pushDrawerStack, setPlayerVisible, sortByItem } = this.props;
|
||||
const { tag } = navigation.state.params;
|
||||
this.setState({ tag, sortByItem, orderBy: getOrderBy(sortByItem) });
|
||||
this.setState({ tag, orderBy: getOrderBy(sortByItem) });
|
||||
pushDrawerStack(Constants.DRAWER_ROUTE_TAG, navigation.state.params);
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Tag');
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -65,42 +65,80 @@ class TagPage extends React.PureComponent {
|
|||
};
|
||||
|
||||
handleTimeItemSelected = item => {
|
||||
this.setState({ currentTimeItem: item, time: item.name, showTimePicker: false });
|
||||
const { setTimeItem } = this.props;
|
||||
setTimeItem(item);
|
||||
this.setState({ showTimePicker: false });
|
||||
};
|
||||
|
||||
isFollowingTag = tag => {
|
||||
const { followedTags } = this.props;
|
||||
return followedTags.map(tag => tag.name).includes(tag);
|
||||
};
|
||||
|
||||
handleFollowTagToggle = () => {
|
||||
const { toggleTagFollow } = this.props;
|
||||
const { tag } = this.state;
|
||||
const isFollowing = this.isFollowingTag(tag);
|
||||
if (isFollowing) {
|
||||
// unfollow
|
||||
NativeModules.Firebase.track('tag_unfollow', { tag });
|
||||
} else {
|
||||
// follow
|
||||
NativeModules.Firebase.track('tag_follow', { tag });
|
||||
}
|
||||
|
||||
toggleTagFollow(tag);
|
||||
if (window.persistor) {
|
||||
window.persistor.flush();
|
||||
}
|
||||
};
|
||||
|
||||
listHeader = () => {
|
||||
const { sortByItem, timeItem } = this.props;
|
||||
const { tag } = this.state;
|
||||
|
||||
return (
|
||||
<View style={discoverStyle.listHeader}>
|
||||
<View style={discoverStyle.titleRow}>
|
||||
<Text style={discoverStyle.pageTitle}>{formatTagTitle(tag)}</Text>
|
||||
</View>
|
||||
<View style={discoverStyle.pickerRow}>
|
||||
<View style={discoverStyle.leftPickerRow}>
|
||||
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
|
||||
<Text style={discoverStyle.tagSortText}>{sortByItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
{Constants.SORT_BY_TOP === sortByItem.name && (
|
||||
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
||||
<Text style={discoverStyle.tagSortText}>{timeItem.label}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<Link
|
||||
style={discoverStyle.customizeLink}
|
||||
text={this.isFollowingTag(tag) ? 'Unfollow' : 'Follow'}
|
||||
onPress={this.handleFollowTagToggle}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { navigation, sortByItem } = this.props;
|
||||
const { tag, currentTimeItem, showSortPicker, showTimePicker } = this.state;
|
||||
const { navigation, sortByItem, timeItem } = this.props;
|
||||
const { tag, showSortPicker, showTimePicker } = this.state;
|
||||
|
||||
return (
|
||||
<View style={discoverStyle.container}>
|
||||
<UriBar navigation={navigation} belowOverlay={showSortPicker || showTimePicker} />
|
||||
{this.state.tag && (
|
||||
<ClaimList
|
||||
ListHeaderComponent={
|
||||
<View style={discoverStyle.tagTitleRow}>
|
||||
<Text style={discoverStyle.tagPageTitle}>{formatTagTitle(tag)}</Text>
|
||||
{Constants.SORT_BY_TOP === sortByItem.name && (
|
||||
<TouchableOpacity
|
||||
style={discoverStyle.tagTime}
|
||||
onPress={() => this.setState({ showTimePicker: true })}
|
||||
>
|
||||
<Text style={discoverStyle.tagSortText}>{currentTimeItem.label}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
<TouchableOpacity
|
||||
style={discoverStyle.tagSortBy}
|
||||
onPress={() => this.setState({ showSortPicker: true })}
|
||||
>
|
||||
<Text style={discoverStyle.tagSortText}>{sortByItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
}
|
||||
ListHeaderComponent={this.listHeader}
|
||||
style={discoverStyle.tagPageClaimList}
|
||||
orderBy={this.state.orderBy}
|
||||
time={this.state.time}
|
||||
time={timeItem.name}
|
||||
tags={[tag]}
|
||||
navigation={navigation}
|
||||
orientation={Constants.ORIENTATION_VERTICAL}
|
||||
|
@ -112,7 +150,7 @@ class TagPage extends React.PureComponent {
|
|||
title={__('Sort content by')}
|
||||
onOverlayPress={() => this.setState({ showSortPicker: false })}
|
||||
onItemSelected={this.handleSortByItemSelected}
|
||||
selectedItem={this.state.sortByItem}
|
||||
selectedItem={sortByItem}
|
||||
items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS}
|
||||
/>
|
||||
)}
|
||||
|
@ -121,7 +159,7 @@ class TagPage extends React.PureComponent {
|
|||
title={__('Content from')}
|
||||
onOverlayPress={() => this.setState({ showTimePicker: false })}
|
||||
onItemSelected={this.handleTimeItemSelected}
|
||||
selectedItem={this.state.currentTimeItem}
|
||||
selectedItem={timeItem}
|
||||
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { View, ScrollView, Text } from 'react-native';
|
||||
import { NativeModules, View, ScrollView, Text } from 'react-native';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import TransactionList from 'component/transactionList';
|
||||
import UriBar from 'component/uriBar';
|
||||
|
@ -23,6 +23,8 @@ class TransactionHistoryPage extends React.PureComponent {
|
|||
const { fetchTransactions, pushDrawerStack, setPlayerVisible } = this.props;
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Transaction History');
|
||||
|
||||
fetchTransactions();
|
||||
};
|
||||
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectFollowedTags } from 'lbry-redux';
|
||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||
import { doSetSortByItem, doSetTimeItem } from 'redux/actions/settings';
|
||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import { selectSortByItem, selectTimeItem } from 'redux/selectors/settings';
|
||||
import TrendingPage from './view';
|
||||
|
||||
const select = state => ({
|
||||
currentRoute: selectCurrentRoute(state),
|
||||
sortByItem: selectSortByItem(state),
|
||||
timeItem: selectTimeItem(state),
|
||||
followedTags: selectFollowedTags(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_TRENDING)),
|
||||
pushDrawerStack: (routeName, params) => dispatch(doPushDrawerStack(routeName, params)),
|
||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||
setSortByItem: item => dispatch(doSetSortByItem(item)),
|
||||
setTimeItem: item => dispatch(doSetTimeItem(item)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import { ActivityIndicator, NativeModules, FlatList, Text, TouchableOpacity, View } from 'react-native';
|
||||
import { DEFAULT_FOLLOWED_TAGS, normalizeURI } from 'lbry-redux';
|
||||
import { normalizeURI } from 'lbry-redux';
|
||||
import { getOrderBy } from 'utils/helper';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import moment from 'moment';
|
||||
import ClaimList from 'component/claimList';
|
||||
|
@ -23,7 +24,10 @@ const TRENDING_FOR_ITEMS = [
|
|||
class TrendingPage extends React.PureComponent {
|
||||
state = {
|
||||
showModalTagSelector: false,
|
||||
showSortByPicker: false,
|
||||
showTimePicker: false,
|
||||
showTrendingForPicker: false,
|
||||
orderBy: Constants.DEFAULT_ORDER_BY,
|
||||
currentTrendingForItem: TRENDING_FOR_ITEMS[0],
|
||||
};
|
||||
|
||||
|
@ -41,9 +45,12 @@ class TrendingPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
onComponentFocused = () => {
|
||||
const { pushDrawerStack, setPlayerVisible } = this.props;
|
||||
pushDrawerStack();
|
||||
const { pushDrawerStack, setPlayerVisible, navigation } = this.props;
|
||||
const { filterForTags } = navigation.state.params ? navigation.state.params : { filterForTags: false };
|
||||
this.setState({ currentTrendingForItem: TRENDING_FOR_ITEMS[filterForTags ? 1 : 0] });
|
||||
pushDrawerStack(Constants.DRAWER_ROUTE_TRENDING, navigation.state.params);
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('All content');
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -62,44 +69,96 @@ class TrendingPage extends React.PureComponent {
|
|||
this.setState({ currentTrendingForItem: item, showTrendingForPicker: false });
|
||||
};
|
||||
|
||||
handleSortByItemSelected = item => {
|
||||
const { setSortByItem } = this.props;
|
||||
setSortByItem(item);
|
||||
this.setState({ orderBy: getOrderBy(item), showSortPicker: false });
|
||||
};
|
||||
|
||||
handleTimeItemSelected = item => {
|
||||
const { setTimeItem } = this.props;
|
||||
setTimeItem(item);
|
||||
this.setState({ showTimePicker: false });
|
||||
};
|
||||
|
||||
listHeader = () => {
|
||||
const { sortByItem, timeItem } = this.props;
|
||||
const { currentTrendingForItem } = this.state;
|
||||
const sortByTop = Constants.SORT_BY_TOP === sortByItem.name;
|
||||
|
||||
return (
|
||||
<View style={discoverStyle.listHeader}>
|
||||
<View style={discoverStyle.titleRow}>
|
||||
<Text style={discoverStyle.pageTitle}>All content</Text>
|
||||
</View>
|
||||
<View style={discoverStyle.pickerRow}>
|
||||
<View style={discoverStyle.leftPickerRow}>
|
||||
<TouchableOpacity
|
||||
style={discoverStyle.allTagSortBy}
|
||||
onPress={() => this.setState({ showSortPicker: true })}
|
||||
>
|
||||
<Text style={discoverStyle.tagSortText}>{sortByItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
|
||||
<Text style={discoverStyle.pickerLabel}>for</Text>
|
||||
<TouchableOpacity
|
||||
style={discoverStyle.allTagSortBy}
|
||||
onPress={() => this.setState({ showTrendingForPicker: true })}
|
||||
>
|
||||
<Text style={discoverStyle.tagSortText}>{currentTrendingForItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
|
||||
{sortByTop && <Text style={discoverStyle.pickerLabel}>in the</Text>}
|
||||
|
||||
{sortByTop && (
|
||||
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
||||
<Text style={discoverStyle.tagSortText}>{timeItem.label}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{TRENDING_FOR_ITEMS[1].name === currentTrendingForItem.name && (
|
||||
<Link
|
||||
style={discoverStyle.customizeLink}
|
||||
text={'Customize'}
|
||||
onPress={() => this.setState({ showModalTagSelector: true })}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { followedTags, navigation } = this.props;
|
||||
const { currentTrendingForItem, showModalTagSelector, showTrendingForPicker } = this.state;
|
||||
const { followedTags, navigation, sortByItem, timeItem } = this.props;
|
||||
const {
|
||||
currentTrendingForItem,
|
||||
orderBy,
|
||||
showModalTagSelector,
|
||||
showSortPicker,
|
||||
showTimePicker,
|
||||
showTrendingForPicker,
|
||||
} = this.state;
|
||||
const filteredForTags = TRENDING_FOR_ITEMS[1].name === currentTrendingForItem.name;
|
||||
|
||||
return (
|
||||
<View style={discoverStyle.container}>
|
||||
<UriBar navigation={navigation} />
|
||||
<ClaimList
|
||||
ListHeaderComponent={
|
||||
<View style={discoverStyle.titleRow}>
|
||||
<Text style={discoverStyle.pageTitle}>Trending</Text>
|
||||
<View style={discoverStyle.rightTitleRow}>
|
||||
{TRENDING_FOR_ITEMS[1].name === currentTrendingForItem.name && (
|
||||
<Link
|
||||
style={discoverStyle.customizeLink}
|
||||
text={'Customize'}
|
||||
onPress={() => this.setState({ showModalTagSelector: true })}
|
||||
/>
|
||||
)}
|
||||
<TouchableOpacity
|
||||
style={discoverStyle.tagSortBy}
|
||||
onPress={() => this.setState({ showTrendingForPicker: true })}
|
||||
>
|
||||
<Text style={discoverStyle.tagSortText}>{currentTrendingForItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
}
|
||||
ListHeaderComponent={this.listHeader}
|
||||
style={discoverStyle.verticalClaimList}
|
||||
orderBy={Constants.DEFAULT_ORDER_BY}
|
||||
trendingForAll={TRENDING_FOR_ITEMS[0].name === currentTrendingForItem.name}
|
||||
tags={followedTags.map(tag => tag.name)}
|
||||
time={null}
|
||||
orderBy={orderBy}
|
||||
tags={filteredForTags ? followedTags.map(tag => tag.name) : null}
|
||||
time={timeItem.name}
|
||||
navigation={navigation}
|
||||
orientation={Constants.ORIENTATION_VERTICAL}
|
||||
/>
|
||||
{!showModalTagSelector && <FloatingWalletBalance navigation={navigation} />}
|
||||
{!showModalTagSelector && !showTrendingForPicker && !showSortPicker && !showTimePicker && (
|
||||
<FloatingWalletBalance navigation={navigation} />
|
||||
)}
|
||||
{showModalTagSelector && (
|
||||
<ModalTagSelector
|
||||
onOverlayPress={() => this.setState({ showModalTagSelector: false })}
|
||||
|
@ -108,13 +167,31 @@ class TrendingPage extends React.PureComponent {
|
|||
)}
|
||||
{showTrendingForPicker && (
|
||||
<ModalPicker
|
||||
title={'Trending for'}
|
||||
title={'Filter for'}
|
||||
onOverlayPress={() => this.setState({ showTrendingForPicker: false })}
|
||||
onItemSelected={this.handleTrendingForItemSelected}
|
||||
selectedItem={currentTrendingForItem}
|
||||
items={TRENDING_FOR_ITEMS}
|
||||
/>
|
||||
)}
|
||||
{showSortPicker && (
|
||||
<ModalPicker
|
||||
title={__('Sort content by')}
|
||||
onOverlayPress={() => this.setState({ showSortPicker: false })}
|
||||
onItemSelected={this.handleSortByItemSelected}
|
||||
selectedItem={sortByItem}
|
||||
items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS}
|
||||
/>
|
||||
)}
|
||||
{showTimePicker && (
|
||||
<ModalPicker
|
||||
title={__('Content from')}
|
||||
onOverlayPress={() => this.setState({ showTimePicker: false })}
|
||||
onItemSelected={this.handleTimeItemSelected}
|
||||
selectedItem={timeItem}
|
||||
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class VerificationScreen extends React.PureComponent {
|
|||
componentDidMount() {
|
||||
const { user } = this.props;
|
||||
this.checkVerificationStatus(user);
|
||||
NativeModules.Firebase.setCurrentScreen('Verification');
|
||||
}
|
||||
|
||||
setEmailVerificationPhase = value => {
|
||||
|
|
|
@ -42,6 +42,7 @@ class WalletPage extends React.PureComponent {
|
|||
const { pushDrawerStack, setPlayerVisible } = this.props;
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Firebase.setCurrentScreen('Wallet');
|
||||
|
||||
const { deviceWalletSynced, getSync, user } = this.props;
|
||||
if (deviceWalletSynced && user && user.has_verified_email) {
|
||||
|
|
|
@ -27,3 +27,14 @@ export function doSetSortByItem(item) {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doSetTimeItem(item) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: Constants.ACTION_TIME_ITEM_CHANGED,
|
||||
data: {
|
||||
name: item.name,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ const reducers = {};
|
|||
const defaultState = {
|
||||
clientSettings: {},
|
||||
sortByItemName: Constants.SORT_BY_HOT,
|
||||
timeItemName: Constants.TIME_WEEK,
|
||||
};
|
||||
|
||||
reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => {
|
||||
|
@ -23,6 +24,11 @@ reducers[Constants.ACTION_SORT_BY_ITEM_CHANGED] = (state, action) =>
|
|||
sortByItemName: action.data.name,
|
||||
});
|
||||
|
||||
reducers[Constants.ACTION_TIME_ITEM_CHANGED] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
timeItemName: action.data.name,
|
||||
});
|
||||
|
||||
export default function reducer(state = defaultState, action) {
|
||||
const handler = reducers[action.type];
|
||||
if (handler) return handler(state, action);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { SETTINGS } from 'lbry-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { getSortByItemForName } from 'utils/helper';
|
||||
import { getSortByItemForName, getTimeItemForName } from 'utils/helper';
|
||||
|
||||
const selectState = state => state.settings || {};
|
||||
|
||||
|
@ -19,6 +19,11 @@ export const selectSortByItem = createSelector(
|
|||
state => getSortByItemForName(state.sortByItemName)
|
||||
);
|
||||
|
||||
export const selectTimeItem = createSelector(
|
||||
selectState,
|
||||
state => getTimeItemForName(state.timeItemName)
|
||||
);
|
||||
|
||||
export const makeSelectClientSetting = setting =>
|
||||
createSelector(
|
||||
selectClientSettings,
|
||||
|
|
|
@ -33,7 +33,7 @@ const buttonStyle = StyleSheet.create({
|
|||
fontSize: 14,
|
||||
},
|
||||
textWithIcon: {
|
||||
marginLeft: 8,
|
||||
marginLeft: 4,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -31,13 +31,11 @@ const channelPageStyle = StyleSheet.create({
|
|||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
infoText: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 20,
|
||||
textAlign: 'center',
|
||||
marginLeft: 10,
|
||||
},
|
||||
pageButtons: {
|
||||
width: '100%',
|
||||
|
@ -69,7 +67,7 @@ const channelPageStyle = StyleSheet.create({
|
|||
subscribeButtonContainer: {
|
||||
position: 'absolute',
|
||||
flexDirection: 'row',
|
||||
left: 8,
|
||||
right: 8,
|
||||
bottom: -90,
|
||||
zIndex: 100,
|
||||
},
|
||||
|
@ -148,11 +146,25 @@ const channelPageStyle = StyleSheet.create({
|
|||
left: 24,
|
||||
bottom: -40,
|
||||
zIndex: 100,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
avatarImage: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
listHeader: {
|
||||
marginTop: 16,
|
||||
marginBottom: 8,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
},
|
||||
claimList: {
|
||||
flex: 1,
|
||||
},
|
||||
claimListContent: {
|
||||
paddingTop: 16,
|
||||
},
|
||||
});
|
||||
|
||||
export default channelPageStyle;
|
||||
|
|
|
@ -28,16 +28,25 @@ const discoverStyle = StyleSheet.create({
|
|||
scrollContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
listHeader: {
|
||||
marginBottom: 8,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
},
|
||||
titleRow: {
|
||||
flexDirection: 'row',
|
||||
marginTop: 76,
|
||||
marginBottom: 8,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
},
|
||||
rightTitleRow: {
|
||||
pickerRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: 8,
|
||||
},
|
||||
leftPickerRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
@ -48,7 +57,6 @@ const discoverStyle = StyleSheet.create({
|
|||
customizeLink: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 14,
|
||||
marginRight: 48,
|
||||
},
|
||||
trendingContainer: {
|
||||
flex: 1,
|
||||
|
@ -258,7 +266,12 @@ const discoverStyle = StyleSheet.create({
|
|||
tagSortBy: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginRight: 4,
|
||||
marginRight: 24,
|
||||
},
|
||||
allTagSortBy: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginRight: 8,
|
||||
},
|
||||
tagTime: {
|
||||
flexDirection: 'row',
|
||||
|
@ -272,6 +285,53 @@ const discoverStyle = StyleSheet.create({
|
|||
tagSortIcon: {
|
||||
marginTop: -6,
|
||||
},
|
||||
pickerLabel: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 14,
|
||||
color: Colors.DescriptionGrey,
|
||||
marginRight: 6,
|
||||
},
|
||||
menuScrollContent: {
|
||||
paddingTop: 16,
|
||||
},
|
||||
menuGroup: {
|
||||
marginTop: 8,
|
||||
marginBottom: 8,
|
||||
},
|
||||
menuGroupName: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 12,
|
||||
color: Colors.DescriptionGrey,
|
||||
textTransform: 'uppercase',
|
||||
marginBottom: 4,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
},
|
||||
menuItemTouchArea: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
paddingTop: 12,
|
||||
paddingBottom: 12,
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
alignItems: 'center',
|
||||
},
|
||||
menuItemTouchAreaFocused: {
|
||||
backgroundColor: Colors.VeryLightGrey,
|
||||
},
|
||||
menuItemFocused: {
|
||||
color: Colors.LbryGreen,
|
||||
},
|
||||
menuItemIcon: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
width: 24,
|
||||
},
|
||||
menuItem: {
|
||||
marginLeft: 8,
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 16,
|
||||
},
|
||||
});
|
||||
|
||||
export default discoverStyle;
|
||||
|
|
|
@ -341,6 +341,11 @@ const publishStyle = StyleSheet.create({
|
|||
fontSize: 14,
|
||||
marginLeft: 8,
|
||||
},
|
||||
relativeCentered: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: 16,
|
||||
},
|
||||
centered: {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
|
|
|
@ -156,10 +156,18 @@ const subscriptionsStyle = StyleSheet.create({
|
|||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
pickerRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
marginTop: 8,
|
||||
marginBottom: 8,
|
||||
},
|
||||
tagSortBy: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginRight: 4,
|
||||
marginRight: 24,
|
||||
},
|
||||
tagSortText: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
|
|
|
@ -217,6 +217,16 @@ export function getSortByItemForName(name) {
|
|||
return null;
|
||||
}
|
||||
|
||||
export function getTimeItemForName(name) {
|
||||
for (let i = 0; i < Constants.CLAIM_SEARCH_TIME_ITEMS.length; i++) {
|
||||
if (name === Constants.CLAIM_SEARCH_TIME_ITEMS[i].name) {
|
||||
return Constants.CLAIM_SEARCH_TIME_ITEMS[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getOrderBy(item) {
|
||||
let orderBy = [];
|
||||
switch (item.name) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue