show blocked message for blacklisted content
This commit is contained in:
parent
d921347d73
commit
51fcf04b0b
5 changed files with 184 additions and 134 deletions
|
@ -10,6 +10,7 @@ import {
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import {
|
import {
|
||||||
Lbry,
|
Lbry,
|
||||||
|
blacklistReducer,
|
||||||
claimsReducer,
|
claimsReducer,
|
||||||
costInfoReducer,
|
costInfoReducer,
|
||||||
fileInfoReducer,
|
fileInfoReducer,
|
||||||
|
@ -68,6 +69,7 @@ const navigatorReducer = (state = initialNavState, action) => {
|
||||||
|
|
||||||
const reducers = combineReducers({
|
const reducers = combineReducers({
|
||||||
auth: authReducer,
|
auth: authReducer,
|
||||||
|
blacklist: blacklistReducer,
|
||||||
claims: claimsReducer,
|
claims: claimsReducer,
|
||||||
costInfo: costInfoReducer,
|
costInfo: costInfoReducer,
|
||||||
fileInfo: fileInfoReducer,
|
fileInfo: fileInfoReducer,
|
||||||
|
|
|
@ -329,144 +329,170 @@ class FilePage extends React.PureComponent {
|
||||||
<ChannelPage uri={uri} navigation={navigation} />
|
<ChannelPage uri={uri} navigation={navigation} />
|
||||||
);
|
);
|
||||||
} else if (claim) {
|
} else if (claim) {
|
||||||
const completed = fileInfo && fileInfo.completed;
|
let isClaimBlackListed = false;
|
||||||
const title = metadata.title;
|
|
||||||
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
|
||||||
const description = metadata.description ? metadata.description : null;
|
|
||||||
const mediaType = Lbry.getMediaType(contentType);
|
|
||||||
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
|
||||||
const { height, channel_name: channelName, value } = claim;
|
|
||||||
const showActions = !this.state.fullscreenMode && !this.state.showImageViewer && !this.state.showWebView &&
|
|
||||||
(completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
|
|
||||||
const channelClaimId =
|
|
||||||
value && value.publisherSignature && value.publisherSignature.certificateId;
|
|
||||||
|
|
||||||
const playerStyle = [filePageStyle.player,
|
if (blackListedOutpoints) {
|
||||||
this.state.isLandscape ? filePageStyle.containedPlayerLandscape :
|
for (let i = 0; i < blackListedOutpoints.length; i += 1) {
|
||||||
(this.state.fullscreenMode ? filePageStyle.fullscreenPlayer : filePageStyle.containedPlayer)];
|
const outpoint = blackListedOutpoints[i];
|
||||||
const playerBgStyle = [filePageStyle.playerBackground, this.state.fullscreenMode ?
|
if (outpoint.txid === claim.txid && outpoint.nout === claim.nout) {
|
||||||
filePageStyle.fullscreenPlayerBackground : filePageStyle.containedPlayerBackground];
|
isClaimBlackListed = true;
|
||||||
// at least 2MB (or the full download) before media can be loaded
|
break;
|
||||||
const canLoadMedia = fileInfo &&
|
}
|
||||||
(fileInfo.written_bytes >= 2097152 || fileInfo.written_bytes == fileInfo.total_bytes); // 2MB = 1024*1024*2
|
|
||||||
const canOpen = (mediaType === 'image' || mediaType === 'text') && completed;
|
|
||||||
const isWebViewable = mediaType === 'text';
|
|
||||||
const localFileUri = this.localUriForFileInfo(fileInfo);
|
|
||||||
|
|
||||||
const openFile = () => {
|
|
||||||
if (mediaType === 'image') {
|
|
||||||
// use image viewer
|
|
||||||
this.setState({
|
|
||||||
imageUrls: [{
|
|
||||||
url: localFileUri
|
|
||||||
}],
|
|
||||||
showImageViewer: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (isWebViewable) {
|
|
||||||
// show webview
|
|
||||||
this.setState({
|
|
||||||
showWebView: true
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
innerContent = (
|
if (isClaimBlackListed) {
|
||||||
<View style={filePageStyle.pageContainer}>
|
innerContent = (
|
||||||
{this.state.showWebView && isWebViewable && <WebView source={{ uri: localFileUri }}
|
<View style={filePageStyle.pageContainer}>
|
||||||
style={filePageStyle.viewer} />}
|
<View style={filePageStyle.dmcaContainer}>
|
||||||
|
<Text style={filePageStyle.dmcaText}>
|
||||||
{this.state.showImageViewer && <ImageViewer style={StyleSheet.flatten(filePageStyle.viewer)}
|
In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications.
|
||||||
imageUrls={this.state.imageUrls}
|
</Text>
|
||||||
renderIndicator={() => null} />}
|
<Link style={filePageStyle.dmcaLink} href="https://lbry.io/faq/dmca" text="Read More" />
|
||||||
|
|
||||||
{!this.state.showWebView && (
|
|
||||||
<View style={this.state.fullscreenMode ? filePageStyle.innerPageContainerFsMode : filePageStyle.innerPageContainer}
|
|
||||||
onLayout={this.checkOrientation}>
|
|
||||||
<View style={filePageStyle.mediaContainer}>
|
|
||||||
{((canOpen || (!fileInfo || (isPlayable && !canLoadMedia))) || (!canOpen && fileInfo)) &&
|
|
||||||
<FileItemMedia style={filePageStyle.thumbnail} title={title} thumbnail={metadata.thumbnail} />}
|
|
||||||
{((!this.state.downloadButtonShown || this.state.downloadPressed) && !this.state.mediaLoaded) &&
|
|
||||||
<ActivityIndicator size="large" color={Colors.LbryGreen} style={filePageStyle.loading} />}
|
|
||||||
{((isPlayable && !completed && !canLoadMedia) || !completed || canOpen) && (!this.state.downloadPressed) &&
|
|
||||||
<FileDownloadButton uri={uri}
|
|
||||||
style={filePageStyle.downloadButton}
|
|
||||||
openFile={openFile}
|
|
||||||
isPlayable={isPlayable}
|
|
||||||
onPlay={() => {
|
|
||||||
this.startTime = Date.now();
|
|
||||||
this.setState({ downloadPressed: true, autoPlayMedia: true });
|
|
||||||
}}
|
|
||||||
onButtonLayout={() => this.setState({ downloadButtonShown: true })}
|
|
||||||
onStartDownloadFailed={() => {
|
|
||||||
this.startTime = null;
|
|
||||||
setTimeout(() => {
|
|
||||||
this.setState({ downloadPressed: false, fileViewLogged: false, mediaLoaded: false });
|
|
||||||
}, 500);
|
|
||||||
}} />}
|
|
||||||
{!fileInfo && <FilePrice uri={uri} style={filePageStyle.filePriceContainer} textStyle={filePageStyle.filePriceText} />}
|
|
||||||
</View>
|
|
||||||
{canLoadMedia && fileInfo && <View style={playerBgStyle}
|
|
||||||
ref={(ref) => { this.playerBackground = ref; }}
|
|
||||||
onLayout={(evt) => {
|
|
||||||
if (!this.state.playerBgHeight) {
|
|
||||||
this.setState({ playerBgHeight: evt.nativeEvent.layout.height });
|
|
||||||
}
|
|
||||||
}} />}
|
|
||||||
{canLoadMedia && fileInfo && <MediaPlayer
|
|
||||||
fileInfo={fileInfo}
|
|
||||||
assignPlayer={(ref) => { this.player = ref; }}
|
|
||||||
uri={uri}
|
|
||||||
style={playerStyle}
|
|
||||||
autoPlay={autoplay || this.state.autoPlayMedia}
|
|
||||||
onFullscreenToggled={this.handleFullscreenToggle}
|
|
||||||
onLayout={(evt) => {
|
|
||||||
if (!this.state.playerHeight) {
|
|
||||||
this.setState({ playerHeight: evt.nativeEvent.layout.height });
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onMediaLoaded={() => this.onMediaLoaded(channelName, title, uri)}
|
|
||||||
onPlaybackStarted={this.onPlaybackStarted}
|
|
||||||
/>}
|
|
||||||
|
|
||||||
{ showActions &&
|
|
||||||
<View style={filePageStyle.actions}>
|
|
||||||
{completed && <Button style={filePageStyle.actionButton}
|
|
||||||
theme={"light"}
|
|
||||||
icon={"trash"}
|
|
||||||
text={"Delete"}
|
|
||||||
onPress={this.onDeletePressed} />}
|
|
||||||
{!completed && fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes &&
|
|
||||||
<Button style={filePageStyle.actionButton}
|
|
||||||
theme={"light"}
|
|
||||||
text={"Stop Download"}
|
|
||||||
onPress={this.onStopDownloadPressed} />
|
|
||||||
}
|
|
||||||
</View>}
|
|
||||||
<ScrollView
|
|
||||||
style={showActions ? filePageStyle.scrollContainerActions : filePageStyle.scrollContainer}
|
|
||||||
contentContainerstyle={showActions ? null : filePageStyle.scrollContent}>
|
|
||||||
<Text style={filePageStyle.title} selectable={true}>{title}</Text>
|
|
||||||
{channelName && <Link style={filePageStyle.channelName}
|
|
||||||
selectable={true}
|
|
||||||
text={channelName}
|
|
||||||
onPress={() => {
|
|
||||||
const channelUri = normalizeURI(channelName);
|
|
||||||
navigateToUri(navigation, channelUri);
|
|
||||||
}} />}
|
|
||||||
|
|
||||||
{description && description.length > 0 && <View style={filePageStyle.divider} />}
|
|
||||||
|
|
||||||
{description && <Text style={filePageStyle.description} selectable={true}>{this.linkify(description)}</Text>}
|
|
||||||
|
|
||||||
<RelatedContent navigation={navigation} uri={uri} />
|
|
||||||
</ScrollView>
|
|
||||||
</View>
|
</View>
|
||||||
)}
|
<UriBar value={uri} navigation={navigation} />
|
||||||
{!this.state.fullscreenMode && <FloatingWalletBalance navigation={navigation} />}
|
</View>
|
||||||
{!this.state.fullscreenMode && <UriBar value={uri} navigation={navigation} />}
|
);
|
||||||
</View>
|
} else {
|
||||||
);
|
const completed = fileInfo && fileInfo.completed;
|
||||||
|
const title = metadata.title;
|
||||||
|
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
|
const description = metadata.description ? metadata.description : null;
|
||||||
|
const mediaType = Lbry.getMediaType(contentType);
|
||||||
|
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
||||||
|
const { height, channel_name: channelName, value } = claim;
|
||||||
|
const showActions = !this.state.fullscreenMode && !this.state.showImageViewer && !this.state.showWebView &&
|
||||||
|
(completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
|
||||||
|
const channelClaimId =
|
||||||
|
value && value.publisherSignature && value.publisherSignature.certificateId;
|
||||||
|
|
||||||
|
const playerStyle = [filePageStyle.player,
|
||||||
|
this.state.isLandscape ? filePageStyle.containedPlayerLandscape :
|
||||||
|
(this.state.fullscreenMode ? filePageStyle.fullscreenPlayer : filePageStyle.containedPlayer)];
|
||||||
|
const playerBgStyle = [filePageStyle.playerBackground, this.state.fullscreenMode ?
|
||||||
|
filePageStyle.fullscreenPlayerBackground : filePageStyle.containedPlayerBackground];
|
||||||
|
// at least 2MB (or the full download) before media can be loaded
|
||||||
|
const canLoadMedia = fileInfo &&
|
||||||
|
(fileInfo.written_bytes >= 2097152 || fileInfo.written_bytes == fileInfo.total_bytes); // 2MB = 1024*1024*2
|
||||||
|
const canOpen = (mediaType === 'image' || mediaType === 'text') && completed;
|
||||||
|
const isWebViewable = mediaType === 'text';
|
||||||
|
const localFileUri = this.localUriForFileInfo(fileInfo);
|
||||||
|
|
||||||
|
const openFile = () => {
|
||||||
|
if (mediaType === 'image') {
|
||||||
|
// use image viewer
|
||||||
|
this.setState({
|
||||||
|
imageUrls: [{
|
||||||
|
url: localFileUri
|
||||||
|
}],
|
||||||
|
showImageViewer: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (isWebViewable) {
|
||||||
|
// show webview
|
||||||
|
this.setState({
|
||||||
|
showWebView: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
innerContent = (
|
||||||
|
<View style={filePageStyle.pageContainer}>
|
||||||
|
{this.state.showWebView && isWebViewable && <WebView source={{ uri: localFileUri }}
|
||||||
|
style={filePageStyle.viewer} />}
|
||||||
|
|
||||||
|
{this.state.showImageViewer && <ImageViewer style={StyleSheet.flatten(filePageStyle.viewer)}
|
||||||
|
imageUrls={this.state.imageUrls}
|
||||||
|
renderIndicator={() => null} />}
|
||||||
|
|
||||||
|
{!this.state.showWebView && (
|
||||||
|
<View style={this.state.fullscreenMode ? filePageStyle.innerPageContainerFsMode : filePageStyle.innerPageContainer}
|
||||||
|
onLayout={this.checkOrientation}>
|
||||||
|
<View style={filePageStyle.mediaContainer}>
|
||||||
|
{((canOpen || (!fileInfo || (isPlayable && !canLoadMedia))) || (!canOpen && fileInfo)) &&
|
||||||
|
<FileItemMedia style={filePageStyle.thumbnail} title={title} thumbnail={metadata.thumbnail} />}
|
||||||
|
{((!this.state.downloadButtonShown || this.state.downloadPressed) && !this.state.mediaLoaded) &&
|
||||||
|
<ActivityIndicator size="large" color={Colors.LbryGreen} style={filePageStyle.loading} />}
|
||||||
|
{((isPlayable && !completed && !canLoadMedia) || !completed || canOpen) && (!this.state.downloadPressed) &&
|
||||||
|
<FileDownloadButton uri={uri}
|
||||||
|
style={filePageStyle.downloadButton}
|
||||||
|
openFile={openFile}
|
||||||
|
isPlayable={isPlayable}
|
||||||
|
onPlay={() => {
|
||||||
|
this.startTime = Date.now();
|
||||||
|
this.setState({ downloadPressed: true, autoPlayMedia: true });
|
||||||
|
}}
|
||||||
|
onButtonLayout={() => this.setState({ downloadButtonShown: true })}
|
||||||
|
onStartDownloadFailed={() => {
|
||||||
|
this.startTime = null;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState({ downloadPressed: false, fileViewLogged: false, mediaLoaded: false });
|
||||||
|
}, 500);
|
||||||
|
}} />}
|
||||||
|
{!fileInfo && <FilePrice uri={uri} style={filePageStyle.filePriceContainer} textStyle={filePageStyle.filePriceText} />}
|
||||||
|
</View>
|
||||||
|
{canLoadMedia && fileInfo && <View style={playerBgStyle}
|
||||||
|
ref={(ref) => { this.playerBackground = ref; }}
|
||||||
|
onLayout={(evt) => {
|
||||||
|
if (!this.state.playerBgHeight) {
|
||||||
|
this.setState({ playerBgHeight: evt.nativeEvent.layout.height });
|
||||||
|
}
|
||||||
|
}} />}
|
||||||
|
{canLoadMedia && fileInfo && <MediaPlayer
|
||||||
|
fileInfo={fileInfo}
|
||||||
|
assignPlayer={(ref) => { this.player = ref; }}
|
||||||
|
uri={uri}
|
||||||
|
style={playerStyle}
|
||||||
|
autoPlay={autoplay || this.state.autoPlayMedia}
|
||||||
|
onFullscreenToggled={this.handleFullscreenToggle}
|
||||||
|
onLayout={(evt) => {
|
||||||
|
if (!this.state.playerHeight) {
|
||||||
|
this.setState({ playerHeight: evt.nativeEvent.layout.height });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onMediaLoaded={() => this.onMediaLoaded(channelName, title, uri)}
|
||||||
|
onPlaybackStarted={this.onPlaybackStarted}
|
||||||
|
/>}
|
||||||
|
|
||||||
|
{ showActions &&
|
||||||
|
<View style={filePageStyle.actions}>
|
||||||
|
{completed && <Button style={filePageStyle.actionButton}
|
||||||
|
theme={"light"}
|
||||||
|
icon={"trash"}
|
||||||
|
text={"Delete"}
|
||||||
|
onPress={this.onDeletePressed} />}
|
||||||
|
{!completed && fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes &&
|
||||||
|
<Button style={filePageStyle.actionButton}
|
||||||
|
theme={"light"}
|
||||||
|
text={"Stop Download"}
|
||||||
|
onPress={this.onStopDownloadPressed} />
|
||||||
|
}
|
||||||
|
</View>}
|
||||||
|
<ScrollView
|
||||||
|
style={showActions ? filePageStyle.scrollContainerActions : filePageStyle.scrollContainer}
|
||||||
|
contentContainerstyle={showActions ? null : filePageStyle.scrollContent}>
|
||||||
|
<Text style={filePageStyle.title} selectable={true}>{title}</Text>
|
||||||
|
{channelName && <Link style={filePageStyle.channelName}
|
||||||
|
selectable={true}
|
||||||
|
text={channelName}
|
||||||
|
onPress={() => {
|
||||||
|
const channelUri = normalizeURI(channelName);
|
||||||
|
navigateToUri(navigation, channelUri);
|
||||||
|
}} />}
|
||||||
|
|
||||||
|
{description && description.length > 0 && <View style={filePageStyle.divider} />}
|
||||||
|
|
||||||
|
{description && <Text style={filePageStyle.description} selectable={true}>{this.linkify(description)}</Text>}
|
||||||
|
|
||||||
|
<RelatedContent navigation={navigation} uri={uri} />
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
{!this.state.fullscreenMode && <FloatingWalletBalance navigation={navigation} />}
|
||||||
|
{!this.state.fullscreenMode && <UriBar value={uri} navigation={navigation} />}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return innerContent;
|
return innerContent;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doBalanceSubscribe, doNotify } from 'lbry-redux';
|
import { doBalanceSubscribe, doBlackListedOutpointsSubscribe, doNotify } from 'lbry-redux';
|
||||||
import {
|
import {
|
||||||
doAuthenticate,
|
doAuthenticate,
|
||||||
doFetchRewardedContent,
|
doFetchRewardedContent,
|
||||||
|
@ -20,6 +20,7 @@ const select = state => ({
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
authenticate: (appVersion, os) => dispatch(doAuthenticate(appVersion, os)),
|
authenticate: (appVersion, os) => dispatch(doAuthenticate(appVersion, os)),
|
||||||
balanceSubscribe: () => dispatch(doBalanceSubscribe()),
|
balanceSubscribe: () => dispatch(doBalanceSubscribe()),
|
||||||
|
blacklistedOutpointsSubscribe: () => dispatch(doBlackListedOutpointsSubscribe()),
|
||||||
deleteCompleteBlobs: () => dispatch(doDeleteCompleteBlobs()),
|
deleteCompleteBlobs: () => dispatch(doDeleteCompleteBlobs()),
|
||||||
fetchRewardedContent: () => dispatch(doFetchRewardedContent()),
|
fetchRewardedContent: () => dispatch(doFetchRewardedContent()),
|
||||||
notify: data => dispatch(doNotify(data)),
|
notify: data => dispatch(doNotify(data)),
|
||||||
|
|
|
@ -144,11 +144,13 @@ class SplashScreen extends React.PureComponent {
|
||||||
const {
|
const {
|
||||||
authenticate,
|
authenticate,
|
||||||
balanceSubscribe,
|
balanceSubscribe,
|
||||||
|
blacklistedOutpointsSubscribe,
|
||||||
navigation,
|
navigation,
|
||||||
notify
|
notify
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
balanceSubscribe();
|
balanceSubscribe();
|
||||||
|
blacklistedOutpointsSubscribe();
|
||||||
NativeModules.VersionInfo.getAppVersion().then(appVersion => {
|
NativeModules.VersionInfo.getAppVersion().then(appVersion => {
|
||||||
this.setState({ shouldAuthenticate: true });
|
this.setState({ shouldAuthenticate: true });
|
||||||
authenticate(appVersion, Platform.OS);
|
authenticate(appVersion, Platform.OS);
|
||||||
|
|
|
@ -165,6 +165,25 @@ const filePageStyle = StyleSheet.create({
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row'
|
flexDirection: 'row'
|
||||||
},
|
},
|
||||||
|
dmcaContainer: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
justifyContent: 'center',
|
||||||
|
paddingLeft: 24,
|
||||||
|
paddingRight: 24
|
||||||
|
},
|
||||||
|
dmcaText: {
|
||||||
|
fontFamily: 'Metropolis-Regular',
|
||||||
|
fontSize: 18,
|
||||||
|
lineHeight: 24
|
||||||
|
},
|
||||||
|
dmcaLink: {
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
fontFamily: 'Metropolis-Regular',
|
||||||
|
fontSize: 18,
|
||||||
|
lineHeight: 24,
|
||||||
|
marginTop: 24
|
||||||
|
},
|
||||||
infoText: {
|
infoText: {
|
||||||
fontFamily: 'Metropolis-Regular',
|
fontFamily: 'Metropolis-Regular',
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
|
|
Loading…
Reference in a new issue