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",
|
||||
"from": "github:lbryio/lbryinc",
|
||||
"requires": {
|
||||
"lbry-redux": "github:lbryio/lbry-redux#31f7afa8a37f5741dac01fc1ecdf153f3bed95dc",
|
||||
"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": {
|
||||
|
@ -5188,6 +5197,11 @@
|
|||
"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": {
|
||||
"version": "0.10.8",
|
||||
"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",
|
||||
"react": "16.2.0",
|
||||
"react-native": "0.55.3",
|
||||
"react-native-fast-image": "^5.0.3",
|
||||
"react-native-fetch-blob": "^0.10.8",
|
||||
"react-native-image-zoom-viewer": "^2.2.5",
|
||||
"react-native-vector-icons": "^5.0.0",
|
||||
|
|
|
@ -1,6 +1,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 fileItemMediaStyle from '../../styles/fileItemMedia';
|
||||
|
||||
class FileItemMedia extends React.PureComponent {
|
||||
|
@ -18,6 +19,10 @@ class FileItemMedia extends React.PureComponent {
|
|||
fileItemMediaStyle.autothumbOrange,
|
||||
];
|
||||
|
||||
state: {
|
||||
imageLoadFailed: false
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
this.setState({
|
||||
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() {
|
||||
let style = this.props.style;
|
||||
const { blurRadius, isResolvingUri, thumbnail, title, resizeMode } = this.props;
|
||||
const atStyle = this.state.autoThumbStyle;
|
||||
|
||||
if (thumbnail && ((typeof thumbnail) === 'string')) {
|
||||
if (thumbnail && ((typeof thumbnail) === 'string') && !this.state.imageLoadFailed) {
|
||||
if (style == null) {
|
||||
style = fileItemMediaStyle.thumbnail;
|
||||
}
|
||||
|
||||
if (blurRadius > 0) {
|
||||
// No blur radius support in FastImage yet
|
||||
return (
|
||||
<Image source={{uri: thumbnail}}
|
||||
<Image
|
||||
source={{uri: thumbnail}}
|
||||
blurRadius={blurRadius}
|
||||
resizeMode={resizeMode ? resizeMode : "cover"}
|
||||
style={style} />
|
||||
style={style}
|
||||
/>);
|
||||
}
|
||||
|
||||
return (
|
||||
<FastImage
|
||||
source={{uri: thumbnail}}
|
||||
onError={() => this.setState({ imageLoadFailed: true })}
|
||||
resizeMode={this.getFastImageResizeMode(resizeMode)}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,19 +27,27 @@ class FileListItem extends React.PureComponent {
|
|||
|
||||
formatBytes = (bytes) => {
|
||||
if (bytes < 1048576) { // < 1MB
|
||||
const value = (bytes / 1024.0).toFixed(2);
|
||||
const value = (bytes / 1024.0).toFixed(0);
|
||||
return `${value} KB`;
|
||||
}
|
||||
|
||||
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`;
|
||||
}
|
||||
|
||||
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`;
|
||||
}
|
||||
|
||||
formatTitle = (title) => {
|
||||
if (!title) {
|
||||
return title;
|
||||
}
|
||||
|
||||
return (title.length > 80) ? title.substring(0, 77).trim() + '...' : title;
|
||||
}
|
||||
|
||||
getDownloadProgress = (fileInfo) => {
|
||||
return Math.ceil((fileInfo.written_bytes / fileInfo.total_bytes) * 100);
|
||||
}
|
||||
|
@ -85,7 +93,7 @@ class FileListItem extends React.PureComponent {
|
|||
</View>
|
||||
</View>)}
|
||||
|
||||
{!isResolving && <Text style={fileListStyle.title}>{title || name}</Text>}
|
||||
{!isResolving && <Text style={fileListStyle.title}>{this.formatTitle(title) || this.formatTitle(name)}</Text>}
|
||||
{!isResolving && channel &&
|
||||
<Link style={fileListStyle.publisher} text={channel} onPress={() => {
|
||||
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';
|
||||
|
||||
const screenDimension = Dimensions.get('window');
|
||||
const screenWidth = screenDimension.width;
|
||||
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
|
||||
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 mediaHeight = (screenWidth / (screenHeight - verticalMargin)) * mediaWidth;
|
||||
const mediaHeight = ((screenWidth / screenHeight) * ((screenWidthPixels <= 720) ? screenWidth : mediaWidth)) - verticalMargin;
|
||||
|
||||
const discoverStyle = StyleSheet.create({
|
||||
container: {
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
import { Dimensions, StyleSheet } from 'react-native';
|
||||
import { Dimensions, PixelRatio, StyleSheet } from 'react-native';
|
||||
import Colors from './colors';
|
||||
|
||||
const screenDimension = Dimensions.get('window');
|
||||
const screenWidth = screenDimension.width;
|
||||
const screenHeight = screenDimension.height;
|
||||
const thumbnailHeight = 100;
|
||||
const thumbnailWidth = (screenHeight / screenWidth) * thumbnailHeight;
|
||||
const screenWidthPixels = PixelRatio.getPixelSizeForLayoutSize(screenWidth);
|
||||
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({
|
||||
item: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
marginTop: 16
|
||||
marginTop: 8
|
||||
},
|
||||
detailsContainer: {
|
||||
flex: 1
|
||||
|
@ -20,37 +23,37 @@ const fileListStyle = StyleSheet.create({
|
|||
thumbnail: {
|
||||
width: thumbnailWidth,
|
||||
height: thumbnailHeight,
|
||||
marginRight: 16,
|
||||
marginRight: (screenWidthPixels <= 720) ? 10 : 12,
|
||||
justifyContent: 'center'
|
||||
},
|
||||
title: {
|
||||
fontFamily: 'Metropolis-SemiBold',
|
||||
fontSize: 16
|
||||
fontSize: (screenWidthPixels <= 720) ? 12 : 16
|
||||
},
|
||||
uri: {
|
||||
fontFamily: 'Metropolis-SemiBold',
|
||||
fontSize: 14,
|
||||
fontSize: (screenWidthPixels <= 720) ? 12 : 14,
|
||||
marginBottom: 8
|
||||
},
|
||||
publisher: {
|
||||
fontFamily: 'Metropolis-SemiBold',
|
||||
fontSize: 14,
|
||||
marginTop: 3,
|
||||
fontSize: (screenWidthPixels <= 720) ? 12 : 14,
|
||||
marginTop: (screenWidthPixels <= 720) ? 1 : 3,
|
||||
color: Colors.LbryGreen
|
||||
},
|
||||
loading: {
|
||||
position: 'absolute'
|
||||
},
|
||||
downloadInfo: {
|
||||
marginTop: 8
|
||||
marginTop: (screenWidthPixels <= 720) ? 4 : 8
|
||||
},
|
||||
downloadStorage: {
|
||||
fontFamily: 'Metropolis-Regular',
|
||||
fontSize: 14,
|
||||
fontSize: (screenWidthPixels <= 720) ? 12 : 14,
|
||||
color: Colors.ChannelGrey
|
||||
},
|
||||
progress: {
|
||||
marginTop: 4,
|
||||
marginTop: (screenWidthPixels <= 720) ? 2 : 4,
|
||||
height: 3,
|
||||
flex: 1,
|
||||
flexDirection: 'row'
|
||||
|
|
|
@ -21,7 +21,7 @@ const searchStyle = StyleSheet.create({
|
|||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
marginTop: 16
|
||||
marginTop: 8
|
||||
},
|
||||
searchInput: {
|
||||
width: '100%',
|
||||
|
|
|
@ -40,6 +40,10 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
jumboMode true
|
||||
}
|
||||
|
||||
{% if args.sign -%}
|
||||
signingConfigs {
|
||||
release {
|
||||
|
@ -80,8 +84,9 @@ subprojects {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':react-native-video')
|
||||
compile project(':react-native-fast-image')
|
||||
compile project(':react-native-fetch-blob')
|
||||
compile project(':react-native-video')
|
||||
{%- for aar in aars %}
|
||||
compile(name: '{{ aar }}', ext: 'aar')
|
||||
{%- endfor -%}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
rootProject.name = 'browser'
|
||||
include ':react-native-video'
|
||||
project(':react-native-video').projectDir = new File(rootProject.projectDir, './react/node_modules/react-native-video/android-exoplayer')
|
||||
include ':react-native-fast-image'
|
||||
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, './react/node_modules/react-native-fast-image/android')
|
||||
include ':react-native-fetch-blob'
|
||||
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 com.brentvatne.react.ReactVideoPackage;
|
||||
import com.dylanvann.fastimage.FastImageViewPackage;
|
||||
import com.facebook.react.common.LifecycleState;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.ReactRootView;
|
||||
|
@ -103,6 +104,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
|||
.setBundleAssetName("index.android.bundle")
|
||||
.setJSMainModulePath("index")
|
||||
.addPackage(new MainReactPackage())
|
||||
.addPackage(new FastImageViewPackage())
|
||||
.addPackage(new ReactVideoPackage())
|
||||
.addPackage(new RNFetchBlobPackage())
|
||||
.addPackage(new LbryReactPackage())
|
||||
|
|
Loading…
Reference in a new issue