Fix release blockers ()

This commit is contained in:
Akinwale Ariwodola 2019-08-10 07:55:12 +01:00 committed by GitHub
parent 4b7f3f140a
commit 1e0a636b4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 405 additions and 241 deletions
package-lock.jsonpackage.json
src
component
AppNavigator.js
channelSelector
claimList
fileItem
fileListItem
modalTagSelector
subscribeNotificationButton
suggestedSubscriptionItem
tag
tagSearch
constants.js
page
about
channel
discover
downloads
file
firstRun
publish
publishes
rewards
search
settings
subscriptions
tag
transactionHistory
trending
verification
wallet
redux
styles
utils

8
package-lock.json generated
View file

@ -5562,8 +5562,8 @@
} }
}, },
"lbry-redux": { "lbry-redux": {
"version": "github:lbryio/lbry-redux#cd23c12fb7fd541d28d7cbf3874b1058b036fd13", "version": "github:lbryio/lbry-redux#4e5e51b99b730cc834747edb9fd7d87d47a7d4f9",
"from": "github:lbryio/lbry-redux#cd23c12fb7fd541d28d7cbf3874b1058b036fd13", "from": "github:lbryio/lbry-redux#4e5e51b99b730cc834747edb9fd7d87d47a7d4f9",
"requires": { "requires": {
"proxy-polyfill": "0.1.6", "proxy-polyfill": "0.1.6",
"reselect": "^3.0.0", "reselect": "^3.0.0",
@ -5571,8 +5571,8 @@
} }
}, },
"lbryinc": { "lbryinc": {
"version": "github:lbryio/lbryinc#2cc861145e79ed59478c150ac63f5ffc5fc2ad28", "version": "github:lbryio/lbryinc#430c280789a5031c2e49ca5bf8a7d90ccccc4cdb",
"from": "github:lbryio/lbryinc", "from": "github:lbryio/lbryinc#430c280789a5031c2e49ca5bf8a7d90ccccc4cdb",
"requires": { "requires": {
"reselect": "^3.0.0" "reselect": "^3.0.0"
} }

View file

@ -12,8 +12,8 @@
"base-64": "^0.1.0", "base-64": "^0.1.0",
"@expo/vector-icons": "^8.1.0", "@expo/vector-icons": "^8.1.0",
"gfycat-style-urls": "^1.0.3", "gfycat-style-urls": "^1.0.3",
"lbry-redux": "lbryio/lbry-redux#67a654f60630710cae72419448a73a18d076d18a", "lbry-redux": "lbryio/lbry-redux#4e5e51b99b730cc834747edb9fd7d87d47a7d4f9",
"lbryinc": "lbryio/lbryinc", "lbryinc": "lbryio/lbryinc#430c280789a5031c2e49ca5bf8a7d90ccccc4cdb",
"lodash": ">=4.17.11", "lodash": ">=4.17.11",
"merge": ">=1.2.1", "merge": ">=1.2.1",
"moment": "^2.22.1", "moment": "^2.22.1",

View file

@ -127,79 +127,83 @@ const walletStack = createStackNavigator(
} }
); );
const drawerIconSize = 18;
const drawer = createDrawerNavigator( const drawer = createDrawerNavigator(
{ {
DiscoverStack: { DiscoverStack: {
screen: discoverStack, screen: discoverStack,
navigationOptions: { navigationOptions: {
title: 'Explore', title: 'Explore',
drawerIcon: ({ tintColor }) => <Icon name="home" size={20} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => <Icon name="home" size={drawerIconSize} style={{ color: tintColor }} />,
}, },
}, },
TrendingStack: { TrendingStack: {
screen: TrendingPage, screen: TrendingPage,
navigationOptions: { navigationOptions: {
title: 'Trending', title: 'Trending',
drawerIcon: ({ tintColor }) => <Icon name="fire" size={20} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => <Icon name="fire" size={drawerIconSize} style={{ color: tintColor }} />,
}, },
}, },
MySubscriptionsStack: { MySubscriptionsStack: {
screen: SubscriptionsPage, screen: SubscriptionsPage,
navigationOptions: { navigationOptions: {
title: 'Subscriptions', title: 'Subscriptions',
drawerIcon: ({ tintColor }) => <Icon name="heart" solid size={20} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => <Icon name="heart" solid size={drawerIconSize} style={{ color: tintColor }} />,
}, },
}, },
WalletStack: { WalletStack: {
screen: walletStack, screen: walletStack,
navigationOptions: { navigationOptions: {
title: 'Wallet', title: 'Wallet',
drawerIcon: ({ tintColor }) => <Icon name="wallet" size={20} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => <Icon name="wallet" size={drawerIconSize} style={{ color: tintColor }} />,
}, },
}, },
Publish: { Publish: {
screen: PublishPage, screen: PublishPage,
navigationOptions: { navigationOptions: {
drawerIcon: ({ tintColor }) => <Icon name="upload" size={20} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => <Icon name="upload" size={drawerIconSize} style={{ color: tintColor }} />,
}, },
}, },
Publishes: { Publishes: {
screen: PublishesPage, screen: PublishesPage,
navigationOptions: { navigationOptions: {
drawerIcon: ({ tintColor }) => <Icon name="cloud-upload-alt" size={20} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => (
<Icon name="cloud-upload-alt" size={drawerIconSize} style={{ color: tintColor }} />
),
}, },
}, },
Rewards: { Rewards: {
screen: RewardsPage, screen: RewardsPage,
navigationOptions: { navigationOptions: {
drawerIcon: ({ tintColor }) => <Icon name="award" size={20} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => <Icon name="award" size={drawerIconSize} style={{ color: tintColor }} />,
}, },
}, },
MyLBRYStack: { Downloads: {
screen: DownloadsPage, screen: DownloadsPage,
navigationOptions: { navigationOptions: {
title: 'Library', title: 'Library',
drawerIcon: ({ tintColor }) => <Icon name="download" size={20} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => <Icon name="download" size={drawerIconSize} style={{ color: tintColor }} />,
}, },
}, },
Settings: { Settings: {
screen: SettingsPage, screen: SettingsPage,
navigationOptions: { navigationOptions: {
drawerLockMode: 'locked-closed', drawerLockMode: 'locked-closed',
drawerIcon: ({ tintColor }) => <Icon name="cog" size={20} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => <Icon name="cog" size={drawerIconSize} style={{ color: tintColor }} />,
}, },
}, },
About: { About: {
screen: AboutPage, screen: AboutPage,
navigationOptions: { navigationOptions: {
drawerLockMode: 'locked-closed', drawerLockMode: 'locked-closed',
drawerIcon: ({ tintColor }) => <Icon name="info" size={20} style={{ color: tintColor }} />, drawerIcon: ({ tintColor }) => <Icon name="info" size={drawerIconSize} style={{ color: tintColor }} />,
}, },
}, },
}, },
{ {
drawerWidth: 300, drawerWidth: 300,
headerMode: 'none', headerMode: 'none',
backBehavior: 'none',
unmountInactiveRoutes: true, unmountInactiveRoutes: true,
contentComponent: DrawerContent, contentComponent: DrawerContent,
contentOptions: { contentOptions: {
@ -314,6 +318,7 @@ class AppWithNavigationState extends React.Component {
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'false'); AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'false');
this.setState({ verifyPending: false }); this.setState({ verifyPending: false });
NativeModules.Firebase.track('email_verified', { email: user.primary_email });
ToastAndroid.show('Your email address was successfully verified.', ToastAndroid.LONG); ToastAndroid.show('Your email address was successfully verified.', ToastAndroid.LONG);
// upon successful email verification, do wallet sync (if password has been set) // upon successful email verification, do wallet sync (if password has been set)

View file

@ -1,9 +1,9 @@
import React from 'react'; import React from 'react';
import { CLAIM_VALUES, isNameValid } from 'lbry-redux'; import { CLAIM_VALUES, isURIValid } from 'lbry-redux';
import { ActivityIndicator, Picker, Text, TextInput, TouchableOpacity, View } from 'react-native'; import { ActivityIndicator, Picker, Text, TextInput, TouchableOpacity, View } from 'react-native';
import Button from 'component/button'; import Button from 'component/button';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import Icon from 'react-native-vector-icons/FontAwesome5'; import Icon from 'react-native-vector-icons/FontAwesome5';
import Link from 'component/link'; import Link from 'component/link';
import channelSelectorStyle from 'styles/channelSelector'; import channelSelectorStyle from 'styles/channelSelector';
@ -102,7 +102,7 @@ export default class ChannelSelector extends React.PureComponent {
const { balance, createChannel, onChannelChange, notify } = this.props; const { balance, createChannel, onChannelChange, notify } = this.props;
const { newChannelBid, newChannelName } = this.state; const { newChannelBid, newChannelName } = this.state;
if (newChannelName.trim().length === 0 || !isNameValid(newChannelName.substr(1), false)) { if (newChannelName.trim().length === 0 || !isURIValid(newChannelName.substr(1), false)) {
notify({ message: 'Your channel name contains invalid characters.' }); notify({ message: 'Your channel name contains invalid characters.' });
return; return;
} }

View file

@ -8,6 +8,7 @@ import {
selectFetchingClaimSearch, selectFetchingClaimSearch,
selectLastClaimSearchUris, selectLastClaimSearchUris,
} from 'lbry-redux'; } from 'lbry-redux';
import { selectShowNsfw } from 'redux/selectors/settings';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import ClaimList from './view'; import ClaimList from './view';
@ -18,6 +19,7 @@ const select = (state, props) => {
// for subscriptions // for subscriptions
claimSearchLoading: selectFetchingClaimSearch(state), claimSearchLoading: selectFetchingClaimSearch(state),
claimSearchUris: selectLastClaimSearchUris(state), claimSearchUris: selectLastClaimSearchUris(state),
showNsfwContent: selectShowNsfw(state),
}; };
}; };
@ -34,7 +36,6 @@ const perform = dispatch => ({
no_totals: true, no_totals: true,
order_by: orderBy, order_by: orderBy,
page, page,
not_tags: MATURE_TAGS,
}, },
additionalOptions additionalOptions
) )

View file

@ -31,6 +31,7 @@ class ClaimList extends React.PureComponent {
claimSearch, claimSearch,
orderBy = Constants.DEFAULT_ORDER_BY, orderBy = Constants.DEFAULT_ORDER_BY,
searchByTags, searchByTags,
showNsfwContent,
tags, tags,
time, time,
} = this.props; } = this.props;
@ -38,9 +39,11 @@ class ClaimList extends React.PureComponent {
const options = { const options = {
order_by: orderBy, order_by: orderBy,
no_totals: true, no_totals: true,
not_tags: MATURE_TAGS,
page: this.state.currentPage, page: this.state.currentPage,
}; };
if (!showNsfwContent) {
options.not_tags = MATURE_TAGS;
}
if (channelIds) { if (channelIds) {
this.setState({ subscriptionsView: true }); this.setState({ subscriptionsView: true });
options.channel_ids = channelIds; options.channel_ids = channelIds;
@ -54,6 +57,9 @@ class ClaimList extends React.PureComponent {
if (orderBy && orderBy[0] === Constants.ORDER_BY_EFFECTIVE_AMOUNT && Constants.TIME_ALL !== time) { if (orderBy && orderBy[0] === Constants.ORDER_BY_EFFECTIVE_AMOUNT && Constants.TIME_ALL !== time) {
additionalOptions.release_time = this.getReleaseTimeOption(time); additionalOptions.release_time = this.getReleaseTimeOption(time);
} }
if (!showNsfwContent) {
additionalOptions.not_tags = MATURE_TAGS;
}
searchByTags(tags, orderBy, this.state.currentPage, additionalOptions); searchByTags(tags, orderBy, this.state.currentPage, additionalOptions);
} }
} }
@ -67,6 +73,7 @@ class ClaimList extends React.PureComponent {
channelIds: prevChannelIds, channelIds: prevChannelIds,
trendingForAll: prevTrendingForAll, trendingForAll: prevTrendingForAll,
time: prevTime, time: prevTime,
showNsfwContent,
} = this.props; } = this.props;
const { orderBy, tags, channelIds, trendingForAll, time } = nextProps; const { orderBy, tags, channelIds, trendingForAll, time } = nextProps;
if ( if (
@ -85,9 +92,11 @@ class ClaimList extends React.PureComponent {
const options = { const options = {
order_by: orderBy, order_by: orderBy,
no_totals: true, no_totals: true,
not_tags: MATURE_TAGS,
page: this.state.currentPage, page: this.state.currentPage,
}; };
if (!showNsfwContent) {
options.not_tags = MATURE_TAGS;
}
if (channelIds) { if (channelIds) {
this.setState({ subscriptionsView: true }); this.setState({ subscriptionsView: true });
options.channel_ids = channelIds; options.channel_ids = channelIds;
@ -103,6 +112,9 @@ class ClaimList extends React.PureComponent {
if (orderBy && orderBy[0] === Constants.ORDER_BY_EFFECTIVE_AMOUNT && Constants.TIME_ALL !== time) { if (orderBy && orderBy[0] === Constants.ORDER_BY_EFFECTIVE_AMOUNT && Constants.TIME_ALL !== time) {
additionalOptions.release_time = this.getReleaseTimeOption(time); additionalOptions.release_time = this.getReleaseTimeOption(time);
} }
if (!showNsfwContent) {
additionalOptions.not_tags = MATURE_TAGS;
}
searchByTags(tags, orderBy, this.state.currentPage, additionalOptions); searchByTags(tags, orderBy, this.state.currentPage, additionalOptions);
} }
}); });
@ -119,7 +131,17 @@ class ClaimList extends React.PureComponent {
handleVerticalEndReached = () => { handleVerticalEndReached = () => {
// fetch more content // fetch more content
const { channelIds, claimSearch, claimSearchUris, orderBy, searchByTags, tags, time, uris } = this.props; const {
channelIds,
claimSearch,
claimSearchUris,
orderBy,
searchByTags,
showNsfwContent,
tags,
time,
uris,
} = this.props;
const { subscriptionsView, trendingForAllView } = this.state; const { subscriptionsView, trendingForAllView } = this.state;
if ((claimSearchUris && claimSearchUris.length >= softLimit) || (uris && uris.length >= softLimit)) { if ((claimSearchUris && claimSearchUris.length >= softLimit) || (uris && uris.length >= softLimit)) {
// don't fetch more than the specified limit to be displayed // don't fetch more than the specified limit to be displayed
@ -131,9 +153,11 @@ class ClaimList extends React.PureComponent {
const options = { const options = {
order_by: orderBy, order_by: orderBy,
no_totals: true, no_totals: true,
not_tags: MATURE_TAGS,
page: this.state.currentPage, page: this.state.currentPage,
}; };
if (!showNsfwContent) {
options.not_tags = MATURE_TAGS;
}
if (subscriptionsView) { if (subscriptionsView) {
options.channel_ids = channelIds; options.channel_ids = channelIds;
} }
@ -144,6 +168,9 @@ class ClaimList extends React.PureComponent {
if (orderBy && orderBy[0] === Constants.ORDER_BY_EFFECTIVE_AMOUNT && Constants.TIME_ALL !== time) { if (orderBy && orderBy[0] === Constants.ORDER_BY_EFFECTIVE_AMOUNT && Constants.TIME_ALL !== time) {
additionalOptions.release_time = this.getReleaseTimeOption(time); additionalOptions.release_time = this.getReleaseTimeOption(time);
} }
if (!showNsfwContent) {
additionalOptions.not_tags = MATURE_TAGS;
}
searchByTags(tags, orderBy, this.state.currentPage, additionalOptions); searchByTags(tags, orderBy, this.state.currentPage, additionalOptions);
} }
}); });
@ -174,6 +201,29 @@ class ClaimList extends React.PureComponent {
); );
}; };
renderVerticalItem = ({ item }) => {
const { navigation } = this.props;
return <FileListItem key={item} uri={item} style={claimListStyle.verticalListItem} navigation={navigation} />;
};
renderHorizontalItem = ({ item }) => {
const { navigation } = this.props;
return item === Constants.MORE_PLACEHOLDER ? (
this.renderMorePlaceholder()
) : (
<FileItem
style={discoverStyle.fileItem}
mediaStyle={discoverStyle.fileItemMedia}
key={item}
uri={normalizeURI(item)}
navigation={navigation}
showDetails
compactView={false}
/>
);
};
render() { render() {
const { const {
ListHeaderComponent, ListHeaderComponent,
@ -202,9 +252,7 @@ class ClaimList extends React.PureComponent {
initialNumToRender={10} initialNumToRender={10}
maxToRenderPerBatch={20} maxToRenderPerBatch={20}
removeClippedSubviews removeClippedSubviews
renderItem={({ item }) => ( renderItem={this.renderVerticalItem}
<FileListItem key={item} uri={item} style={claimListStyle.verticalListItem} navigation={navigation} />
)}
data={data} data={data}
keyExtractor={(item, index) => item} keyExtractor={(item, index) => item}
onEndReached={this.handleVerticalEndReached} onEndReached={this.handleVerticalEndReached}
@ -235,21 +283,7 @@ class ClaimList extends React.PureComponent {
initialNumToRender={3} initialNumToRender={3}
maxToRenderPerBatch={3} maxToRenderPerBatch={3}
removeClippedSubviews removeClippedSubviews
renderItem={({ item }) => { renderItem={this.renderHorizontalItem}
return item === Constants.MORE_PLACEHOLDER ? (
this.renderMorePlaceholder()
) : (
<FileItem
style={discoverStyle.fileItem}
mediaStyle={discoverStyle.fileItemMedia}
key={item}
uri={normalizeURI(item)}
navigation={navigation}
showDetails
compactView={false}
/>
);
}}
horizontal horizontal
showsHorizontalScrollIndicator={false} showsHorizontalScrollIndicator={false}
data={uris ? this.appendMorePlaceholder(uris.slice(0, horizontalLimit)) : []} data={uris ? this.appendMorePlaceholder(uris.slice(0, horizontalLimit)) : []}

View file

@ -50,13 +50,15 @@ class FileItem extends React.PureComponent {
style, style,
mediaStyle, mediaStyle,
navigation, navigation,
nsfw,
obscureNsfw,
showDetails, showDetails,
compactView, compactView,
titleBeforeThumbnail, titleBeforeThumbnail,
} = this.props; } = this.props;
const uri = normalizeURI(this.props.uri); const uri = normalizeURI(this.props.uri);
const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; const obscure = obscureNsfw && nsfw;
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id); const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
const signingChannel = claim ? claim.signing_channel : null; const signingChannel = claim ? claim.signing_channel : null;
const channelName = signingChannel ? signingChannel.name : null; const channelName = signingChannel ? signingChannel.name : null;
@ -75,7 +77,7 @@ class FileItem extends React.PureComponent {
<FileItemMedia <FileItemMedia
title={title} title={title}
thumbnail={thumbnail} thumbnail={thumbnail}
blurRadius={obscureNsfw ? 15 : 0} blurRadius={obscure ? 15 : 0}
resizeMode="cover" resizeMode="cover"
isResolvingUri={isResolvingUri} isResolvingUri={isResolvingUri}
style={mediaStyle} style={mediaStyle}
@ -106,13 +108,12 @@ class FileItem extends React.PureComponent {
}} }}
/> />
)} )}
{!channelName && <Text style={discoverStyle.anonChannelName}>Anonymous</Text>}
<DateTime style={discoverStyle.dateTime} textStyle={discoverStyle.dateTimeText} timeAgo uri={uri} /> <DateTime style={discoverStyle.dateTime} textStyle={discoverStyle.dateTimeText} timeAgo uri={uri} />
</View> </View>
)} )}
</TouchableOpacity> </TouchableOpacity>
{obscureNsfw && ( {obscure && <NsfwOverlay onPress={() => navigation.navigate({ routeName: 'Settings', key: 'settingsPage' })} />}
<NsfwOverlay onPress={() => navigation.navigate({ routeName: 'Settings', key: 'settingsPage' })} />
)}
</View> </View>
); );
} }

View file

@ -5,6 +5,7 @@ import {
makeSelectMetadataForUri, makeSelectMetadataForUri,
makeSelectFileInfoForUri, makeSelectFileInfoForUri,
makeSelectIsUriResolving, makeSelectIsUriResolving,
makeSelectClaimIsNsfw,
makeSelectTitleForUri, makeSelectTitleForUri,
makeSelectThumbnailForUri, makeSelectThumbnailForUri,
} from 'lbry-redux'; } from 'lbry-redux';
@ -19,6 +20,7 @@ const select = (state, props) => ({
filteredOutpoints: selectFilteredOutpoints(state), filteredOutpoints: selectFilteredOutpoints(state),
isDownloaded: !!makeSelectFileInfoForUri(props.uri)(state), isDownloaded: !!makeSelectFileInfoForUri(props.uri)(state),
metadata: makeSelectMetadataForUri(props.uri)(state), metadata: makeSelectMetadataForUri(props.uri)(state),
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
isResolvingUri: makeSelectIsUriResolving(props.uri)(state), isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
obscureNsfw: !selectShowNsfw(state), obscureNsfw: !selectShowNsfw(state),
title: makeSelectTitleForUri(props.uri)(state), title: makeSelectTitleForUri(props.uri)(state),

View file

@ -53,10 +53,12 @@ class FileListItem extends React.PureComponent {
fileInfo, fileInfo,
filteredOutpoints, filteredOutpoints,
metadata, metadata,
nsfw,
featuredResult, featuredResult,
isResolvingUri, isResolvingUri,
isDownloaded, isDownloaded,
style, style,
obscureNsfw,
onPress, onPress,
navigation, navigation,
thumbnail, thumbnail,
@ -65,7 +67,7 @@ class FileListItem extends React.PureComponent {
} = this.props; } = this.props;
const uri = normalizeURI(this.props.uri); const uri = normalizeURI(this.props.uri);
const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; const obscure = obscureNsfw && nsfw;
const isResolving = !fileInfo && isResolvingUri; const isResolving = !fileInfo && isResolvingUri;
let name, channel, height, channelClaimId, fullChannelUri, shouldHide, signingChannel; let name, channel, height, channelClaimId, fullChannelUri, shouldHide, signingChannel;
@ -92,7 +94,7 @@ class FileListItem extends React.PureComponent {
<TouchableOpacity style={style} onPress={onPress || this.defaultOnPress}> <TouchableOpacity style={style} onPress={onPress || this.defaultOnPress}>
<FileItemMedia <FileItemMedia
style={fileListStyle.thumbnail} style={fileListStyle.thumbnail}
blurRadius={obscureNsfw ? 15 : 0} blurRadius={obscure ? 15 : 0}
resizeMode="cover" resizeMode="cover"
title={title || name} title={title || name}
thumbnail={thumbnail} thumbnail={thumbnail}
@ -155,9 +157,7 @@ class FileListItem extends React.PureComponent {
)} )}
</View> </View>
</TouchableOpacity> </TouchableOpacity>
{obscureNsfw && ( {obscure && <NsfwOverlay onPress={() => navigation.navigate({ routeName: 'Settings', key: 'settingsPage' })} />}
<NsfwOverlay onPress={() => navigation.navigate({ routeName: 'Settings', key: 'settingsPage' })} />
)}
</View> </View>
); );
} }

View file

@ -23,6 +23,9 @@ export default class ModalTagSelector extends React.PureComponent {
} }
this.props.doToggleTagFollow(tag); this.props.doToggleTagFollow(tag);
if (window.persistor) {
window.persistor.flush();
}
NativeModules.Firebase.track('tag_follow', { tag }); NativeModules.Firebase.track('tag_follow', { tag });
}; };
@ -32,6 +35,9 @@ export default class ModalTagSelector extends React.PureComponent {
} }
this.props.doToggleTagFollow(tag); this.props.doToggleTagFollow(tag);
if (window.persistor) {
window.persistor.flush();
}
NativeModules.Firebase.track('tag_unfollow', { tag }); NativeModules.Firebase.track('tag_unfollow', { tag });
}; };

View file

@ -5,17 +5,27 @@ import Button from 'component/button';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
class SubscribeNotificationButton extends React.PureComponent { class SubscribeNotificationButton extends React.PureComponent {
render() { handlePress = () => {
const { const {
uri,
name, name,
doChannelSubscriptionEnableNotifications, doChannelSubscriptionEnableNotifications,
doChannelSubscriptionDisableNotifications, doChannelSubscriptionDisableNotifications,
doToast, doToast,
enabledChannelNotifications, enabledChannelNotifications,
isSubscribed,
style,
} = this.props; } = this.props;
const shouldNotify = enabledChannelNotifications.indexOf(name) > -1;
if (shouldNotify) {
doChannelSubscriptionDisableNotifications(name);
doToast({ message: 'You will not receive notifications for new content.' });
} else {
doChannelSubscriptionEnableNotifications(name);
doToast({ message: 'You will receive all notifications for new content.' });
}
};
render() {
const { enabledChannelNotifications, name, uri, isSubscribed, style } = this.props;
if (!isSubscribed) { if (!isSubscribed) {
return null; return null;
@ -31,23 +41,14 @@ class SubscribeNotificationButton extends React.PureComponent {
} }
const shouldNotify = enabledChannelNotifications.indexOf(name) > -1; const shouldNotify = enabledChannelNotifications.indexOf(name) > -1;
const { claimName } = parseURI(uri);
return ( return (
<Button <Button
style={styles} style={styles}
theme={'light'} theme={'light'}
icon={shouldNotify ? 'bell-slash' : 'bell'} icon={shouldNotify ? 'bell-slash' : 'bell'}
solid={true} solid
onPress={() => { onPress={this.handlePress}
if (shouldNotify) {
doChannelSubscriptionDisableNotifications(name);
doToast({ message: 'You will not receive notifications for new content.' });
} else {
doChannelSubscriptionEnableNotifications(name);
doToast({ message: 'You will receive all notifications for new content.' });
}
}}
/> />
); );
} }

View file

@ -1,11 +1,13 @@
import React from 'react'; import React from 'react';
import { buildURI, normalizeURI } from 'lbry-redux'; import { buildURI, normalizeURI } from 'lbry-redux';
import { ActivityIndicator, FlatList, Image, Text, View } from 'react-native'; import { ActivityIndicator, FlatList, Image, Text, View } from 'react-native';
import { navigateToUri } from 'utils/helper';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import discoverStyle from 'styles/discover'; import discoverStyle from 'styles/discover';
import FileItem from 'component/fileItem'; import FileItem from 'component/fileItem';
import SubscribeButton from 'component/subscribeButton'; import SubscribeButton from 'component/subscribeButton';
import subscriptionsStyle from 'styles/subscriptions'; import subscriptionsStyle from 'styles/subscriptions';
import Link from 'component/link';
import Tag from 'component/tag'; import Tag from 'component/tag';
class SuggestedSubscriptionItem extends React.PureComponent { class SuggestedSubscriptionItem extends React.PureComponent {
@ -47,15 +49,22 @@ class SuggestedSubscriptionItem extends React.PureComponent {
{title} {title}
</Text> </Text>
)} )}
<Text style={subscriptionsStyle.suggestedItemName} numberOfLines={1}> {claim && (
{claim && claim.name} <Link
</Text> style={subscriptionsStyle.suggestedItemName}
numberOfLines={1}
text={claim.name}
onPress={() => navigateToUri(navigation, normalizeURI(uri))}
/>
)}
{tags && ( {tags && (
<View style={subscriptionsStyle.suggestedItemTagList}> <View style={subscriptionsStyle.suggestedItemTagList}>
{tags && {tags &&
tags tags
.slice(0, 3) .slice(0, 3)
.map(tag => <Tag style={subscriptionsStyle.tag} key={tag} name={tag} navigation={navigation} />)} .map(tag => (
<Tag style={subscriptionsStyle.tag} key={tag} name={tag} navigation={navigation} truncate />
))}
</View> </View>
)} )}
</View> </View>

View file

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { Text, TouchableOpacity, View } from 'react-native'; import { Text, TouchableOpacity, View } from 'react-native';
import { MATURE_TAGS } from 'lbry-redux';
import { formatTagName } from 'utils/helper'; import { formatTagName } from 'utils/helper';
import tagStyle from 'styles/tag'; import tagStyle from 'styles/tag';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
@ -29,7 +30,7 @@ export default class Tag extends React.PureComponent {
}; };
render() { render() {
const { name, onPress, style, type } = this.props; const { name, onPress, style, type, truncate } = this.props;
let styles = []; let styles = [];
if (style) { if (style) {
@ -41,7 +42,7 @@ export default class Tag extends React.PureComponent {
} }
styles.push({ styles.push({
backgroundColor: Colors.TagGreen, backgroundColor: MATURE_TAGS.includes(name) ? Colors.TagGrape : Colors.TagGreen,
borderRadius: 8, borderRadius: 8,
marginBottom: 4, marginBottom: 4,
}); });
@ -49,7 +50,7 @@ export default class Tag extends React.PureComponent {
return ( return (
<TouchableOpacity style={styles} onPress={onPress || this.onPressDefault}> <TouchableOpacity style={styles} onPress={onPress || this.onPressDefault}>
<View style={tagStyle.content}> <View style={tagStyle.content}>
<Text style={tagStyle.text}>{formatTagName(name)}</Text> <Text style={tagStyle.text}>{truncate ? formatTagName(name) : name}</Text>
{type && <Icon style={tagStyle.icon} name={type === 'add' ? 'plus' : 'times'} size={8} />} {type && <Icon style={tagStyle.icon} name={type === 'add' ? 'plus' : 'times'} size={8} />}
</View> </View>
</TouchableOpacity> </TouchableOpacity>

View file

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { KeyboardAvoidingView, Text, TextInput, TouchableOpacity, View } from 'react-native'; import { KeyboardAvoidingView, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { MATURE_TAGS } from 'lbry-redux';
import Tag from 'component/tag'; import Tag from 'component/tag';
import tagStyle from 'styles/tag'; import tagStyle from 'styles/tag';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
@ -66,7 +67,7 @@ export default class TagSearch extends React.PureComponent {
}; };
render() { render() {
const { name, style, type, selectedTags = [] } = this.props; const { name, style, type, selectedTags = [], showNsfwTags } = this.props;
return ( return (
<View> <View>
@ -85,6 +86,22 @@ export default class TagSearch extends React.PureComponent {
))} ))}
</View> </View>
</KeyboardAvoidingView> </KeyboardAvoidingView>
{showNsfwTags && (
<View style={tagStyle.nsfwTagsContainer}>
<Text style={tagStyle.nsfwTagsTitle}>Mature tags</Text>
<View style={tagStyle.tagResultsList}>
{MATURE_TAGS.map(tag => (
<Tag
key={tag}
name={tag}
style={tagStyle.tag}
type="add"
onAddPress={name => this.onAddTagPress(name)}
/>
))}
</View>
</View>
)}
</View> </View>
); );
} }

View file

@ -53,6 +53,8 @@ const Constants = {
ACTION_REACT_NAVIGATION_NAVIGATE: 'Navigation/NAVIGATE', ACTION_REACT_NAVIGATION_NAVIGATE: 'Navigation/NAVIGATE',
ACTION_REACT_NAVIGATION_REPLACE: 'Navigation/REPLACE', ACTION_REACT_NAVIGATION_REPLACE: 'Navigation/REPLACE',
ACTION_SORT_BY_ITEM_CHANGED: 'SORT_BY_ITEM_CHANGED',
ORIENTATION_HORIZONTAL: 'horizontal', ORIENTATION_HORIZONTAL: 'horizontal',
ORIENTATION_VERTICAL: 'vertical', ORIENTATION_VERTICAL: 'vertical',
@ -79,7 +81,6 @@ const Constants = {
FULL_ROUTE_NAME_TRENDING: 'TrendingStack', FULL_ROUTE_NAME_TRENDING: 'TrendingStack',
FULL_ROUTE_NAME_MY_SUBSCRIPTIONS: 'MySubscriptionsStack', FULL_ROUTE_NAME_MY_SUBSCRIPTIONS: 'MySubscriptionsStack',
FULL_ROUTE_NAME_WALLET: 'WalletStack', FULL_ROUTE_NAME_WALLET: 'WalletStack',
FULL_ROUTE_NAME_MY_LBRY: 'MyLBRYStack',
ROUTE_FILE: 'File', ROUTE_FILE: 'File',

View file

@ -2,7 +2,7 @@ import React from 'react';
import { Lbry } from 'lbry-redux'; import { Lbry } from 'lbry-redux';
import { NativeModules, Text, View, ScrollView } from 'react-native'; import { NativeModules, Text, View, ScrollView } from 'react-native';
import { navigateBack } from 'utils/helper'; import { navigateBack } from 'utils/helper';
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import Link from 'component/link'; import Link from 'component/link';
import PageHeader from 'component/pageHeader'; import PageHeader from 'component/pageHeader';
import aboutStyle from 'styles/about'; import aboutStyle from 'styles/about';
@ -18,7 +18,7 @@ class AboutPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {
@ -105,7 +105,7 @@ class AboutPage extends React.PureComponent {
<Text style={aboutStyle.text}>Connected email</Text> <Text style={aboutStyle.text}>Connected email</Text>
</View> </View>
<View style={aboutStyle.col}> <View style={aboutStyle.col}>
<Text selectable={true} style={aboutStyle.valueText}> <Text selectable style={aboutStyle.valueText}>
{userEmail} {userEmail}
</Text> </Text>
</View> </View>
@ -125,7 +125,7 @@ class AboutPage extends React.PureComponent {
<Text style={aboutStyle.text}>App version</Text> <Text style={aboutStyle.text}>App version</Text>
</View> </View>
<View style={aboutStyle.col}> <View style={aboutStyle.col}>
<Text selectable={true} style={aboutStyle.valueText}> <Text selectable style={aboutStyle.valueText}>
{this.state.appVersion} {this.state.appVersion}
</Text> </Text>
</View> </View>
@ -136,7 +136,7 @@ class AboutPage extends React.PureComponent {
<Text style={aboutStyle.text}>Daemon (lbrynet)</Text> <Text style={aboutStyle.text}>Daemon (lbrynet)</Text>
</View> </View>
<View style={aboutStyle.col}> <View style={aboutStyle.col}>
<Text selectable={true} style={aboutStyle.valueText}> <Text selectable style={aboutStyle.valueText}>
{ver ? ver.lbrynet_version : loading} {ver ? ver.lbrynet_version : loading}
</Text> </Text>
</View> </View>
@ -147,7 +147,7 @@ class AboutPage extends React.PureComponent {
<Text style={aboutStyle.text}>Platform</Text> <Text style={aboutStyle.text}>Platform</Text>
</View> </View>
<View style={aboutStyle.col}> <View style={aboutStyle.col}>
<Text selectable={true} style={aboutStyle.valueText}> <Text selectable style={aboutStyle.valueText}>
{ver ? ver.platform : loading} {ver ? ver.platform : loading}
</Text> </Text>
</View> </View>
@ -156,7 +156,7 @@ class AboutPage extends React.PureComponent {
<View style={aboutStyle.row}> <View style={aboutStyle.row}>
<View style={aboutStyle.col}> <View style={aboutStyle.col}>
<Text style={aboutStyle.text}>Installation ID</Text> <Text style={aboutStyle.text}>Installation ID</Text>
<Text selectable={true} style={aboutStyle.lineValueText}> <Text selectable style={aboutStyle.lineValueText}>
{this.state.lbryId ? this.state.lbryId : loading} {this.state.lbryId ? this.state.lbryId : loading}
</Text> </Text>
</View> </View>

View file

@ -10,6 +10,7 @@ import Link from 'component/link';
import FileList from 'component/fileList'; import FileList from 'component/fileList';
import PageHeader from 'component/pageHeader'; import PageHeader from 'component/pageHeader';
import SubscribeButton from 'component/subscribeButton'; import SubscribeButton from 'component/subscribeButton';
import SubscribeNotificationButton from 'component/subscribeNotificationButton';
import UriBar from 'component/uriBar'; import UriBar from 'component/uriBar';
import channelPageStyle from 'styles/channelPage'; import channelPageStyle from 'styles/channelPage';
@ -206,7 +207,14 @@ class ChannelPage extends React.PureComponent {
/> />
</View> </View>
<View style={channelPageStyle.subscribeButtonContainer}>
<SubscribeButton style={channelPageStyle.subscribeButton} uri={uri} name={name} /> <SubscribeButton style={channelPageStyle.subscribeButton} uri={uri} name={name} />
<SubscribeNotificationButton
style={[channelPageStyle.subscribeButton, channelPageStyle.bellButton]}
uri={uri}
name={name}
/>
</View>
</View> </View>
<View style={channelPageStyle.tabBar}> <View style={channelPageStyle.tabBar}>

View file

@ -18,9 +18,8 @@ import {
selectSubscriptionClaims, selectSubscriptionClaims,
selectUnreadSubscriptions, selectUnreadSubscriptions,
} from 'lbryinc'; } from 'lbryinc';
import { doSetClientSetting, doSetSortByItem } from 'redux/actions/settings';
import { doSetClientSetting } from 'redux/actions/settings'; import { makeSelectClientSetting, selectSortByItem } from 'redux/selectors/settings';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import DiscoverPage from './view'; import DiscoverPage from './view';
@ -34,6 +33,7 @@ const select = state => ({
followedTags: selectFollowedTags(state), followedTags: selectFollowedTags(state),
ratingReminderDisabled: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED)(state), ratingReminderDisabled: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED)(state),
ratingReminderLastShown: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_LAST_SHOWN)(state), ratingReminderLastShown: makeSelectClientSetting(Constants.SETTING_RATING_REMINDER_LAST_SHOWN)(state),
sortByItem: selectSortByItem(state),
unreadSubscriptions: selectUnreadSubscriptions(state), unreadSubscriptions: selectUnreadSubscriptions(state),
uris: selectLastClaimSearchUris(state), uris: selectLastClaimSearchUris(state),
}); });
@ -46,6 +46,7 @@ const perform = dispatch => ({
fileList: () => dispatch(doFileList()), fileList: () => dispatch(doFileList()),
removeUnreadSubscriptions: () => dispatch(doRemoveUnreadSubscriptions()), removeUnreadSubscriptions: () => dispatch(doRemoveUnreadSubscriptions()),
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
setSortByItem: item => dispatch(doSetSortByItem(item)),
}); });
export default connect( export default connect(

View file

@ -11,7 +11,7 @@ import {
View, View,
} from 'react-native'; } from 'react-native';
import { DEFAULT_FOLLOWED_TAGS, Lbry, normalizeURI, parseURI } from 'lbry-redux'; import { DEFAULT_FOLLOWED_TAGS, Lbry, normalizeURI, parseURI } from 'lbry-redux';
import { __, formatTagTitle } from 'utils/helper'; import { __, formatTagTitle, getOrderBy } from 'utils/helper';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import moment from 'moment'; import moment from 'moment';
import CategoryList from 'component/categoryList'; import CategoryList from 'component/categoryList';
@ -33,7 +33,6 @@ class DiscoverPage extends React.PureComponent {
showModalTagSelector: false, showModalTagSelector: false,
showSortPicker: false, showSortPicker: false,
orderBy: Constants.DEFAULT_ORDER_BY, orderBy: Constants.DEFAULT_ORDER_BY,
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[0],
}; };
componentDidMount() { componentDidMount() {
@ -60,33 +59,22 @@ class DiscoverPage extends React.PureComponent {
} }
}); });
const { fetchRewardedContent, fetchSubscriptions, fileList, followedTags } = this.props; const { sortByItem, fetchRewardedContent, fetchSubscriptions, fileList, followedTags } = this.props;
this.buildTagCollection(followedTags); this.buildTagCollection(followedTags);
fetchRewardedContent(); fetchRewardedContent();
fetchSubscriptions(); fetchSubscriptions();
fileList(); fileList();
this.handleSortByItemSelected(sortByItem);
this.showRatingReminder(); this.showRatingReminder();
} }
handleSortByItemSelected = item => { handleSortByItemSelected = item => {
let orderBy = []; const { setSortByItem } = this.props;
switch (item.name) { setSortByItem(item);
case Constants.SORT_BY_HOT: const orderBy = getOrderBy(item);
orderBy = Constants.DEFAULT_ORDER_BY; this.setState({ orderBy, showSortPicker: false });
break;
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 });
}; };
subscriptionForUri = (uri, channelName) => { subscriptionForUri = (uri, channelName) => {
@ -217,7 +205,7 @@ class DiscoverPage extends React.PureComponent {
// each of the followed tags // each of the followed tags
const tagCollection = _.shuffle(tags) const tagCollection = _.shuffle(tags)
.slice(0, 6) .slice(0, 5)
.map(tag => [tag]); .map(tag => [tag]);
// everything // everything
tagCollection.unshift(tags); tagCollection.unshift(tags);
@ -226,24 +214,22 @@ class DiscoverPage extends React.PureComponent {
}; };
handleTagPress = name => { handleTagPress = name => {
const { navigation } = this.props; const { navigation, sortByItem } = this.props;
if (name.toLowerCase() !== 'trending') { if (name.toLowerCase() !== 'all tags you follow') {
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TAG, key: `tagPage`, params: { tag: name } }); navigation.navigate({
routeName: Constants.DRAWER_ROUTE_TAG,
key: `tagPage`,
params: {
tag: name,
},
});
} else { } else {
// navigate to the trending page // navigate to the trending page
navigation.navigate({ routeName: Constants.FULL_ROUTE_NAME_TRENDING }); navigation.navigate({ routeName: Constants.FULL_ROUTE_NAME_TRENDING });
} }
}; };
render() { sectionListHeader = () => (
const { navigation } = this.props;
const { currentSortByItem, orderBy, showModalTagSelector, showSortPicker } = this.state;
return (
<View style={discoverStyle.container}>
<UriBar navigation={navigation} belowOverlay={showModalTagSelector} />
<SectionList
ListHeaderComponent={
<View style={discoverStyle.titleRow}> <View style={discoverStyle.titleRow}>
<Text style={discoverStyle.pageTitle}>Explore</Text> <Text style={discoverStyle.pageTitle}>Explore</Text>
<View style={discoverStyle.rightTitleRow}> <View style={discoverStyle.rightTitleRow}>
@ -252,33 +238,27 @@ class DiscoverPage extends React.PureComponent {
text={'Customize'} text={'Customize'}
onPress={() => this.setState({ showModalTagSelector: true })} onPress={() => this.setState({ showModalTagSelector: true })}
/> />
<TouchableOpacity <TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
style={discoverStyle.tagSortBy} <Text style={discoverStyle.tagSortText}>{this.props.sortByItem.label.split(' ')[0]}</Text>
onPress={() => this.setState({ showSortPicker: true })}
>
<Text style={discoverStyle.tagSortText}>{currentSortByItem.label.split(' ')[0]}</Text>
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} /> <Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </View>
} );
style={discoverStyle.scrollContainer}
contentContainerStyle={discoverStyle.scrollPadding} renderSectionListItem = ({ item, index, section }) => (
initialNumToRender={4}
maxToRenderPerBatch={4}
removeClippedSubviews
renderItem={({ item, index, section }) => (
<ClaimList <ClaimList
key={item.sort().join(',')} key={item.sort().join(',')}
orderBy={orderBy} orderBy={this.state.orderBy}
time={Constants.TIME_WEEK} time={Constants.TIME_WEEK}
tags={item} tags={item}
morePlaceholder morePlaceholder
navigation={navigation} navigation={this.props.navigation}
orientation={Constants.ORIENTATION_HORIZONTAL} orientation={Constants.ORIENTATION_HORIZONTAL}
/> />
)} );
renderSectionHeader={({ section: { title } }) => (
renderSectionHeader = ({ section: { title } }) => (
<View style={discoverStyle.categoryTitleRow}> <View style={discoverStyle.categoryTitleRow}>
<Text style={discoverStyle.categoryName} onPress={() => this.handleTagPress(title)}> <Text style={discoverStyle.categoryName} onPress={() => this.handleTagPress(title)}>
{formatTagTitle(title)} {formatTagTitle(title)}
@ -287,7 +267,24 @@ class DiscoverPage extends React.PureComponent {
<Icon name={'angle-double-down'} size={16} /> <Icon name={'angle-double-down'} size={16} />
</TouchableOpacity> </TouchableOpacity>
</View> </View>
)} );
render() {
const { navigation, sortByItem } = this.props;
const { orderBy, showModalTagSelector, showSortPicker } = this.state;
return (
<View style={discoverStyle.container}>
<UriBar navigation={navigation} belowOverlay={showModalTagSelector} />
<SectionList
ListHeaderComponent={this.sectionListHeader}
style={discoverStyle.scrollContainer}
contentContainerStyle={discoverStyle.scrollPadding}
initialNumToRender={4}
maxToRenderPerBatch={4}
removeClippedSubviews
renderItem={this.renderSectionListItem}
renderSectionHeader={this.renderSectionHeader}
sections={this.buildSections()} sections={this.buildSections()}
keyExtractor={(item, index) => item} keyExtractor={(item, index) => item}
/> />
@ -303,7 +300,7 @@ class DiscoverPage extends React.PureComponent {
title={__('Sort content by')} title={__('Sort content by')}
onOverlayPress={() => this.setState({ showSortPicker: false })} onOverlayPress={() => this.setState({ showSortPicker: false })}
onItemSelected={this.handleSortByItemSelected} onItemSelected={this.handleSortByItemSelected}
selectedItem={currentSortByItem} selectedItem={sortByItem}
items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS} items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS}
/> />
)} )}

View file

@ -21,7 +21,7 @@ class DownloadsPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {
@ -44,7 +44,7 @@ class DownloadsPage extends React.PureComponent {
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
const { currentRoute } = nextProps; const { currentRoute } = nextProps;
const { currentRoute: prevRoute } = this.props; const { currentRoute: prevRoute } = this.props;
if (Constants.FULL_ROUTE_NAME_MY_LBRY === currentRoute && currentRoute !== prevRoute) { if (Constants.DRAWER_ROUTE_MY_LBRY === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused(); this.onComponentFocused();
} }
} }

View file

@ -88,7 +88,7 @@ class FilePage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
onComponentFocused = () => { onComponentFocused = () => {
@ -913,6 +913,7 @@ class FilePage extends React.PureComponent {
<TextInput <TextInput
ref={ref => (this.tipAmountInput = ref)} ref={ref => (this.tipAmountInput = ref)}
onChangeText={value => this.setState({ tipAmount: value })} onChangeText={value => this.setState({ tipAmount: value })}
underlineColorAndroid={Colors.NextLbryGreen}
keyboardType={'numeric'} keyboardType={'numeric'}
placeholder={'0'} placeholder={'0'}
value={this.state.tipAmount} value={this.state.tipAmount}

View file

@ -4,7 +4,7 @@ import { ActivityIndicator, Linking, NativeModules, Text, TouchableOpacity, View
import { NavigationActions, StackActions } from 'react-navigation'; import { NavigationActions, StackActions } from 'react-navigation';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import WalletPage from './internal/wallet-page'; import WalletPage from './internal/wallet-page';
import WelcomePage from './internal/welcome-page'; import WelcomePage from './internal/welcome-page';
import EmailCollectPage from './internal/email-collect-page'; import EmailCollectPage from './internal/email-collect-page';
@ -73,6 +73,7 @@ class FirstRunScreen extends React.PureComponent {
notify({ message: String(emailNewErrorMessage), isError: true }); notify({ message: String(emailNewErrorMessage), isError: true });
} else { } else {
// Request successful. Navigate to email verify page. // Request successful. Navigate to email verify page.
NativeModules.Firebase.track('email_added', { email: this.state.email });
this.showPage(Constants.FIRST_RUN_PAGE_EMAIL_VERIFY); this.showPage(Constants.FIRST_RUN_PAGE_EMAIL_VERIFY);
} }
} }
@ -228,7 +229,7 @@ class FirstRunScreen extends React.PureComponent {
onEmailChanged = email => { onEmailChanged = email => {
this.setState({ email }); this.setState({ email });
if (Constants.FIRST_RUN_PAGE_EMAIL_COLLECT == this.state.currentPage) { if (Constants.FIRST_RUN_PAGE_EMAIL_COLLECT === this.state.currentPage) {
this.setState({ showSkip: !email || email.trim().length === 0 }); this.setState({ showSkip: !email || email.trim().length === 0 });
} else { } else {
this.setState({ showSkip: false }); this.setState({ showSkip: false });
@ -236,14 +237,14 @@ class FirstRunScreen extends React.PureComponent {
}; };
onEmailViewLayout = phase => { onEmailViewLayout = phase => {
if ('collect' === phase) { if (phase === 'collect') {
if (!this.state.emailCollectTracked) { if (!this.state.emailCollectTracked) {
// we only want to track this once // we only want to track this once
this.setState({ emailCollectTracked: true }, () => this.setState({ emailCollectTracked: true }, () =>
NativeModules.Firebase.track('first_run_email_collect', null) NativeModules.Firebase.track('first_run_email_collect', null)
); );
} }
} else if ('verify' === phase) { } else if (phase === 'verify') {
NativeModules.Firebase.track('first_run_email_verify', null); NativeModules.Firebase.track('first_run_email_verify', null);
} }

View file

@ -15,7 +15,15 @@ import {
View, View,
} from 'react-native'; } from 'react-native';
import { FlatGrid } from 'react-native-super-grid'; import { FlatGrid } from 'react-native-super-grid';
import { isNameValid, buildURI, regexInvalidURI, CLAIM_VALUES, LICENSES, THUMBNAIL_STATUSES } from 'lbry-redux'; import {
isNameValid,
buildURI,
regexInvalidURI,
CLAIM_VALUES,
LICENSES,
MATURE_TAGS,
THUMBNAIL_STATUSES,
} from 'lbry-redux';
import { DocumentPicker, DocumentPickerUtil } from 'react-native-document-picker'; import { DocumentPicker, DocumentPickerUtil } from 'react-native-document-picker';
import { RNCamera } from 'react-native-camera'; import { RNCamera } from 'react-native-camera';
import { generateCombination } from 'gfycat-style-urls'; import { generateCombination } from 'gfycat-style-urls';
@ -116,7 +124,7 @@ class PublishPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
DeviceEventEmitter.addListener('onGalleryThumbnailsChecked', this.handleGalleryThumbnailsChecked); DeviceEventEmitter.addListener('onGalleryThumbnailsChecked', this.handleGalleryThumbnailsChecked);
} }
@ -203,10 +211,6 @@ class PublishPage extends React.PureComponent {
} }
const publishTags = tags.slice(); const publishTags = tags.slice();
if (mature) {
publishTags.push('nsfw');
}
const publishParams = { const publishParams = {
filePath: currentMedia.filePath, filePath: currentMedia.filePath,
bid: bid || 0.1, bid: bid || 0.1,
@ -215,7 +219,7 @@ class PublishPage extends React.PureComponent {
thumbnail: thumbnail, thumbnail: thumbnail,
description: description || '', description: description || '',
language, language,
nsfw: mature, nsfw: publishTags.some(tag => MATURE_TAGS.includes(tag)),
license, license,
licenseUrl: '', licenseUrl: '',
otherLicenseDescription: '', otherLicenseDescription: '',
@ -654,7 +658,7 @@ class PublishPage extends React.PureComponent {
/> />
))} ))}
</View> </View>
<TagSearch handleAddTag={this.handleAddTag} selectedTags={this.state.tags} /> <TagSearch handleAddTag={this.handleAddTag} selectedTags={this.state.tags} showNsfwTags />
</View> </View>
<View style={publishStyle.card}> <View style={publishStyle.card}>
@ -727,11 +731,6 @@ class PublishPage extends React.PureComponent {
{this.state.advancedMode && ( {this.state.advancedMode && (
<View style={publishStyle.card}> <View style={publishStyle.card}>
<Text style={publishStyle.cardTitle}>Additional Options</Text> <Text style={publishStyle.cardTitle}>Additional Options</Text>
<View style={publishStyle.toggleField}>
<Switch value={this.state.mature} onValueChange={value => this.setState({ mature: value })} />
<Text style={publishStyle.toggleText}>Mature content</Text>
</View>
<View> <View>
<Text style={publishStyle.cardText}>Language</Text> <Text style={publishStyle.cardText}>Language</Text>
<Picker <Picker

View file

@ -14,7 +14,7 @@ class PublishesPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {
@ -23,6 +23,10 @@ class PublishesPage extends React.PureComponent {
} }
} }
componentDidMount() {
this.onComponentFocused();
}
onComponentFocused = () => { onComponentFocused = () => {
const { checkPendingPublishes, pushDrawerStack, setPlayerVisible } = this.props; const { checkPendingPublishes, pushDrawerStack, setPlayerVisible } = this.props;

View file

@ -28,7 +28,7 @@ class RewardsPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {

View file

@ -24,7 +24,7 @@ class SearchPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {

View file

@ -2,7 +2,7 @@ import React from 'react';
import { SETTINGS } from 'lbry-redux'; import { SETTINGS } from 'lbry-redux';
import { Text, View, ScrollView, Switch, NativeModules } from 'react-native'; import { Text, View, ScrollView, Switch, NativeModules } from 'react-native';
import { navigateBack } from 'utils/helper'; import { navigateBack } from 'utils/helper';
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import PageHeader from 'component/pageHeader'; import PageHeader from 'component/pageHeader';
import settingsStyle from 'styles/settings'; import settingsStyle from 'styles/settings';
@ -15,7 +15,7 @@ class SettingsPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {

View file

@ -42,7 +42,7 @@ class SubscriptionsPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {

View file

@ -1,16 +1,19 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { doSetSortByItem } from 'redux/actions/settings';
import { selectCurrentRoute } from 'redux/selectors/drawer'; import { selectCurrentRoute } from 'redux/selectors/drawer';
import Constants from 'constants'; import { selectSortByItem } from 'redux/selectors/settings';
import TagPage from './view'; import TagPage from './view';
const select = state => ({ const select = state => ({
currentRoute: selectCurrentRoute(state), currentRoute: selectCurrentRoute(state),
sortByItem: selectSortByItem(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_TAG)), pushDrawerStack: (routeName, params) => dispatch(doPushDrawerStack(routeName, params)),
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)), setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
setSortByItem: item => dispatch(doSetSortByItem(item)),
}); });
export default connect( export default connect(

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { ActivityIndicator, NativeModules, FlatList, Text, TouchableOpacity, View } from 'react-native'; import { ActivityIndicator, NativeModules, FlatList, Text, TouchableOpacity, View } from 'react-native';
import { DEFAULT_FOLLOWED_TAGS, normalizeURI } from 'lbry-redux'; import { DEFAULT_FOLLOWED_TAGS, normalizeURI } from 'lbry-redux';
import { formatTagTitle } from 'utils/helper'; import { formatTagTitle, getOrderBy } from 'utils/helper';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import moment from 'moment'; import moment from 'moment';
import ClaimList from 'component/claimList'; import ClaimList from 'component/claimList';
@ -22,7 +22,6 @@ class TagPage extends React.PureComponent {
showTimePicker: false, showTimePicker: false,
orderBy: Constants.DEFAULT_ORDER_BY, orderBy: Constants.DEFAULT_ORDER_BY,
time: Constants.TIME_WEEK, time: Constants.TIME_WEEK,
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[0],
currentTimeItem: Constants.CLAIM_SEARCH_TIME_ITEMS[1], currentTimeItem: Constants.CLAIM_SEARCH_TIME_ITEMS[1],
}; };
@ -30,7 +29,7 @@ class TagPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {
@ -40,9 +39,10 @@ class TagPage extends React.PureComponent {
} }
onComponentFocused = () => { onComponentFocused = () => {
const { pushDrawerStack, setPlayerVisible, navigation } = this.props; const { navigation, pushDrawerStack, setPlayerVisible, sortByItem } = this.props;
this.setState({ tag: navigation.state.params.tag }); const { tag } = navigation.state.params;
pushDrawerStack(); this.setState({ tag, sortByItem, orderBy: getOrderBy(sortByItem) });
pushDrawerStack(Constants.DRAWER_ROUTE_TAG, navigation.state.params);
setPlayerVisible(); setPlayerVisible();
}; };
@ -59,22 +59,9 @@ class TagPage extends React.PureComponent {
} }
handleSortByItemSelected = item => { handleSortByItemSelected = item => {
let orderBy = []; const { setSortByItem } = this.props;
switch (item.name) { setSortByItem(item);
case Constants.SORT_BY_HOT: this.setState({ orderBy: getOrderBy(item), showSortPicker: false });
orderBy = Constants.DEFAULT_ORDER_BY;
break;
case Constants.SORT_BY_NEW:
orderBy = ['release_time'];
break;
case Constants.SORT_BY_TOP:
orderBy = [Constants.ORDER_BY_EFFECTIVE_AMOUNT];
break;
}
this.setState({ currentSortByItem: item, orderBy, showSortPicker: false });
}; };
handleTimeItemSelected = item => { handleTimeItemSelected = item => {
@ -82,8 +69,8 @@ class TagPage extends React.PureComponent {
}; };
render() { render() {
const { navigation } = this.props; const { navigation, sortByItem } = this.props;
const { tag, currentSortByItem, currentTimeItem, showSortPicker, showTimePicker } = this.state; const { tag, currentTimeItem, showSortPicker, showTimePicker } = this.state;
return ( return (
<View style={discoverStyle.container}> <View style={discoverStyle.container}>
@ -92,14 +79,14 @@ class TagPage extends React.PureComponent {
ListHeaderComponent={ ListHeaderComponent={
<View style={discoverStyle.tagTitleRow}> <View style={discoverStyle.tagTitleRow}>
<Text style={discoverStyle.tagPageTitle}>{formatTagTitle(tag)}</Text> <Text style={discoverStyle.tagPageTitle}>{formatTagTitle(tag)}</Text>
{Constants.SORT_BY_TOP === currentSortByItem.name && ( {Constants.SORT_BY_TOP === sortByItem.name && (
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}> <TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
<Text style={discoverStyle.tagSortText}>{currentTimeItem.label}</Text> <Text style={discoverStyle.tagSortText}>{currentTimeItem.label}</Text>
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} /> <Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
</TouchableOpacity> </TouchableOpacity>
)} )}
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}> <TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
<Text style={discoverStyle.tagSortText}>{currentSortByItem.label.split(' ')[0]}</Text> <Text style={discoverStyle.tagSortText}>{sortByItem.label.split(' ')[0]}</Text>
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} /> <Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
</TouchableOpacity> </TouchableOpacity>
</View> </View>
@ -117,7 +104,7 @@ class TagPage extends React.PureComponent {
title={__('Sort content by')} title={__('Sort content by')}
onOverlayPress={() => this.setState({ showSortPicker: false })} onOverlayPress={() => this.setState({ showSortPicker: false })}
onItemSelected={this.handleSortByItemSelected} onItemSelected={this.handleSortByItemSelected}
selectedItem={this.state.currentSortByItem} selectedItem={this.state.sortByItem}
items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS} items={Constants.CLAIM_SEARCH_SORT_BY_ITEMS}
/> />
)} )}

View file

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { View, ScrollView, Text } from 'react-native'; import { View, ScrollView, Text } from 'react-native';
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import TransactionList from 'component/transactionList'; import TransactionList from 'component/transactionList';
import UriBar from 'component/uriBar'; import UriBar from 'component/uriBar';
import walletStyle from 'styles/wallet'; import walletStyle from 'styles/wallet';
@ -10,7 +10,7 @@ class TransactionHistoryPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {

View file

@ -31,7 +31,7 @@ class TrendingPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {

View file

@ -1,11 +1,11 @@
import React from 'react'; import React from 'react';
import { Lbry } from 'lbry-redux'; import { Lbry } from 'lbry-redux';
import { ActivityIndicator, View, Text, TextInput } from 'react-native'; import { ActivityIndicator, NativeModules, View, Text, TextInput } from 'react-native';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import Button from 'component/button'; import Button from 'component/button';
import Link from 'component/link'; import Link from 'component/link';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import firstRunStyle from 'styles/firstRun'; import firstRunStyle from 'styles/firstRun';
import rewardStyle from 'styles/reward'; import rewardStyle from 'styles/reward';
@ -44,6 +44,7 @@ class EmailVerifyPage extends React.PureComponent {
notify({ message: String(emailNewErrorMessage), isError: true }); notify({ message: String(emailNewErrorMessage), isError: true });
this.setState({ verifyStarted: false }); this.setState({ verifyStarted: false });
} else { } else {
NativeModules.Firebase.track('email_added', { email: this.state.email });
this.setState({ phase: Constants.PHASE_VERIFICATION }); this.setState({ phase: Constants.PHASE_VERIFICATION });
if (setEmailVerificationPhase) { if (setEmailVerificationPhase) {
setEmailVerificationPhase(true); setEmailVerificationPhase(true);

View file

@ -4,7 +4,7 @@ import { ActivityIndicator, Linking, NativeModules, Text, TouchableOpacity, View
import { NavigationActions, StackActions } from 'react-navigation'; import { NavigationActions, StackActions } from 'react-navigation';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import EmailVerifyPage from './internal/email-verify-page'; import EmailVerifyPage from './internal/email-verify-page';
import ManualVerifyPage from './internal/manual-verify-page'; import ManualVerifyPage from './internal/manual-verify-page';
import PhoneVerifyPage from './internal/phone-verify-page'; import PhoneVerifyPage from './internal/phone-verify-page';
@ -68,6 +68,9 @@ class VerificationScreen extends React.PureComponent {
if (this.state.isEmailVerified && this.state.isRewardApproved) { if (this.state.isEmailVerified && this.state.isRewardApproved) {
// verification steps already completed // verification steps already completed
// simply navigate back to the rewards page // simply navigate back to the rewards page
if (user.primary_email) {
NativeModules.Firebase.track('reward_eligibility_completed', { email: user.primary_email });
}
navigation.goBack(); navigation.goBack();
} }
} }

View file

@ -9,7 +9,7 @@ import WalletSyncDriver from 'component/walletSyncDriver';
import Button from 'component/button'; import Button from 'component/button';
import Link from 'component/link'; import Link from 'component/link';
import UriBar from 'component/uriBar'; import UriBar from 'component/uriBar';
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import walletStyle from 'styles/wallet'; import walletStyle from 'styles/wallet';
class WalletPage extends React.PureComponent { class WalletPage extends React.PureComponent {
@ -17,7 +17,7 @@ class WalletPage extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { navigation } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused); // this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
} }
componentWillUnmount() { componentWillUnmount() {

View file

@ -1,9 +1,9 @@
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
export const doPushDrawerStack = routeName => dispatch => export const doPushDrawerStack = (routeName, params) => dispatch =>
dispatch({ dispatch({
type: Constants.ACTION_PUSH_DRAWER_STACK, type: Constants.ACTION_PUSH_DRAWER_STACK,
data: routeName, data: { routeName, params },
}); });
export const doPopDrawerStack = () => dispatch => export const doPopDrawerStack = () => dispatch =>

View file

@ -1,4 +1,5 @@
import { ACTIONS } from 'lbry-redux'; import { ACTIONS } from 'lbry-redux';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
export function doSetClientSetting(key, value) { export function doSetClientSetting(key, value) {
return dispatch => { return dispatch => {
@ -15,3 +16,14 @@ export function doSetClientSetting(key, value) {
} }
}; };
} }
export function doSetSortByItem(item) {
return dispatch => {
dispatch({
type: Constants.ACTION_SORT_BY_ITEM_CHANGED,
data: {
name: item.name,
},
});
};
}

View file

@ -1,8 +1,8 @@
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
const reducers = {}; const reducers = {};
const defaultState = { const defaultState = {
stack: [Constants.DRAWER_ROUTE_DISCOVER], // Discover is always the first drawer route stack: [{ route: Constants.DRAWER_ROUTE_DISCOVER, params: {} }], // Discover is always the first drawer route
playerVisible: false, playerVisible: false,
currentRoute: null, currentRoute: null,
}; };
@ -13,11 +13,11 @@ reducers[Constants.ACTION_SET_PLAYER_VISIBLE] = (state, action) =>
}); });
reducers[Constants.ACTION_PUSH_DRAWER_STACK] = (state, action) => { reducers[Constants.ACTION_PUSH_DRAWER_STACK] = (state, action) => {
const routeName = action.data; const { routeName, params } = action.data;
const newStack = state.stack.slice(); const newStack = state.stack.slice();
if (routeName !== newStack[newStack.length - 1]) { if (routeName !== newStack[newStack.length - 1].route) {
newStack.push(routeName); newStack.push({ route: routeName, params });
} }
return { return {

View file

@ -1,8 +1,10 @@
import { ACTIONS } from 'lbry-redux'; import { ACTIONS } from 'lbry-redux';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
const reducers = {}; const reducers = {};
const defaultState = { const defaultState = {
clientSettings: {}, clientSettings: {},
sortByItemName: Constants.SORT_BY_HOT,
}; };
reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => { reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => {
@ -16,6 +18,11 @@ reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => {
}); });
}; };
reducers[Constants.ACTION_SORT_BY_ITEM_CHANGED] = (state, action) =>
Object.assign({}, state, {
sortByItemName: action.data.name,
});
export default function reducer(state = defaultState, action) { export default function reducer(state = defaultState, action) {
const handler = reducers[action.type]; const handler = reducers[action.type];
if (handler) return handler(state, action); if (handler) return handler(state, action);

View file

@ -1,5 +1,6 @@
import { SETTINGS } from 'lbry-redux'; import { SETTINGS } from 'lbry-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { getSortByItemForName } from 'utils/helper';
const selectState = state => state.settings || {}; const selectState = state => state.settings || {};
@ -13,6 +14,11 @@ export const selectClientSettings = createSelector(
state => state.clientSettings || {} state => state.clientSettings || {}
); );
export const selectSortByItem = createSelector(
selectState,
state => getSortByItemForName(state.sortByItemName)
);
export const makeSelectClientSetting = setting => export const makeSelectClientSetting = setting =>
createSelector( createSelector(
selectClientSettings, selectClientSettings,

View file

@ -66,15 +66,21 @@ const channelPageStyle = StyleSheet.create({
fontFamily: 'Inter-UI-Regular', fontFamily: 'Inter-UI-Regular',
fontSize: 18, fontSize: 18,
}, },
subscribeButtonContainer: {
position: 'absolute',
flexDirection: 'row',
left: 8,
bottom: -90,
zIndex: 100,
},
subscribeButton: { subscribeButton: {
alignSelf: 'flex-start', alignSelf: 'flex-start',
backgroundColor: Colors.White, backgroundColor: Colors.White,
paddingLeft: 16, paddingLeft: 16,
paddingRight: 16, paddingRight: 16,
position: 'absolute', },
right: 8, bellButton: {
bottom: -88, marginLeft: 8,
zIndex: 100,
}, },
cover: { cover: {
width: '100%', width: '100%',
@ -120,6 +126,7 @@ const channelPageStyle = StyleSheet.create({
marginBottom: 24, marginBottom: 24,
}, },
aboutScrollContent: { aboutScrollContent: {
paddingTop: 52,
padding: 24, padding: 24,
}, },
aboutTitle: { aboutTitle: {

View file

@ -10,6 +10,7 @@ const Colors = {
BrighterLbryGreen: '#40b887', BrighterLbryGreen: '#40b887',
NextLbryGreen: '#38d9a9', NextLbryGreen: '#38d9a9',
TagGreen: '#e3f6f1', TagGreen: '#e3f6f1',
TagGrape: '#da77f255',
LightGrey: '#cccccc', LightGrey: '#cccccc',
LighterGrey: '#e5e5e5', LighterGrey: '#e5e5e5',
Orange: '#ffbb00', Orange: '#ffbb00',

View file

@ -121,6 +121,12 @@ const discoverStyle = StyleSheet.create({
marginTop: 4, marginTop: 4,
color: Colors.LbryGreen, color: Colors.LbryGreen,
}, },
anonChannelName: {
fontFamily: 'Inter-UI-SemiBold',
fontSize: 12,
marginTop: 4,
color: Colors.DescriptionGrey,
},
downloadedIcon: { downloadedIcon: {
position: 'absolute', position: 'absolute',
right: 8, right: 8,

View file

@ -289,6 +289,7 @@ const filePageStyle = StyleSheet.create({
}, },
tipAmountInput: { tipAmountInput: {
alignSelf: 'flex-start', alignSelf: 'flex-start',
textAlign: 'right',
width: 80, width: 80,
fontSize: 16, fontSize: 16,
letterSpacing: 1, letterSpacing: 1,

View file

@ -114,6 +114,7 @@ const publishStyle = StyleSheet.create({
width: 80, width: 80,
fontFamily: 'Inter-UI-Regular', fontFamily: 'Inter-UI-Regular',
fontSize: 16, fontSize: 16,
textAlign: 'right',
}, },
currency: { currency: {
fontFamily: 'Inter-UI-Regular', fontFamily: 'Inter-UI-Regular',

View file

@ -30,6 +30,14 @@ const tagStyle = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
flexWrap: 'wrap', flexWrap: 'wrap',
}, },
nsfwTagsContainer: {
marginTop: 8,
},
nsfwTagsTitle: {
fontFamily: 'Inter-UI-Regular',
fontSize: 16,
marginBottom: 4,
},
}); });
export default tagStyle; export default tagStyle;

View file

@ -154,11 +154,12 @@ export function navigateBack(navigation, drawerStack, popDrawerStack) {
} }
const target = drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0]; const target = drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0];
const { route, params } = target;
navigation.goBack(navigation.state.key); navigation.goBack(navigation.state.key);
if (DrawerRoutes.indexOf(target) === -1 && isURIValid(target)) { if (DrawerRoutes.indexOf(route) === -1 && isURIValid(route)) {
navigateToUri(navigation, target, null, true); navigateToUri(navigation, route, null, true);
} else { } else {
navigation.navigate({ routeName: target }); navigation.navigate({ routeName: route, params });
} }
} }
@ -166,13 +167,15 @@ export function dispatchNavigateBack(dispatch, nav, drawerStack) {
dispatch(doPopDrawerStack()); dispatch(doPopDrawerStack());
const target = drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0]; const target = drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0];
const { route } = target;
dispatch(NavigationActions.back()); dispatch(NavigationActions.back());
if (DrawerRoutes.indexOf(route) === -1 && isURIValid(route)) {
if (DrawerRoutes.indexOf(target) === -1 && isURIValid(target)) { dispatchNavigateToUri(dispatch, nav, route, true);
dispatchNavigateToUri(dispatch, nav, target, true);
} else { } else {
const newTarget = drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0];
const navigateAction = NavigationActions.navigate({ const navigateAction = NavigationActions.navigate({
routeName: drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0], routeName: newTarget.route,
params: newTarget.params,
}); });
dispatch(navigateAction); dispatch(navigateAction);
} }
@ -204,6 +207,35 @@ export function formatTagName(name) {
return name.substring(0, 7) + '...'; return name.substring(0, 7) + '...';
} }
export function getSortByItemForName(name) {
for (let i = 0; i < Constants.CLAIM_SEARCH_SORT_BY_ITEMS.length; i++) {
if (name === Constants.CLAIM_SEARCH_SORT_BY_ITEMS[i].name) {
return Constants.CLAIM_SEARCH_SORT_BY_ITEMS[i];
}
}
return null;
}
export function getOrderBy(item) {
let orderBy = [];
switch (item.name) {
case Constants.SORT_BY_HOT:
orderBy = Constants.DEFAULT_ORDER_BY;
break;
case Constants.SORT_BY_NEW:
orderBy = ['release_time'];
break;
case Constants.SORT_BY_TOP:
orderBy = [Constants.ORDER_BY_EFFECTIVE_AMOUNT];
break;
}
return orderBy;
}
// i18n placeholder until we find a good react-native i18n module // i18n placeholder until we find a good react-native i18n module
export function __(str) { export function __(str) {
return str; return str;