display the video duration in the FileItemMedia component #27

Merged
akinwale merged 3 commits from video-duration into master 2019-08-20 10:03:56 +02:00
7 changed files with 107 additions and 10 deletions

View file

@ -71,6 +71,7 @@ class FileItem extends React.PureComponent {
const fullChannelUri = channelClaimId ? `${channelName}#${channelClaimId}` : channelName; const fullChannelUri = channelClaimId ? `${channelName}#${channelClaimId}` : channelName;
const shortChannelUri = signingChannel ? signingChannel.short_url : null; const shortChannelUri = signingChannel ? signingChannel.short_url : null;
const height = claim ? claim.height : null; const height = claim ? claim.height : null;
const duration = claim && claim.value && claim.value.video ? claim.value.video.duration : null;
return ( return (
<View style={style}> <View style={style}>
@ -81,6 +82,7 @@ class FileItem extends React.PureComponent {
</Text> </Text>
)} )}
<FileItemMedia <FileItemMedia
duration={duration}
title={title} title={title}
thumbnail={thumbnail} thumbnail={thumbnail}
blurRadius={obscure ? 15 : 0} blurRadius={obscure ? 15 : 0}
@ -88,7 +90,6 @@ class FileItem extends React.PureComponent {
isResolvingUri={isResolvingUri} isResolvingUri={isResolvingUri}
style={mediaStyle} style={mediaStyle}
/> />
{!compactView && fileInfo && fileInfo.completed && fileInfo.download_path && ( {!compactView && fileInfo && fileInfo.completed && fileInfo.download_path && (
<Icon style={discoverStyle.downloadedIcon} solid color={Colors.NextLbryGreen} name={'folder'} size={16} /> <Icon style={discoverStyle.downloadedIcon} solid color={Colors.NextLbryGreen} name={'folder'} size={16} />
)} )}

View file

@ -2,6 +2,7 @@ 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 VideoDuration from 'component/videoDuration';
import autothumbStyle from 'styles/autothumb'; import autothumbStyle from 'styles/autothumb';
import fileItemMediaStyle from 'styles/fileItemMedia'; import fileItemMediaStyle from 'styles/fileItemMedia';
@ -58,7 +59,7 @@ class FileItemMedia extends React.PureComponent {
render() { render() {
let style = this.props.style; let style = this.props.style;
const { blurRadius, isResolvingUri, thumbnail, title, resizeMode } = this.props; const { blurRadius, duration, isResolvingUri, thumbnail, title, resizeMode } = this.props;
const atStyle = this.state.autoThumbStyle; const atStyle = this.state.autoThumbStyle;
if (this.isThumbnailValid(thumbnail) && !this.state.imageLoadFailed) { if (this.isThumbnailValid(thumbnail) && !this.state.imageLoadFailed) {
if (style == null) { if (style == null) {
@ -68,17 +69,40 @@ 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 source={{ uri: thumbnail }} blurRadius={blurRadius} resizeMode={resizeMode || 'cover'} style={style} /> <View style={style}>
<Image
source={{ uri: thumbnail }}
blurRadius={blurRadius}
resizeMode={resizeMode || 'cover'}
style={fileItemMediaStyle.image}
/>
{duration && (
<VideoDuration
duration={duration}
style={fileItemMediaStyle.duration}
textStyle={fileItemMediaStyle.durationText}
/>
)}
</View>
); );
} }
return ( return (
<FastImage <View style={style}>
source={{ uri: thumbnail }} <FastImage
onError={() => this.setState({ imageLoadFailed: true })} source={{ uri: thumbnail }}
resizeMode={this.getFastImageResizeMode(resizeMode)} onError={() => this.setState({ imageLoadFailed: true })}
style={style} resizeMode={this.getFastImageResizeMode(resizeMode)}
/> style={fileItemMediaStyle.image}
/>
{duration && (
<VideoDuration
duration={duration}
style={fileItemMediaStyle.duration}
textStyle={fileItemMediaStyle.durationText}
/>
)}
</View>
); );
} }
@ -100,6 +124,13 @@ class FileItemMedia extends React.PureComponent {
.toUpperCase()} .toUpperCase()}
</Text> </Text>
)} )}
{duration && (
<VideoDuration
duration={duration}
style={fileItemMediaStyle.duration}
textStyle={fileItemMediaStyle.durationText}
/>
)}
</View> </View>
); );
} }

View file

@ -80,6 +80,7 @@ class FileListItem extends React.PureComponent {
const uri = normalizeURI(this.props.uri); const uri = normalizeURI(this.props.uri);
const obscure = obscureNsfw && nsfw; const obscure = obscureNsfw && nsfw;
const isResolving = !fileInfo && isResolvingUri; const isResolving = !fileInfo && isResolvingUri;
const duration = claim && claim.value && claim.value.video ? claim.value.video.duration : null;
let name, channel, height, channelClaimId, fullChannelUri, shortChannelUri, shouldHide, signingChannel; let name, channel, height, channelClaimId, fullChannelUri, shortChannelUri, shouldHide, signingChannel;
if (claim) { if (claim) {
@ -110,6 +111,7 @@ class FileListItem extends React.PureComponent {
<FileItemMedia <FileItemMedia
style={fileListStyle.thumbnail} style={fileListStyle.thumbnail}
blurRadius={obscure ? 15 : 0} blurRadius={obscure ? 15 : 0}
duration={duration}
resizeMode="cover" resizeMode="cover"
title={title || name} title={title || name}
thumbnail={thumbnail} thumbnail={thumbnail}

View file

@ -0,0 +1,4 @@
import { connect } from 'react-redux';
import VideoDuration from './view';
export default connect()(VideoDuration);

View file

@ -0,0 +1,36 @@
import React from 'react';
import { Text, View } from 'react-native';
import fileListStyle from 'styles/fileList';
import _ from 'lodash';
export default class VideoDuration extends React.PureComponent {
getDurationString = duration => {
let seconds = duration;
const hours = Math.floor(seconds / 3600);
seconds = duration - hours * 3600;
const minutes = Math.floor(seconds / 60);
seconds = seconds % 60;
let durationString = '';
if (hours > 0) {
durationString += hours + ':';
}
durationString += _.padStart(minutes, hours > 0 ? 2 : 0, '0') + ':';
durationString += _.padStart(seconds, 2, '0');
return durationString;
};
render() {
const { duration, style, textStyle } = this.props;
if (!duration || isNaN(parseFloat(duration))) {
return null;
}
return (
<View style={style}>
<Text style={textStyle}>{this.getDurationString(duration)}</Text>
</View>
);
}
}

View file

@ -658,6 +658,7 @@ class FilePage extends React.PureComponent {
const canLoadMedia = const canLoadMedia =
this.state.streamingMode || this.state.streamingMode ||
(fileInfo && (fileInfo.written_bytes >= 2097152 || fileInfo.written_bytes === fileInfo.total_bytes)); // 2MB = 1024*1024*2 (fileInfo && (fileInfo.written_bytes >= 2097152 || fileInfo.written_bytes === fileInfo.total_bytes)); // 2MB = 1024*1024*2
const duration = claim && claim.value && claim.value.video ? claim.value.video.duration : null;
const isViewable = mediaType === 'image' || mediaType === 'text'; const isViewable = mediaType === 'image' || mediaType === 'text';
const isWebViewable = mediaType === 'text'; const isWebViewable = mediaType === 'text';
const canOpen = isViewable && completed; const canOpen = isViewable && completed;
@ -725,7 +726,12 @@ class FilePage extends React.PureComponent {
> >
<View style={filePageStyle.mediaContainer}> <View style={filePageStyle.mediaContainer}>
{(canOpen || (!fileInfo || (isPlayable && !canLoadMedia)) || (!canOpen && fileInfo)) && ( {(canOpen || (!fileInfo || (isPlayable && !canLoadMedia)) || (!canOpen && fileInfo)) && (
<FileItemMedia style={filePageStyle.thumbnail} title={title} thumbnail={thumbnail} /> <FileItemMedia
duration={duration}
style={filePageStyle.thumbnail}
title={title}
thumbnail={thumbnail}
/>
)} )}
{(!this.state.downloadButtonShown || this.state.downloadPressed) && !this.state.mediaLoaded && ( {(!this.state.downloadButtonShown || this.state.downloadPressed) && !this.state.mediaLoaded && (
<ActivityIndicator size="large" color={Colors.NextLbryGreen} style={filePageStyle.loading} /> <ActivityIndicator size="large" color={Colors.NextLbryGreen} style={filePageStyle.loading} />

View file

@ -26,12 +26,29 @@ const fileItemMediaStyle = StyleSheet.create({
fontSize: 16, fontSize: 16,
marginTop: 8, marginTop: 8,
}, },
image: {
width: '100%',
height: '100%',
},
thumbnail: { thumbnail: {
flex: 1, flex: 1,
width: '100%', width: '100%',
height: 200, height: 200,
shadowColor: 'transparent', shadowColor: 'transparent',
}, },
duration: {
backgroundColor: Colors.Black,
position: 'absolute',
right: 4,
bottom: 4,
paddingLeft: 2,
paddingRight: 2,
},
durationText: {
fontFamily: 'Inter-UI-SemiBold',
fontSize: 12,
color: Colors.White,
},
}); });
export default fileItemMediaStyle; export default fileItemMediaStyle;