better performance on lower end devices with react-native-fast-image (#275)
* thumbnail aspect ratio sizing tweaks * show approximate values for formatted bytes * truncate titles over 80 characters in the file item list component
This commit is contained in:
parent
e9abbf256e
commit
4b7be60c27
10 changed files with 100 additions and 31 deletions
16
app/package-lock.json
generated
16
app/package-lock.json
generated
|
@ -3969,8 +3969,17 @@
|
||||||
"version": "github:lbryio/lbryinc#678c5098e2099dd1560b2fefa2795f38ca3ce07b",
|
"version": "github:lbryio/lbryinc#678c5098e2099dd1560b2fefa2795f38ca3ce07b",
|
||||||
"from": "github:lbryio/lbryinc",
|
"from": "github:lbryio/lbryinc",
|
||||||
"requires": {
|
"requires": {
|
||||||
"lbry-redux": "github:lbryio/lbry-redux#31f7afa8a37f5741dac01fc1ecdf153f3bed95dc",
|
|
||||||
"reselect": "^3.0.0"
|
"reselect": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lbry-redux": {
|
||||||
|
"version": "github:lbryio/lbry-redux#31f7afa8a37f5741dac01fc1ecdf153f3bed95dc",
|
||||||
|
"from": "github:lbryio/lbry-redux#31f7afa8a37f5741dac01fc1ecdf153f3bed95dc",
|
||||||
|
"requires": {
|
||||||
|
"proxy-polyfill": "0.1.6",
|
||||||
|
"reselect": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lcid": {
|
"lcid": {
|
||||||
|
@ -5188,6 +5197,11 @@
|
||||||
"react-native-drawer-layout": "1.3.2"
|
"react-native-drawer-layout": "1.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-native-fast-image": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-5.0.3.tgz",
|
||||||
|
"integrity": "sha512-70XlQPt8b7yQSMwUEEIN5jTx7KOx1EBD2XhIRIEHChfNv5Gwn8dh28RSo/Dq9qezf4CWJXO3CAb4lq+Hu9d0vw=="
|
||||||
|
},
|
||||||
"react-native-fetch-blob": {
|
"react-native-fetch-blob": {
|
||||||
"version": "0.10.8",
|
"version": "0.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-fetch-blob/-/react-native-fetch-blob-0.10.8.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-fetch-blob/-/react-native-fetch-blob-0.10.8.tgz",
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"moment": "^2.22.1",
|
"moment": "^2.22.1",
|
||||||
"react": "16.2.0",
|
"react": "16.2.0",
|
||||||
"react-native": "0.55.3",
|
"react-native": "0.55.3",
|
||||||
|
"react-native-fast-image": "^5.0.3",
|
||||||
"react-native-fetch-blob": "^0.10.8",
|
"react-native-fetch-blob": "^0.10.8",
|
||||||
"react-native-image-zoom-viewer": "^2.2.5",
|
"react-native-image-zoom-viewer": "^2.2.5",
|
||||||
"react-native-vector-icons": "^5.0.0",
|
"react-native-vector-icons": "^5.0.0",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
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 fileItemMediaStyle from '../../styles/fileItemMedia';
|
import fileItemMediaStyle from '../../styles/fileItemMedia';
|
||||||
|
|
||||||
class FileItemMedia extends React.PureComponent {
|
class FileItemMedia extends React.PureComponent {
|
||||||
|
@ -18,6 +19,10 @@ class FileItemMedia extends React.PureComponent {
|
||||||
fileItemMediaStyle.autothumbOrange,
|
fileItemMediaStyle.autothumbOrange,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
state: {
|
||||||
|
imageLoadFailed: false
|
||||||
|
};
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.setState({
|
this.setState({
|
||||||
autoThumbStyle:
|
autoThumbStyle:
|
||||||
|
@ -27,21 +32,47 @@ class FileItemMedia extends React.PureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFastImageResizeMode(resizeMode) {
|
||||||
|
switch (resizeMode) {
|
||||||
|
case "contain":
|
||||||
|
return FastImage.resizeMode.contain;
|
||||||
|
case "stretch":
|
||||||
|
console.log('using stretch resize mode...');
|
||||||
|
return FastImage.resizeMode.stretch;
|
||||||
|
case "center":
|
||||||
|
return FastImage.resizeMode.center;
|
||||||
|
default:
|
||||||
|
return FastImage.resizeMode.cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let style = this.props.style;
|
let style = this.props.style;
|
||||||
const { blurRadius, isResolvingUri, thumbnail, title, resizeMode } = this.props;
|
const { blurRadius, isResolvingUri, thumbnail, title, resizeMode } = this.props;
|
||||||
const atStyle = this.state.autoThumbStyle;
|
const atStyle = this.state.autoThumbStyle;
|
||||||
|
if (thumbnail && ((typeof thumbnail) === 'string') && !this.state.imageLoadFailed) {
|
||||||
if (thumbnail && ((typeof thumbnail) === 'string')) {
|
|
||||||
if (style == null) {
|
if (style == null) {
|
||||||
style = fileItemMediaStyle.thumbnail;
|
style = fileItemMediaStyle.thumbnail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (blurRadius > 0) {
|
||||||
|
// No blur radius support in FastImage yet
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
source={{uri: thumbnail}}
|
||||||
|
blurRadius={blurRadius}
|
||||||
|
resizeMode={resizeMode ? resizeMode : "cover"}
|
||||||
|
style={style}
|
||||||
|
/>);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Image source={{uri: thumbnail}}
|
<FastImage
|
||||||
blurRadius={blurRadius}
|
source={{uri: thumbnail}}
|
||||||
resizeMode={resizeMode ? resizeMode : "cover"}
|
onError={() => this.setState({ imageLoadFailed: true })}
|
||||||
style={style} />
|
resizeMode={this.getFastImageResizeMode(resizeMode)}
|
||||||
|
style={style}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,19 +27,27 @@ class FileListItem extends React.PureComponent {
|
||||||
|
|
||||||
formatBytes = (bytes) => {
|
formatBytes = (bytes) => {
|
||||||
if (bytes < 1048576) { // < 1MB
|
if (bytes < 1048576) { // < 1MB
|
||||||
const value = (bytes / 1024.0).toFixed(2);
|
const value = (bytes / 1024.0).toFixed(0);
|
||||||
return `${value} KB`;
|
return `${value} KB`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes < 1073741824) { // < 1GB
|
if (bytes < 1073741824) { // < 1GB
|
||||||
const value = (bytes / (1024.0 * 1024.0)).toFixed(2);
|
const value = (bytes / (1024.0 * 1024.0)).toFixed(0);
|
||||||
return `${value} MB`;
|
return `${value} MB`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = (bytes / (1024.0 * 1024.0 * 1024.0)).toFixed(2);
|
const value = (bytes / (1024.0 * 1024.0 * 1024.0)).toFixed(0);
|
||||||
return `${value} GB`;
|
return `${value} GB`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
formatTitle = (title) => {
|
||||||
|
if (!title) {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (title.length > 80) ? title.substring(0, 77).trim() + '...' : title;
|
||||||
|
}
|
||||||
|
|
||||||
getDownloadProgress = (fileInfo) => {
|
getDownloadProgress = (fileInfo) => {
|
||||||
return Math.ceil((fileInfo.written_bytes / fileInfo.total_bytes) * 100);
|
return Math.ceil((fileInfo.written_bytes / fileInfo.total_bytes) * 100);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +93,7 @@ class FileListItem extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
</View>)}
|
</View>)}
|
||||||
|
|
||||||
{!isResolving && <Text style={fileListStyle.title}>{title || name}</Text>}
|
{!isResolving && <Text style={fileListStyle.title}>{this.formatTitle(title) || this.formatTitle(name)}</Text>}
|
||||||
{!isResolving && channel &&
|
{!isResolving && channel &&
|
||||||
<Link style={fileListStyle.publisher} text={channel} onPress={() => {
|
<Link style={fileListStyle.publisher} text={channel} onPress={() => {
|
||||||
const channelUri = normalizeURI(channel);
|
const channelUri = normalizeURI(channel);
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
import { Dimensions, StyleSheet } from 'react-native';
|
import { Dimensions, PixelRatio, StyleSheet } from 'react-native';
|
||||||
import Colors from './colors';
|
import Colors from './colors';
|
||||||
|
|
||||||
const screenDimension = Dimensions.get('window');
|
const screenDimension = Dimensions.get('window');
|
||||||
const screenWidth = screenDimension.width;
|
const screenWidth = screenDimension.width;
|
||||||
const screenHeight = screenDimension.height;
|
const screenHeight = screenDimension.height;
|
||||||
|
const screenWidthPixels = PixelRatio.getPixelSizeForLayoutSize(screenWidth);
|
||||||
|
const screenHeightPixels = PixelRatio.getPixelSizeForLayoutSize(screenHeight);
|
||||||
|
console.log('screenHeightPixels=' + screenHeightPixels);
|
||||||
// calculate thumbnail width and height based on device's aspect ratio
|
// calculate thumbnail width and height based on device's aspect ratio
|
||||||
const horizontalMargin = 48; // left and right margins (24 + 24)
|
const horizontalMargin = 48; // left and right margins (24 + 24)
|
||||||
const verticalMargin = (screenWidth / screenHeight) * horizontalMargin;
|
const verticalMargin = (screenWidthPixels > 720 && screenHeightPixels > 1920) ? 0 : ((screenWidthPixels <= 720) ? 20 : 16);
|
||||||
const mediaWidth = screenWidth - horizontalMargin;
|
const mediaWidth = screenWidth - horizontalMargin;
|
||||||
const mediaHeight = (screenWidth / (screenHeight - verticalMargin)) * mediaWidth;
|
const mediaHeight = ((screenWidth / screenHeight) * ((screenWidthPixels <= 720) ? screenWidth : mediaWidth)) - verticalMargin;
|
||||||
|
|
||||||
const discoverStyle = StyleSheet.create({
|
const discoverStyle = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
import { Dimensions, StyleSheet } from 'react-native';
|
import { Dimensions, PixelRatio, StyleSheet } from 'react-native';
|
||||||
import Colors from './colors';
|
import Colors from './colors';
|
||||||
|
|
||||||
const screenDimension = Dimensions.get('window');
|
const screenDimension = Dimensions.get('window');
|
||||||
const screenWidth = screenDimension.width;
|
const screenWidth = screenDimension.width;
|
||||||
const screenHeight = screenDimension.height;
|
const screenHeight = screenDimension.height;
|
||||||
const thumbnailHeight = 100;
|
const screenWidthPixels = PixelRatio.getPixelSizeForLayoutSize(screenWidth);
|
||||||
const thumbnailWidth = (screenHeight / screenWidth) * thumbnailHeight;
|
const screenHeightPixels = PixelRatio.getPixelSizeForLayoutSize(screenHeight);
|
||||||
|
const verticalAdjust = (screenHeightPixels > 1280 && screenHeightPixels <= 1920) ? 6 : 0;
|
||||||
|
const thumbnailWidth = (screenWidthPixels <= 720) ? 144 : 156;
|
||||||
|
const thumbnailHeight = ((screenWidth / screenHeight) * thumbnailWidth) - verticalAdjust;
|
||||||
|
|
||||||
const fileListStyle = StyleSheet.create({
|
const fileListStyle = StyleSheet.create({
|
||||||
item: {
|
item: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
marginTop: 16
|
marginTop: 8
|
||||||
},
|
},
|
||||||
detailsContainer: {
|
detailsContainer: {
|
||||||
flex: 1
|
flex: 1
|
||||||
|
@ -20,37 +23,37 @@ const fileListStyle = StyleSheet.create({
|
||||||
thumbnail: {
|
thumbnail: {
|
||||||
width: thumbnailWidth,
|
width: thumbnailWidth,
|
||||||
height: thumbnailHeight,
|
height: thumbnailHeight,
|
||||||
marginRight: 16,
|
marginRight: (screenWidthPixels <= 720) ? 10 : 12,
|
||||||
justifyContent: 'center'
|
justifyContent: 'center'
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
fontFamily: 'Metropolis-SemiBold',
|
fontFamily: 'Metropolis-SemiBold',
|
||||||
fontSize: 16
|
fontSize: (screenWidthPixels <= 720) ? 12 : 16
|
||||||
},
|
},
|
||||||
uri: {
|
uri: {
|
||||||
fontFamily: 'Metropolis-SemiBold',
|
fontFamily: 'Metropolis-SemiBold',
|
||||||
fontSize: 14,
|
fontSize: (screenWidthPixels <= 720) ? 12 : 14,
|
||||||
marginBottom: 8
|
marginBottom: 8
|
||||||
},
|
},
|
||||||
publisher: {
|
publisher: {
|
||||||
fontFamily: 'Metropolis-SemiBold',
|
fontFamily: 'Metropolis-SemiBold',
|
||||||
fontSize: 14,
|
fontSize: (screenWidthPixels <= 720) ? 12 : 14,
|
||||||
marginTop: 3,
|
marginTop: (screenWidthPixels <= 720) ? 1 : 3,
|
||||||
color: Colors.LbryGreen
|
color: Colors.LbryGreen
|
||||||
},
|
},
|
||||||
loading: {
|
loading: {
|
||||||
position: 'absolute'
|
position: 'absolute'
|
||||||
},
|
},
|
||||||
downloadInfo: {
|
downloadInfo: {
|
||||||
marginTop: 8
|
marginTop: (screenWidthPixels <= 720) ? 4 : 8
|
||||||
},
|
},
|
||||||
downloadStorage: {
|
downloadStorage: {
|
||||||
fontFamily: 'Metropolis-Regular',
|
fontFamily: 'Metropolis-Regular',
|
||||||
fontSize: 14,
|
fontSize: (screenWidthPixels <= 720) ? 12 : 14,
|
||||||
color: Colors.ChannelGrey
|
color: Colors.ChannelGrey
|
||||||
},
|
},
|
||||||
progress: {
|
progress: {
|
||||||
marginTop: 4,
|
marginTop: (screenWidthPixels <= 720) ? 2 : 4,
|
||||||
height: 3,
|
height: 3,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row'
|
flexDirection: 'row'
|
||||||
|
|
|
@ -21,7 +21,7 @@ const searchStyle = StyleSheet.create({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
marginTop: 16
|
marginTop: 8
|
||||||
},
|
},
|
||||||
searchInput: {
|
searchInput: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|
|
@ -40,6 +40,10 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dexOptions {
|
||||||
|
jumboMode true
|
||||||
|
}
|
||||||
|
|
||||||
{% if args.sign -%}
|
{% if args.sign -%}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
release {
|
release {
|
||||||
|
@ -80,9 +84,10 @@ subprojects {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':react-native-video')
|
compile project(':react-native-fast-image')
|
||||||
compile project(':react-native-fetch-blob')
|
compile project(':react-native-fetch-blob')
|
||||||
{%- for aar in aars %}
|
compile project(':react-native-video')
|
||||||
|
{%- for aar in aars %}
|
||||||
compile(name: '{{ aar }}', ext: 'aar')
|
compile(name: '{{ aar }}', ext: 'aar')
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
{%- if args.depends -%}
|
{%- if args.depends -%}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
rootProject.name = 'browser'
|
rootProject.name = 'browser'
|
||||||
include ':react-native-video'
|
include ':react-native-fast-image'
|
||||||
project(':react-native-video').projectDir = new File(rootProject.projectDir, './react/node_modules/react-native-video/android-exoplayer')
|
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, './react/node_modules/react-native-fast-image/android')
|
||||||
include ':react-native-fetch-blob'
|
include ':react-native-fetch-blob'
|
||||||
project(':react-native-fetch-blob').projectDir = new File(rootProject.projectDir, './react/node_modules/react-native-fetch-blob/android')
|
project(':react-native-fetch-blob').projectDir = new File(rootProject.projectDir, './react/node_modules/react-native-fetch-blob/android')
|
||||||
|
include ':react-native-video'
|
||||||
|
project(':react-native-video').projectDir = new File(rootProject.projectDir, './react/node_modules/react-native-video/android-exoplayer')
|
||||||
|
|
|
@ -20,6 +20,7 @@ import android.telephony.TelephonyManager;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.brentvatne.react.ReactVideoPackage;
|
import com.brentvatne.react.ReactVideoPackage;
|
||||||
|
import com.dylanvann.fastimage.FastImageViewPackage;
|
||||||
import com.facebook.react.common.LifecycleState;
|
import com.facebook.react.common.LifecycleState;
|
||||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||||
import com.facebook.react.ReactRootView;
|
import com.facebook.react.ReactRootView;
|
||||||
|
@ -103,6 +104,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
||||||
.setBundleAssetName("index.android.bundle")
|
.setBundleAssetName("index.android.bundle")
|
||||||
.setJSMainModulePath("index")
|
.setJSMainModulePath("index")
|
||||||
.addPackage(new MainReactPackage())
|
.addPackage(new MainReactPackage())
|
||||||
|
.addPackage(new FastImageViewPackage())
|
||||||
.addPackage(new ReactVideoPackage())
|
.addPackage(new ReactVideoPackage())
|
||||||
.addPackage(new RNFetchBlobPackage())
|
.addPackage(new RNFetchBlobPackage())
|
||||||
.addPackage(new LbryReactPackage())
|
.addPackage(new LbryReactPackage())
|
||||||
|
|
Loading…
Reference in a new issue