diff --git a/src/component/fileItem/view.js b/src/component/fileItem/view.js index 3832a35..e72ed52 100644 --- a/src/component/fileItem/view.js +++ b/src/component/fileItem/view.js @@ -71,6 +71,7 @@ class FileItem extends React.PureComponent { const fullChannelUri = channelClaimId ? `${channelName}#${channelClaimId}` : channelName; const shortChannelUri = signingChannel ? signingChannel.short_url : null; const height = claim ? claim.height : null; + const duration = claim && claim.value && claim.value.video ? claim.value.video.duration : null; return ( @@ -81,6 +82,7 @@ class FileItem extends React.PureComponent { )} - {!compactView && fileInfo && fileInfo.completed && fileInfo.download_path && ( )} diff --git a/src/component/fileItemMedia/view.js b/src/component/fileItemMedia/view.js index f9ac4dc..20ff308 100644 --- a/src/component/fileItemMedia/view.js +++ b/src/component/fileItemMedia/view.js @@ -2,6 +2,7 @@ import React from 'react'; import { ActivityIndicator, Image, Text, View } from 'react-native'; import Colors from 'styles/colors'; import FastImage from 'react-native-fast-image'; +import VideoDuration from 'component/videoDuration'; import autothumbStyle from 'styles/autothumb'; import fileItemMediaStyle from 'styles/fileItemMedia'; @@ -58,7 +59,7 @@ class FileItemMedia extends React.PureComponent { render() { 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; if (this.isThumbnailValid(thumbnail) && !this.state.imageLoadFailed) { if (style == null) { @@ -68,17 +69,40 @@ class FileItemMedia extends React.PureComponent { if (blurRadius > 0) { // No blur radius support in FastImage yet return ( - + + + {duration && ( + + )} + ); } return ( - this.setState({ imageLoadFailed: true })} - resizeMode={this.getFastImageResizeMode(resizeMode)} - style={style} - /> + + this.setState({ imageLoadFailed: true })} + resizeMode={this.getFastImageResizeMode(resizeMode)} + style={fileItemMediaStyle.image} + /> + {duration && ( + + )} + ); } @@ -100,6 +124,13 @@ class FileItemMedia extends React.PureComponent { .toUpperCase()} )} + {duration && ( + + )} ); } diff --git a/src/component/fileListItem/view.js b/src/component/fileListItem/view.js index 11237b5..680b9d5 100644 --- a/src/component/fileListItem/view.js +++ b/src/component/fileListItem/view.js @@ -80,6 +80,7 @@ class FileListItem extends React.PureComponent { const uri = normalizeURI(this.props.uri); const obscure = obscureNsfw && nsfw; 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; if (claim) { @@ -110,6 +111,7 @@ class FileListItem extends React.PureComponent { { + 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 ( + + {this.getDurationString(duration)} + + ); + } +} diff --git a/src/page/file/view.js b/src/page/file/view.js index 8459e3a..16da579 100644 --- a/src/page/file/view.js +++ b/src/page/file/view.js @@ -658,6 +658,7 @@ class FilePage extends React.PureComponent { const canLoadMedia = this.state.streamingMode || (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 isWebViewable = mediaType === 'text'; const canOpen = isViewable && completed; @@ -725,7 +726,12 @@ class FilePage extends React.PureComponent { > {(canOpen || (!fileInfo || (isPlayable && !canLoadMedia)) || (!canOpen && fileInfo)) && ( - + )} {(!this.state.downloadButtonShown || this.state.downloadPressed) && !this.state.mediaLoaded && ( diff --git a/src/styles/fileItemMedia.js b/src/styles/fileItemMedia.js index bb5bc83..6d7197d 100644 --- a/src/styles/fileItemMedia.js +++ b/src/styles/fileItemMedia.js @@ -26,12 +26,29 @@ const fileItemMediaStyle = StyleSheet.create({ fontSize: 16, marginTop: 8, }, + image: { + width: '100%', + height: '100%', + }, thumbnail: { flex: 1, width: '100%', height: 200, 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;