Misc tweaks and fixes (#13)
* channel icon auto thumbs. fix infinite claim list reload. * tweak last page check * additional tweaks and fixes before release
This commit is contained in:
parent
89222bc9ee
commit
38618080a1
23 changed files with 212 additions and 119 deletions
|
@ -144,7 +144,7 @@ const drawer = createDrawerNavigator(
|
||||||
drawerIcon: ({ tintColor }) => <Icon name="fire" size={drawerIconSize} style={{ color: tintColor }} />,
|
drawerIcon: ({ tintColor }) => <Icon name="fire" size={drawerIconSize} style={{ color: tintColor }} />,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MySubscriptionsStack: {
|
Subscriptions: {
|
||||||
screen: SubscriptionsPage,
|
screen: SubscriptionsPage,
|
||||||
navigationOptions: {
|
navigationOptions: {
|
||||||
title: 'Subscriptions',
|
title: 'Subscriptions',
|
||||||
|
@ -270,21 +270,11 @@ class AppWithNavigationState extends React.Component {
|
||||||
'hardwareBackPress',
|
'hardwareBackPress',
|
||||||
function() {
|
function() {
|
||||||
const { dispatch, nav, drawerStack } = this.props;
|
const { dispatch, nav, drawerStack } = this.props;
|
||||||
// There should be a better way to check this
|
if (drawerStack.length > 1) {
|
||||||
if (nav.routes.length > 0) {
|
dispatchNavigateBack(dispatch, nav, drawerStack);
|
||||||
if (nav.routes[0].routeName === 'Main') {
|
return true;
|
||||||
const mainRoute = nav.routes[0];
|
|
||||||
if (
|
|
||||||
mainRoute.index > 0 ||
|
|
||||||
mainRoute.routes[0].index > 0 /* Discover stack index */ ||
|
|
||||||
mainRoute.routes[4].index > 0 /* Wallet stack index */ ||
|
|
||||||
mainRoute.index >= 5 /* Settings and About screens */
|
|
||||||
) {
|
|
||||||
dispatchNavigateBack(dispatch, nav, drawerStack);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doResolveUri, makeSelectClaimForUri, makeSelectThumbnailForUri, makeSelectIsUriResolving } from 'lbry-redux';
|
import {
|
||||||
|
doResolveUri,
|
||||||
|
makeSelectClaimForUri,
|
||||||
|
makeSelectThumbnailForUri,
|
||||||
|
makeSelectTitleForUri,
|
||||||
|
makeSelectIsUriResolving,
|
||||||
|
} from 'lbry-redux';
|
||||||
import ChannelIconItem from './view';
|
import ChannelIconItem from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
|
title: makeSelectTitleForUri(props.uri)(state),
|
||||||
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,35 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ActivityIndicator, Image, Text, TouchableOpacity, View } from 'react-native';
|
import { ActivityIndicator, Image, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
|
import autothumbStyle from 'styles/autothumb';
|
||||||
import channelIconStyle from 'styles/channelIcon';
|
import channelIconStyle from 'styles/channelIcon';
|
||||||
|
|
||||||
export default class ChannelIconItem extends React.PureComponent {
|
export default class ChannelIconItem extends React.PureComponent {
|
||||||
|
static AUTO_THUMB_STYLES = [
|
||||||
|
autothumbStyle.autothumbPurple,
|
||||||
|
autothumbStyle.autothumbRed,
|
||||||
|
autothumbStyle.autothumbPink,
|
||||||
|
autothumbStyle.autothumbIndigo,
|
||||||
|
autothumbStyle.autothumbBlue,
|
||||||
|
autothumbStyle.autothumbLightBlue,
|
||||||
|
autothumbStyle.autothumbCyan,
|
||||||
|
autothumbStyle.autothumbTeal,
|
||||||
|
autothumbStyle.autothumbGreen,
|
||||||
|
autothumbStyle.autothumbYellow,
|
||||||
|
autothumbStyle.autothumbOrange,
|
||||||
|
];
|
||||||
|
|
||||||
|
state = {
|
||||||
|
autoStyle: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.setState({
|
||||||
|
autoStyle:
|
||||||
|
ChannelIconItem.AUTO_THUMB_STYLES[Math.floor(Math.random() * ChannelIconItem.AUTO_THUMB_STYLES.length)],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { claim, isPlaceholder, uri, resolveUri } = this.props;
|
const { claim, isPlaceholder, uri, resolveUri } = this.props;
|
||||||
if (!claim && !isPlaceholder) {
|
if (!claim && !isPlaceholder) {
|
||||||
|
@ -13,6 +39,8 @@ export default class ChannelIconItem extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claim, isPlaceholder, isResolvingUri, onPress, thumbnail, title } = this.props;
|
const { claim, isPlaceholder, isResolvingUri, onPress, thumbnail, title } = this.props;
|
||||||
|
const displayName = title || (claim ? claim.name : '');
|
||||||
|
const substrIndex = displayName.startsWith('@') ? 1 : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={channelIconStyle.container} onPress={onPress}>
|
<TouchableOpacity style={channelIconStyle.container} onPress={onPress}>
|
||||||
|
@ -25,6 +53,7 @@ export default class ChannelIconItem extends React.PureComponent {
|
||||||
style={[
|
style={[
|
||||||
channelIconStyle.thumbnailContainer,
|
channelIconStyle.thumbnailContainer,
|
||||||
isPlaceholder ? channelIconStyle.borderedThumbnailContainer : null,
|
isPlaceholder ? channelIconStyle.borderedThumbnailContainer : null,
|
||||||
|
isPlaceholder ? null : this.state.autoStyle,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{isPlaceholder && (
|
{isPlaceholder && (
|
||||||
|
@ -32,17 +61,18 @@ export default class ChannelIconItem extends React.PureComponent {
|
||||||
<Text style={channelIconStyle.placeholderText}>ALL</Text>
|
<Text style={channelIconStyle.placeholderText}>ALL</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{!isPlaceholder && (
|
{!isPlaceholder && thumbnail && (
|
||||||
<Image
|
<Image style={channelIconStyle.thumbnail} resizeMode={'cover'} source={{ uri: thumbnail }} />
|
||||||
style={channelIconStyle.thumbnail}
|
)}
|
||||||
resizeMode={'cover'}
|
{!isPlaceholder && !thumbnail && (
|
||||||
source={thumbnail ? { uri: thumbnail } : require('../../assets/default_avatar.jpg')}
|
<Text style={channelIconStyle.autothumbCharacter}>
|
||||||
/>
|
{displayName.substring(substrIndex, substrIndex + 1).toUpperCase()}
|
||||||
|
</Text>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
{!isPlaceholder && (
|
{!isPlaceholder && (
|
||||||
<Text style={channelIconStyle.title} numberOfLines={1}>
|
<Text style={channelIconStyle.title} numberOfLines={1}>
|
||||||
{title || (claim ? claim.name : '')}
|
{displayName}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
|
@ -22,6 +22,7 @@ class ClaimList extends React.PureComponent {
|
||||||
currentPage: 1, // initial page load is page 1
|
currentPage: 1, // initial page load is page 1
|
||||||
subscriptionsView: false, // whether or not this claim list is for subscriptions
|
subscriptionsView: false, // whether or not this claim list is for subscriptions
|
||||||
trendingForAllView: false,
|
trendingForAllView: false,
|
||||||
|
lastPageReached: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -73,9 +74,10 @@ class ClaimList extends React.PureComponent {
|
||||||
channelIds: prevChannelIds,
|
channelIds: prevChannelIds,
|
||||||
trendingForAll: prevTrendingForAll,
|
trendingForAll: prevTrendingForAll,
|
||||||
time: prevTime,
|
time: prevTime,
|
||||||
|
claimSearchUris: prevClaimSearchUris,
|
||||||
showNsfwContent,
|
showNsfwContent,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { orderBy, tags, channelIds, trendingForAll, time } = nextProps;
|
const { orderBy, tags, channelIds, trendingForAll, time, claimSearchUris } = nextProps;
|
||||||
if (
|
if (
|
||||||
!_.isEqual(orderBy, prevOrderBy) ||
|
!_.isEqual(orderBy, prevOrderBy) ||
|
||||||
!_.isEqual(tags, prevTags) ||
|
!_.isEqual(tags, prevTags) ||
|
||||||
|
@ -119,6 +121,18 @@ class ClaimList extends React.PureComponent {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(this.state.subscriptionsView || this.state.trendingForAllView) &&
|
||||||
|
this.state.currentPage > 1 &&
|
||||||
|
prevClaimSearchUris &&
|
||||||
|
prevClaimSearchUris.length > 0 &&
|
||||||
|
_.isEqual(prevClaimSearchUris, claimSearchUris)
|
||||||
|
) {
|
||||||
|
this.setState({ lastPageReached: true });
|
||||||
|
} else {
|
||||||
|
this.setState({ lastPageReached: false });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getReleaseTimeOption = time => {
|
getReleaseTimeOption = time => {
|
||||||
|
@ -130,6 +144,10 @@ class ClaimList extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleVerticalEndReached = () => {
|
handleVerticalEndReached = () => {
|
||||||
|
if (this.state.lastPageReached) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// fetch more content
|
// fetch more content
|
||||||
const {
|
const {
|
||||||
channelIds,
|
channelIds,
|
||||||
|
@ -240,6 +258,17 @@ class ClaimList extends React.PureComponent {
|
||||||
|
|
||||||
if (Constants.ORIENTATION_VERTICAL === orientation) {
|
if (Constants.ORIENTATION_VERTICAL === orientation) {
|
||||||
const data = subscriptionsView || trendingForAllView ? claimSearchUris : uris;
|
const data = subscriptionsView || trendingForAllView ? claimSearchUris : uris;
|
||||||
|
|
||||||
|
if (!loading && !claimSearchLoading && (!data || data.length === 0)) {
|
||||||
|
return (
|
||||||
|
<View style={style}>
|
||||||
|
<Text style={claimListStyle.noContentText}>
|
||||||
|
No content to display at this time. Please check back later.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={style}>
|
<View style={style}>
|
||||||
<FlatList
|
<FlatList
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
makeSelectTitleForUri,
|
makeSelectTitleForUri,
|
||||||
makeSelectIsUriResolving,
|
makeSelectIsUriResolving,
|
||||||
makeSelectClaimIsNsfw,
|
makeSelectClaimIsNsfw,
|
||||||
|
makeSelectShortUrlForUri,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { selectRewardContentClaimIds } from 'lbryinc';
|
import { selectRewardContentClaimIds } from 'lbryinc';
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
|
@ -20,6 +21,7 @@ const select = (state, props) => ({
|
||||||
rewardedContentClaimIds: selectRewardContentClaimIds(state, props),
|
rewardedContentClaimIds: selectRewardContentClaimIds(state, props),
|
||||||
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
||||||
obscureNsfw: !selectShowNsfw(state),
|
obscureNsfw: !selectShowNsfw(state),
|
||||||
|
shortUrl: makeSelectShortUrlForUri(props.uri)(state),
|
||||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||||
title: makeSelectTitleForUri(props.uri)(state),
|
title: makeSelectTitleForUri(props.uri)(state),
|
||||||
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
|
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
|
||||||
|
|
|
@ -30,12 +30,12 @@ class FileItem extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateToFileUri = () => {
|
navigateToFileUri = () => {
|
||||||
const { navigation, uri } = this.props;
|
const { navigation, uri, shortUrl } = this.props;
|
||||||
const normalizedUri = normalizeURI(uri);
|
const normalizedUri = normalizeURI(uri);
|
||||||
if (NativeModules.Firebase) {
|
if (NativeModules.Firebase) {
|
||||||
NativeModules.Firebase.track('explore_click', { uri: normalizedUri });
|
NativeModules.Firebase.track('explore_click', { uri: normalizedUri, short_url: shortUrl });
|
||||||
}
|
}
|
||||||
navigateToUri(navigation, normalizedUri);
|
navigateToUri(navigation, shortUrl || uri);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -57,6 +57,11 @@ class FileItem extends React.PureComponent {
|
||||||
titleBeforeThumbnail,
|
titleBeforeThumbnail,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
if (claim && claim.value_type === 'channel') {
|
||||||
|
// don't display channels in the lists on the Explore page
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const uri = normalizeURI(this.props.uri);
|
const uri = normalizeURI(this.props.uri);
|
||||||
const obscure = obscureNsfw && nsfw;
|
const obscure = obscureNsfw && nsfw;
|
||||||
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
|
@ -64,6 +69,7 @@ class FileItem extends React.PureComponent {
|
||||||
const channelName = signingChannel ? signingChannel.name : null;
|
const channelName = signingChannel ? signingChannel.name : null;
|
||||||
const channelClaimId = signingChannel ? signingChannel.claim_id : null;
|
const channelClaimId = signingChannel ? signingChannel.claim_id : null;
|
||||||
const fullChannelUri = channelClaimId ? `${channelName}#${channelClaimId}` : channelName;
|
const fullChannelUri = channelClaimId ? `${channelName}#${channelClaimId}` : channelName;
|
||||||
|
const shortChannelUri = signingChannel ? signingChannel.short_url : null;
|
||||||
const height = claim ? claim.height : null;
|
const height = claim ? claim.height : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -104,7 +110,7 @@ class FileItem extends React.PureComponent {
|
||||||
style={discoverStyle.channelName}
|
style={discoverStyle.channelName}
|
||||||
text={channelName}
|
text={channelName}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
navigateToUri(navigation, normalizeURI(fullChannelUri));
|
navigateToUri(navigation, normalizeURI(shortChannelUri || fullChannelUri));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -2,24 +2,25 @@ import React from 'react';
|
||||||
import { ActivityIndicator, Image, Text, View } from 'react-native';
|
import { ActivityIndicator, Image, Text, View } from 'react-native';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import FastImage from 'react-native-fast-image';
|
import FastImage from 'react-native-fast-image';
|
||||||
|
import autothumbStyle from 'styles/autothumb';
|
||||||
import fileItemMediaStyle from 'styles/fileItemMedia';
|
import fileItemMediaStyle from 'styles/fileItemMedia';
|
||||||
|
|
||||||
class FileItemMedia extends React.PureComponent {
|
class FileItemMedia extends React.PureComponent {
|
||||||
static AUTO_THUMB_STYLES = [
|
static AUTO_THUMB_STYLES = [
|
||||||
fileItemMediaStyle.autothumbPurple,
|
autothumbStyle.autothumbPurple,
|
||||||
fileItemMediaStyle.autothumbRed,
|
autothumbStyle.autothumbRed,
|
||||||
fileItemMediaStyle.autothumbPink,
|
autothumbStyle.autothumbPink,
|
||||||
fileItemMediaStyle.autothumbIndigo,
|
autothumbStyle.autothumbIndigo,
|
||||||
fileItemMediaStyle.autothumbBlue,
|
autothumbStyle.autothumbBlue,
|
||||||
fileItemMediaStyle.autothumbLightBlue,
|
autothumbStyle.autothumbLightBlue,
|
||||||
fileItemMediaStyle.autothumbCyan,
|
autothumbStyle.autothumbCyan,
|
||||||
fileItemMediaStyle.autothumbTeal,
|
autothumbStyle.autothumbTeal,
|
||||||
fileItemMediaStyle.autothumbGreen,
|
autothumbStyle.autothumbGreen,
|
||||||
fileItemMediaStyle.autothumbYellow,
|
autothumbStyle.autothumbYellow,
|
||||||
fileItemMediaStyle.autothumbOrange,
|
autothumbStyle.autothumbOrange,
|
||||||
];
|
];
|
||||||
|
|
||||||
state: {
|
state = {
|
||||||
imageLoadFailed: false,
|
imageLoadFailed: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ class FileItemMedia extends React.PureComponent {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thumbnail.substring(0, 7) != 'http://' && thumbnail.substring(0, 8) != 'https://') {
|
if (thumbnail.substring(0, 7) !== 'http://' && thumbnail.substring(0, 8) !== 'https://') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +68,7 @@ class FileItemMedia extends React.PureComponent {
|
||||||
if (blurRadius > 0) {
|
if (blurRadius > 0) {
|
||||||
// No blur radius support in FastImage yet
|
// No blur radius support in FastImage yet
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image source={{ uri: thumbnail }} blurRadius={blurRadius} resizeMode={resizeMode || 'cover'} style={style} />
|
||||||
source={{ uri: thumbnail }}
|
|
||||||
blurRadius={blurRadius}
|
|
||||||
resizeMode={resizeMode ? resizeMode : 'cover'}
|
|
||||||
style={style}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +83,7 @@ class FileItemMedia extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[style ? style : fileItemMediaStyle.autothumb, atStyle]}>
|
<View style={[style || fileItemMediaStyle.autothumb, atStyle]}>
|
||||||
{isResolvingUri && (
|
{isResolvingUri && (
|
||||||
<View style={fileItemMediaStyle.resolving}>
|
<View style={fileItemMediaStyle.resolving}>
|
||||||
<ActivityIndicator color={Colors.White} size={'large'} />
|
<ActivityIndicator color={Colors.White} size={'large'} />
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
makeSelectFileInfoForUri,
|
makeSelectFileInfoForUri,
|
||||||
makeSelectIsUriResolving,
|
makeSelectIsUriResolving,
|
||||||
makeSelectClaimIsNsfw,
|
makeSelectClaimIsNsfw,
|
||||||
|
makeSelectShortUrlForUri,
|
||||||
makeSelectTitleForUri,
|
makeSelectTitleForUri,
|
||||||
makeSelectThumbnailForUri,
|
makeSelectThumbnailForUri,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
|
@ -23,6 +24,7 @@ const select = (state, props) => ({
|
||||||
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
|
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
|
||||||
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
||||||
obscureNsfw: !selectShowNsfw(state),
|
obscureNsfw: !selectShowNsfw(state),
|
||||||
|
shortUrl: makeSelectShortUrlForUri(props.uri)(state),
|
||||||
title: makeSelectTitleForUri(props.uri)(state),
|
title: makeSelectTitleForUri(props.uri)(state),
|
||||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
|
@ -42,8 +42,8 @@ class FileListItem extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultOnPress = () => {
|
defaultOnPress = () => {
|
||||||
const { navigation, uri } = this.props;
|
const { autoplay, navigation, uri, shortUrl } = this.props;
|
||||||
navigateToUri(navigation, uri);
|
navigateToUri(navigation, shortUrl || uri, { autoplay });
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -70,7 +70,7 @@ class FileListItem extends React.PureComponent {
|
||||||
const obscure = obscureNsfw && 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, shortChannelUri, shouldHide, signingChannel;
|
||||||
if (claim) {
|
if (claim) {
|
||||||
name = claim.name;
|
name = claim.name;
|
||||||
signingChannel = claim.signing_channel;
|
signingChannel = claim.signing_channel;
|
||||||
|
@ -78,14 +78,18 @@ class FileListItem extends React.PureComponent {
|
||||||
height = claim.height;
|
height = claim.height;
|
||||||
channelClaimId = signingChannel ? signingChannel.claim_id : null;
|
channelClaimId = signingChannel ? signingChannel.claim_id : null;
|
||||||
fullChannelUri = channelClaimId ? `${channel}#${channelClaimId}` : channel;
|
fullChannelUri = channelClaimId ? `${channel}#${channelClaimId}` : channel;
|
||||||
|
shortChannelUri = signingChannel ? signingChannel.short_url : null;
|
||||||
|
|
||||||
if (blackListedOutpoints || filteredOutpoints) {
|
if (blackListedOutpoints || filteredOutpoints) {
|
||||||
const outpointsToHide = blackListedOutpoints.concat(filteredOutpoints);
|
const outpointsToHide = blackListedOutpoints.concat(filteredOutpoints);
|
||||||
shouldHide = outpointsToHide.some(outpoint => outpoint.txid === claim.txid && outpoint.nout === claim.nout);
|
shouldHide = outpointsToHide.some(outpoint => outpoint.txid === claim.txid && outpoint.nout === claim.nout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: hide channels on tag pages?
|
||||||
|
// shouldHide = 'channel' === claim.value_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldHide || (featuredResult && !isResolvingUri && !claim && !title && !name)) {
|
if (shouldHide || (!isResolvingUri && !claim) || (featuredResult && !isResolvingUri && !claim && !title && !name)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +134,7 @@ class FileListItem extends React.PureComponent {
|
||||||
style={fileListStyle.publisher}
|
style={fileListStyle.publisher}
|
||||||
text={channel}
|
text={channel}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
navigateToUri(navigation, normalizeURI(fullChannelUri));
|
navigateToUri(navigation, normalizeURI(shortChannelUri || fullChannelUri));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import TagSearch from 'component/tagSearch';
|
||||||
import modalTagSelectorStyle from 'styles/modalTagSelector';
|
import modalTagSelectorStyle from 'styles/modalTagSelector';
|
||||||
import { __ } from 'utils/helper';
|
import { __ } from 'utils/helper';
|
||||||
|
|
||||||
|
const minimumTags = 2;
|
||||||
|
|
||||||
export default class ModalTagSelector extends React.PureComponent {
|
export default class ModalTagSelector extends React.PureComponent {
|
||||||
handleAddTag = tag => {
|
handleAddTag = tag => {
|
||||||
if (!tag) {
|
if (!tag) {
|
||||||
|
@ -34,6 +36,12 @@ export default class ModalTagSelector extends React.PureComponent {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { followedTags, doToast } = this.props;
|
||||||
|
if (followedTags.length <= minimumTags) {
|
||||||
|
doToast({ message: __(`You can follow a minimum of ${minimumTags} tags.`) });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.props.doToggleTagFollow(tag);
|
this.props.doToggleTagFollow(tag);
|
||||||
if (window.persistor) {
|
if (window.persistor) {
|
||||||
window.persistor.flush();
|
window.persistor.flush();
|
||||||
|
|
|
@ -57,7 +57,7 @@ export default class RelatedContent extends React.PureComponent {
|
||||||
key={recommendedUri}
|
key={recommendedUri}
|
||||||
uri={recommendedUri}
|
uri={recommendedUri}
|
||||||
navigation={navigation}
|
navigation={navigation}
|
||||||
onPress={() => navigateToUri(navigation, recommendedUri, { autoplay: true })}
|
autoplay
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{isSearching && (
|
{isSearching && (
|
||||||
|
|
|
@ -20,9 +20,12 @@ class SuggestedSubscriptionItem extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claim, isResolvingUri, navigation, thumbnail, title, uri } = this.props;
|
const { claim, isResolvingUri, navigation, thumbnail, title, uri } = this.props;
|
||||||
let tags;
|
let shortUrl, tags;
|
||||||
if (claim && claim.value) {
|
if (claim) {
|
||||||
tags = claim.value.tags;
|
shortUrl = claim.short_url;
|
||||||
|
if (claim.value) {
|
||||||
|
tags = claim.value.tags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isResolvingUri) {
|
if (isResolvingUri) {
|
||||||
|
@ -54,7 +57,7 @@ class SuggestedSubscriptionItem extends React.PureComponent {
|
||||||
style={subscriptionsStyle.suggestedItemName}
|
style={subscriptionsStyle.suggestedItemName}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
text={claim.name}
|
text={claim.name}
|
||||||
onPress={() => navigateToUri(navigation, normalizeURI(uri))}
|
onPress={() => navigateToUri(navigation, normalizeURI(shortUrl || uri))}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{tags && (
|
{tags && (
|
||||||
|
|
|
@ -79,7 +79,6 @@ const Constants = {
|
||||||
|
|
||||||
FULL_ROUTE_NAME_DISCOVER: 'DiscoverStack',
|
FULL_ROUTE_NAME_DISCOVER: 'DiscoverStack',
|
||||||
FULL_ROUTE_NAME_TRENDING: 'TrendingStack',
|
FULL_ROUTE_NAME_TRENDING: 'TrendingStack',
|
||||||
FULL_ROUTE_NAME_MY_SUBSCRIPTIONS: 'MySubscriptionsStack',
|
|
||||||
FULL_ROUTE_NAME_WALLET: 'WalletStack',
|
FULL_ROUTE_NAME_WALLET: 'WalletStack',
|
||||||
|
|
||||||
ROUTE_FILE: 'File',
|
ROUTE_FILE: 'File',
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ActivityIndicator, Dimensions, Image, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
import { ActivityIndicator, Dimensions, Image, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import { TabView, SceneMap } from 'react-native-tab-view';
|
import { TabView, SceneMap } from 'react-native-tab-view';
|
||||||
|
import { normalizeURI } from 'lbry-redux';
|
||||||
import { navigateBack } from 'utils/helper';
|
import { navigateBack } from 'utils/helper';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
|
@ -164,15 +165,19 @@ class ChannelPage extends React.PureComponent {
|
||||||
const { fetching, claimsInChannel, claim, navigation, totalPages, uri, drawerStack, popDrawerStack } = this.props;
|
const { fetching, claimsInChannel, claim, navigation, totalPages, uri, drawerStack, popDrawerStack } = this.props;
|
||||||
const { name, permanent_url: permanentUrl } = claim;
|
const { name, permanent_url: permanentUrl } = claim;
|
||||||
|
|
||||||
let thumbnailUrl, coverUrl, title;
|
let thumbnailUrl, coverUrl, title, fullUri;
|
||||||
if (claim && claim.value) {
|
if (claim) {
|
||||||
title = claim.value.title;
|
if (claim.value) {
|
||||||
if (claim.value.cover) {
|
title = claim.value.title;
|
||||||
coverUrl = claim.value.cover.url;
|
if (claim.value.cover) {
|
||||||
}
|
coverUrl = claim.value.cover.url;
|
||||||
if (claim.value.thumbnail) {
|
}
|
||||||
thumbnailUrl = claim.value.thumbnail.url;
|
if (claim.value.thumbnail) {
|
||||||
|
thumbnailUrl = claim.value.thumbnail.url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fullUri = normalizeURI(`${claim.name}#${claim.claim_id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -208,10 +213,10 @@ class ChannelPage extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={channelPageStyle.subscribeButtonContainer}>
|
<View style={channelPageStyle.subscribeButtonContainer}>
|
||||||
<SubscribeButton style={channelPageStyle.subscribeButton} uri={uri} name={name} />
|
<SubscribeButton style={channelPageStyle.subscribeButton} uri={fullUri} name={name} />
|
||||||
<SubscribeNotificationButton
|
<SubscribeNotificationButton
|
||||||
style={[channelPageStyle.subscribeButton, channelPageStyle.bellButton]}
|
style={[channelPageStyle.subscribeButton, channelPageStyle.bellButton]}
|
||||||
uri={uri}
|
uri={fullUri}
|
||||||
name={name}
|
name={name}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -83,12 +83,7 @@ class DownloadsPage extends React.PureComponent {
|
||||||
style={downloadsStyle.scrollContainer}
|
style={downloadsStyle.scrollContainer}
|
||||||
contentContainerStyle={downloadsStyle.scrollPadding}
|
contentContainerStyle={downloadsStyle.scrollPadding}
|
||||||
renderItem={({ item }) => (
|
renderItem={({ item }) => (
|
||||||
<FileListItem
|
<FileListItem style={fileListStyle.item} uri={item} navigation={navigation} autoplay />
|
||||||
style={fileListStyle.item}
|
|
||||||
uri={item}
|
|
||||||
navigation={navigation}
|
|
||||||
onPress={() => navigateToUri(navigation, item, { autoplay: true })}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
data={downloadedUris}
|
data={downloadedUris}
|
||||||
keyExtractor={(item, index) => item}
|
keyExtractor={(item, index) => item}
|
||||||
|
|
|
@ -638,7 +638,10 @@ class FilePage extends React.PureComponent {
|
||||||
const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
|
const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
|
||||||
const canSendTip = this.state.tipAmount > 0;
|
const canSendTip = this.state.tipAmount > 0;
|
||||||
const fullChannelUri =
|
const fullChannelUri =
|
||||||
channelClaimId && channelClaimId.trim().length > 0 ? `${channelName}#${channelClaimId}` : channelName;
|
channelClaimId && channelClaimId.trim().length > 0
|
||||||
|
? normalizeURI(`${channelName}#${channelClaimId}`)
|
||||||
|
: normalizeURI(channelName);
|
||||||
|
const shortChannelUri = signingChannel ? signingChannel.short_url : null;
|
||||||
|
|
||||||
const playerStyle = [
|
const playerStyle = [
|
||||||
filePageStyle.player,
|
filePageStyle.player,
|
||||||
|
@ -855,7 +858,7 @@ class FilePage extends React.PureComponent {
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
ellipsizeMode={'tail'}
|
ellipsizeMode={'tail'}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
navigateToUri(navigation, normalizeURI(fullChannelUri));
|
navigateToUri(navigation, normalizeURI(shortChannelUri || fullChannelUri));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -113,13 +113,7 @@ class SearchPage extends React.PureComponent {
|
||||||
)}
|
)}
|
||||||
{uris && uris.length
|
{uris && uris.length
|
||||||
? uris.map(uri => (
|
? uris.map(uri => (
|
||||||
<FileListItem
|
<FileListItem key={uri} uri={uri} style={searchStyle.resultItem} navigation={navigation} />
|
||||||
key={uri}
|
|
||||||
uri={uri}
|
|
||||||
style={searchStyle.resultItem}
|
|
||||||
navigation={navigation}
|
|
||||||
onPress={() => navigateToUri(navigation, uri)}
|
|
||||||
/>
|
|
||||||
))
|
))
|
||||||
: null}
|
: null}
|
||||||
{(!uris || uris.length === 0) && (
|
{(!uris || uris.length === 0) && (
|
||||||
|
|
|
@ -74,7 +74,7 @@ class SubscriptionsPage 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_SUBSCRIPTIONS === currentRoute && currentRoute !== prevRoute) {
|
if (Constants.DRAWER_ROUTE_SUBSCRIPTIONS === currentRoute && currentRoute !== prevRoute) {
|
||||||
this.onComponentFocused();
|
this.onComponentFocused();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
39
src/styles/autothumb.js
Normal file
39
src/styles/autothumb.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
const autothumbStyle = StyleSheet.create({
|
||||||
|
autothumbPurple: {
|
||||||
|
backgroundColor: '#9c27b0',
|
||||||
|
},
|
||||||
|
autothumbRed: {
|
||||||
|
backgroundColor: '#e53935',
|
||||||
|
},
|
||||||
|
autothumbPink: {
|
||||||
|
backgroundColor: '#e91e63',
|
||||||
|
},
|
||||||
|
autothumbIndigo: {
|
||||||
|
backgroundColor: '#3f51b5',
|
||||||
|
},
|
||||||
|
autothumbBlue: {
|
||||||
|
backgroundColor: '#2196f3',
|
||||||
|
},
|
||||||
|
autothumbLightBlue: {
|
||||||
|
backgroundColor: '#039be5',
|
||||||
|
},
|
||||||
|
autothumbCyan: {
|
||||||
|
backgroundColor: '#00acc1',
|
||||||
|
},
|
||||||
|
autothumbTeal: {
|
||||||
|
backgroundColor: '#009688',
|
||||||
|
},
|
||||||
|
autothumbGreen: {
|
||||||
|
backgroundColor: '#43a047',
|
||||||
|
},
|
||||||
|
autothumbYellow: {
|
||||||
|
backgroundColor: '#ffeb3b',
|
||||||
|
},
|
||||||
|
autothumbOrange: {
|
||||||
|
backgroundColor: '#ffa726',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default autothumbStyle;
|
|
@ -18,6 +18,8 @@ const channelIconStyle = StyleSheet.create({
|
||||||
height: 80,
|
height: 80,
|
||||||
borderRadius: 160,
|
borderRadius: 160,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
borderedThumbnailContainer: {
|
borderedThumbnailContainer: {
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
|
@ -43,6 +45,11 @@ const channelIconStyle = StyleSheet.create({
|
||||||
marginTop: 4,
|
marginTop: 4,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
|
autothumbCharacter: {
|
||||||
|
fontFamily: 'Inter-UI-Regular',
|
||||||
|
fontSize: 48,
|
||||||
|
color: Colors.White,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default channelIconStyle;
|
export default channelIconStyle;
|
||||||
|
|
|
@ -11,6 +11,13 @@ const claimListStyle = StyleSheet.create({
|
||||||
verticalScrollContainer: {
|
verticalScrollContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
|
noContentText: {
|
||||||
|
color: Colors.DescriptionGrey,
|
||||||
|
fontFamily: 'Inter-UI-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
margin: 16,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
verticalScrollPadding: {
|
verticalScrollPadding: {
|
||||||
paddingBottom: 16,
|
paddingBottom: 16,
|
||||||
},
|
},
|
||||||
|
|
|
@ -80,7 +80,7 @@ const discoverStyle = StyleSheet.create({
|
||||||
marginTop: 12,
|
marginTop: 12,
|
||||||
marginLeft: 16,
|
marginLeft: 16,
|
||||||
marginRight: 16,
|
marginRight: 16,
|
||||||
marginBottom: 64,
|
marginBottom: 56,
|
||||||
},
|
},
|
||||||
footerTitle: {
|
footerTitle: {
|
||||||
fontFamily: 'Inter-UI-Regular',
|
fontFamily: 'Inter-UI-Regular',
|
||||||
|
|
|
@ -15,39 +15,6 @@ const fileItemMediaStyle = StyleSheet.create({
|
||||||
color: Colors.White,
|
color: Colors.White,
|
||||||
fontSize: 40,
|
fontSize: 40,
|
||||||
},
|
},
|
||||||
autothumbPurple: {
|
|
||||||
backgroundColor: '#9c27b0',
|
|
||||||
},
|
|
||||||
autothumbRed: {
|
|
||||||
backgroundColor: '#e53935',
|
|
||||||
},
|
|
||||||
autothumbPink: {
|
|
||||||
backgroundColor: '#e91e63',
|
|
||||||
},
|
|
||||||
autothumbIndigo: {
|
|
||||||
backgroundColor: '#3f51b5',
|
|
||||||
},
|
|
||||||
autothumbBlue: {
|
|
||||||
backgroundColor: '#2196f3',
|
|
||||||
},
|
|
||||||
autothumbLightBlue: {
|
|
||||||
backgroundColor: '#039be5',
|
|
||||||
},
|
|
||||||
autothumbCyan: {
|
|
||||||
backgroundColor: '#00acc1',
|
|
||||||
},
|
|
||||||
autothumbTeal: {
|
|
||||||
backgroundColor: '#009688',
|
|
||||||
},
|
|
||||||
autothumbGreen: {
|
|
||||||
backgroundColor: '#43a047',
|
|
||||||
},
|
|
||||||
autothumbYellow: {
|
|
||||||
backgroundColor: '#ffeb3b',
|
|
||||||
},
|
|
||||||
autothumbOrange: {
|
|
||||||
backgroundColor: '#ffa726',
|
|
||||||
},
|
|
||||||
resolving: {
|
resolving: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
|
Loading…
Reference in a new issue