Fix release blockers (#10)

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

8
package-lock.json generated
View file

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

View file

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

View file

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

View file

@ -1,9 +1,9 @@
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 Button from 'component/button';
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 Link from 'component/link';
import channelSelectorStyle from 'styles/channelSelector';
@ -102,7 +102,7 @@ export default class ChannelSelector extends React.PureComponent {
const { balance, createChannel, onChannelChange, notify } = this.props;
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.' });
return;
}

View file

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

View file

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

View file

@ -50,13 +50,15 @@ class FileItem extends React.PureComponent {
style,
mediaStyle,
navigation,
nsfw,
obscureNsfw,
showDetails,
compactView,
titleBeforeThumbnail,
} = this.props;
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 signingChannel = claim ? claim.signing_channel : null;
const channelName = signingChannel ? signingChannel.name : null;
@ -75,7 +77,7 @@ class FileItem extends React.PureComponent {
<FileItemMedia
title={title}
thumbnail={thumbnail}
blurRadius={obscureNsfw ? 15 : 0}
blurRadius={obscure ? 15 : 0}
resizeMode="cover"
isResolvingUri={isResolvingUri}
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} />
</View>
)}
</TouchableOpacity>
{obscureNsfw && (
<NsfwOverlay onPress={() => navigation.navigate({ routeName: 'Settings', key: 'settingsPage' })} />
)}
{obscure && <NsfwOverlay onPress={() => navigation.navigate({ routeName: 'Settings', key: 'settingsPage' })} />}
</View>
);
}

View file

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

View file

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

View file

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

View file

@ -5,17 +5,27 @@ import Button from 'component/button';
import Colors from 'styles/colors';
class SubscribeNotificationButton extends React.PureComponent {
render() {
handlePress = () => {
const {
uri,
name,
doChannelSubscriptionEnableNotifications,
doChannelSubscriptionDisableNotifications,
doToast,
enabledChannelNotifications,
isSubscribed,
style,
} = 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) {
return null;
@ -31,23 +41,14 @@ class SubscribeNotificationButton extends React.PureComponent {
}
const shouldNotify = enabledChannelNotifications.indexOf(name) > -1;
const { claimName } = parseURI(uri);
return (
<Button
style={styles}
theme={'light'}
icon={shouldNotify ? 'bell-slash' : 'bell'}
solid={true}
onPress={() => {
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.' });
}
}}
solid
onPress={this.handlePress}
/>
);
}

View file

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

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

View file

@ -1,5 +1,6 @@
import React from 'react';
import { KeyboardAvoidingView, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { MATURE_TAGS } from 'lbry-redux';
import Tag from 'component/tag';
import tagStyle from 'styles/tag';
import Colors from 'styles/colors';
@ -66,7 +67,7 @@ export default class TagSearch extends React.PureComponent {
};
render() {
const { name, style, type, selectedTags = [] } = this.props;
const { name, style, type, selectedTags = [], showNsfwTags } = this.props;
return (
<View>
@ -85,6 +86,22 @@ export default class TagSearch extends React.PureComponent {
))}
</View>
</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 file

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

View file

@ -2,7 +2,7 @@ import React from 'react';
import { Lbry } from 'lbry-redux';
import { NativeModules, Text, View, ScrollView } from 'react-native';
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 PageHeader from 'component/pageHeader';
import aboutStyle from 'styles/about';
@ -18,7 +18,7 @@ class AboutPage extends React.PureComponent {
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
// this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
@ -105,7 +105,7 @@ class AboutPage extends React.PureComponent {
<Text style={aboutStyle.text}>Connected email</Text>
</View>
<View style={aboutStyle.col}>
<Text selectable={true} style={aboutStyle.valueText}>
<Text selectable style={aboutStyle.valueText}>
{userEmail}
</Text>
</View>
@ -125,7 +125,7 @@ class AboutPage extends React.PureComponent {
<Text style={aboutStyle.text}>App version</Text>
</View>
<View style={aboutStyle.col}>
<Text selectable={true} style={aboutStyle.valueText}>
<Text selectable style={aboutStyle.valueText}>
{this.state.appVersion}
</Text>
</View>
@ -136,7 +136,7 @@ class AboutPage extends React.PureComponent {
<Text style={aboutStyle.text}>Daemon (lbrynet)</Text>
</View>
<View style={aboutStyle.col}>
<Text selectable={true} style={aboutStyle.valueText}>
<Text selectable style={aboutStyle.valueText}>
{ver ? ver.lbrynet_version : loading}
</Text>
</View>
@ -147,7 +147,7 @@ class AboutPage extends React.PureComponent {
<Text style={aboutStyle.text}>Platform</Text>
</View>
<View style={aboutStyle.col}>
<Text selectable={true} style={aboutStyle.valueText}>
<Text selectable style={aboutStyle.valueText}>
{ver ? ver.platform : loading}
</Text>
</View>
@ -156,7 +156,7 @@ class AboutPage extends React.PureComponent {
<View style={aboutStyle.row}>
<View style={aboutStyle.col}>
<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}
</Text>
</View>

View file

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

View file

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

View file

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

View file

@ -21,7 +21,7 @@ class DownloadsPage extends React.PureComponent {
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
// this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
@ -44,7 +44,7 @@ class DownloadsPage extends React.PureComponent {
componentWillReceiveProps(nextProps) {
const { currentRoute } = nextProps;
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();
}
}

View file

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

View file

@ -4,7 +4,7 @@ import { ActivityIndicator, Linking, NativeModules, Text, TouchableOpacity, View
import { NavigationActions, StackActions } from 'react-navigation';
import AsyncStorage from '@react-native-community/async-storage';
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 WelcomePage from './internal/welcome-page';
import EmailCollectPage from './internal/email-collect-page';
@ -73,6 +73,7 @@ class FirstRunScreen extends React.PureComponent {
notify({ message: String(emailNewErrorMessage), isError: true });
} else {
// Request successful. Navigate to email verify page.
NativeModules.Firebase.track('email_added', { email: this.state.email });
this.showPage(Constants.FIRST_RUN_PAGE_EMAIL_VERIFY);
}
}
@ -228,7 +229,7 @@ class FirstRunScreen extends React.PureComponent {
onEmailChanged = 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 });
} else {
this.setState({ showSkip: false });
@ -236,14 +237,14 @@ class FirstRunScreen extends React.PureComponent {
};
onEmailViewLayout = phase => {
if ('collect' === phase) {
if (phase === 'collect') {
if (!this.state.emailCollectTracked) {
// we only want to track this once
this.setState({ emailCollectTracked: true }, () =>
NativeModules.Firebase.track('first_run_email_collect', null)
);
}
} else if ('verify' === phase) {
} else if (phase === 'verify') {
NativeModules.Firebase.track('first_run_email_verify', null);
}
@ -402,10 +403,10 @@ class FirstRunScreen extends React.PureComponent {
{Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT !== this.state.currentPage &&
Constants.FIRST_RUN_PAGE_EMAIL_VERIFY !== this.state.currentPage && (
<Text style={firstRunStyle.buttonText}>
{Constants.FIRST_RUN_PAGE_WALLET === this.state.currentPage ? 'Use LBRY' : 'Continue'} »
</Text>
)}
<Text style={firstRunStyle.buttonText}>
{Constants.FIRST_RUN_PAGE_WALLET === this.state.currentPage ? 'Use LBRY' : 'Continue'} »
</Text>
)}
</TouchableOpacity>
)}
</View>

View file

@ -15,7 +15,15 @@ import {
View,
} from 'react-native';
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 { RNCamera } from 'react-native-camera';
import { generateCombination } from 'gfycat-style-urls';
@ -116,7 +124,7 @@ class PublishPage extends React.PureComponent {
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
// this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
DeviceEventEmitter.addListener('onGalleryThumbnailsChecked', this.handleGalleryThumbnailsChecked);
}
@ -203,10 +211,6 @@ class PublishPage extends React.PureComponent {
}
const publishTags = tags.slice();
if (mature) {
publishTags.push('nsfw');
}
const publishParams = {
filePath: currentMedia.filePath,
bid: bid || 0.1,
@ -215,7 +219,7 @@ class PublishPage extends React.PureComponent {
thumbnail: thumbnail,
description: description || '',
language,
nsfw: mature,
nsfw: publishTags.some(tag => MATURE_TAGS.includes(tag)),
license,
licenseUrl: '',
otherLicenseDescription: '',
@ -654,7 +658,7 @@ class PublishPage extends React.PureComponent {
/>
))}
</View>
<TagSearch handleAddTag={this.handleAddTag} selectedTags={this.state.tags} />
<TagSearch handleAddTag={this.handleAddTag} selectedTags={this.state.tags} showNsfwTags />
</View>
<View style={publishStyle.card}>
@ -727,11 +731,6 @@ class PublishPage extends React.PureComponent {
{this.state.advancedMode && (
<View style={publishStyle.card}>
<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>
<Text style={publishStyle.cardText}>Language</Text>
<Picker

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@ import React from 'react';
import { SETTINGS } from 'lbry-redux';
import { Text, View, ScrollView, Switch, NativeModules } from 'react-native';
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 settingsStyle from 'styles/settings';
@ -15,7 +15,7 @@ class SettingsPage extends React.PureComponent {
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
// this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
import React from 'react';
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 UriBar from 'component/uriBar';
import walletStyle from 'styles/wallet';
@ -10,7 +10,7 @@ class TransactionHistoryPage extends React.PureComponent {
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
// this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {

View file

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

View file

@ -1,11 +1,11 @@
import React from 'react';
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 Button from 'component/button';
import Link from 'component/link';
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 rewardStyle from 'styles/reward';
@ -44,11 +44,12 @@ class EmailVerifyPage extends React.PureComponent {
notify({ message: String(emailNewErrorMessage), isError: true });
this.setState({ verifyStarted: false });
} else {
NativeModules.Firebase.track('email_added', { email: this.state.email });
this.setState({ phase: Constants.PHASE_VERIFICATION });
if (setEmailVerificationPhase) {
setEmailVerificationPhase(true);
}
//notify({ message: 'Please follow the instructions in the email sent to your address to continue.' });
// notify({ message: 'Please follow the instructions in the email sent to your address to continue.' });
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
}
}

View file

@ -4,7 +4,7 @@ import { ActivityIndicator, Linking, NativeModules, Text, TouchableOpacity, View
import { NavigationActions, StackActions } from 'react-navigation';
import AsyncStorage from '@react-native-community/async-storage';
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 ManualVerifyPage from './internal/manual-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) {
// verification steps already completed
// simply navigate back to the rewards page
if (user.primary_email) {
NativeModules.Firebase.track('reward_eligibility_completed', { email: user.primary_email });
}
navigation.goBack();
}
}

View file

@ -9,7 +9,7 @@ import WalletSyncDriver from 'component/walletSyncDriver';
import Button from 'component/button';
import Link from 'component/link';
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';
class WalletPage extends React.PureComponent {
@ -17,7 +17,7 @@ class WalletPage extends React.PureComponent {
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
// this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
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({
type: Constants.ACTION_PUSH_DRAWER_STACK,
data: routeName,
data: { routeName, params },
});
export const doPopDrawerStack = () => dispatch =>

View file

@ -1,4 +1,5 @@
import { ACTIONS } from 'lbry-redux';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
export function doSetClientSetting(key, value) {
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 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,
currentRoute: null,
};
@ -13,11 +13,11 @@ reducers[Constants.ACTION_SET_PLAYER_VISIBLE] = (state, action) =>
});
reducers[Constants.ACTION_PUSH_DRAWER_STACK] = (state, action) => {
const routeName = action.data;
const { routeName, params } = action.data;
const newStack = state.stack.slice();
if (routeName !== newStack[newStack.length - 1]) {
newStack.push(routeName);
if (routeName !== newStack[newStack.length - 1].route) {
newStack.push({ route: routeName, params });
}
return {

View file

@ -1,8 +1,10 @@
import { ACTIONS } from 'lbry-redux';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
const reducers = {};
const defaultState = {
clientSettings: {},
sortByItemName: Constants.SORT_BY_HOT,
};
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) {
const handler = reducers[action.type];
if (handler) return handler(state, action);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -30,6 +30,14 @@ const tagStyle = StyleSheet.create({
flexDirection: 'row',
flexWrap: 'wrap',
},
nsfwTagsContainer: {
marginTop: 8,
},
nsfwTagsTitle: {
fontFamily: 'Inter-UI-Regular',
fontSize: 16,
marginBottom: 4,
},
});
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 { route, params } = target;
navigation.goBack(navigation.state.key);
if (DrawerRoutes.indexOf(target) === -1 && isURIValid(target)) {
navigateToUri(navigation, target, null, true);
if (DrawerRoutes.indexOf(route) === -1 && isURIValid(route)) {
navigateToUri(navigation, route, null, true);
} else {
navigation.navigate({ routeName: target });
navigation.navigate({ routeName: route, params });
}
}
@ -166,13 +167,15 @@ export function dispatchNavigateBack(dispatch, nav, drawerStack) {
dispatch(doPopDrawerStack());
const target = drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0];
const { route } = target;
dispatch(NavigationActions.back());
if (DrawerRoutes.indexOf(target) === -1 && isURIValid(target)) {
dispatchNavigateToUri(dispatch, nav, target, true);
if (DrawerRoutes.indexOf(route) === -1 && isURIValid(route)) {
dispatchNavigateToUri(dispatch, nav, route, true);
} else {
const newTarget = drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0];
const navigateAction = NavigationActions.navigate({
routeName: drawerStack[drawerStack.length > 1 ? drawerStack.length - 2 : 0],
routeName: newTarget.route,
params: newTarget.params,
});
dispatch(navigateAction);
}
@ -204,6 +207,35 @@ export function formatTagName(name) {
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
export function __(str) {
return str;