display the video duration in the FileItemMedia component #27
7 changed files with 107 additions and 10 deletions
|
@ -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} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -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 (
|
||||||
|
<View style={style}>
|
||||||
<FastImage
|
<FastImage
|
||||||
source={{ uri: thumbnail }}
|
source={{ uri: thumbnail }}
|
||||||
onError={() => this.setState({ imageLoadFailed: true })}
|
onError={() => this.setState({ imageLoadFailed: true })}
|
||||||
resizeMode={this.getFastImageResizeMode(resizeMode)}
|
resizeMode={this.getFastImageResizeMode(resizeMode)}
|
||||||
style={style}
|
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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}
|
||||||
|
|
4
src/component/videoDuration/index.js
Normal file
4
src/component/videoDuration/index.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import VideoDuration from './view';
|
||||||
|
|
||||||
|
export default connect()(VideoDuration);
|
36
src/component/videoDuration/view.js
Normal file
36
src/component/videoDuration/view.js
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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} />
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue