Unverified Commit ce6ee61a authored by jialing Lee's avatar jialing Lee Committed by GitHub

Merge pull request #2 from z372183629/master

合并官方最新代码
parents bb168453 fc0b620c
{
"presets": [
"react-native"
]
"presets": ["module:metro-react-native-babel-preset"]
}
version: 2
jobs:
build:
docker:
- image: node:9.2.0
working_directory: ~/app
steps:
- checkout
- run: yarn
- run: yarn test
\ No newline at end of file
build:
docker:
- image: 'circleci/node:latest'
steps:
- checkout
- restore_cache:
keys:
- yarn-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
- yarn-v1-{{ .Branch }}-
- yarn-v1-
- run:
name: install
command: yarn install
- run:
name: test
command: yarn run test
- save_cache:
paths:
- ~/.cache/yarn
key: yarn-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
......@@ -32,4 +32,6 @@ __snapshots__
.gitignore
.npmignore
prettier.config.js
yarn.lock
\ No newline at end of file
yarn.lock
babel.config.js
jest.config.js
\ No newline at end of file
This diff is collapsed.
......@@ -66,7 +66,7 @@ and
yarn add react-native-fast-image
# Automatic linking. (other linking methods listed below)
react-native link
react-native link react-native-fast-image
```
```jsx
......@@ -121,9 +121,17 @@ Headers to load the image with. e.g. `{ Authorization: 'someAuthToken' }`.
### `source.priority?: enum`
- `FastImage.priority.low` - Low Priority
- `FastImage.priority.normal` **(Default)** - Normal Priority
- `FastImage.priority.high` - High Priority
- `FastImage.priority.low` - Low Priority.
- `FastImage.priority.normal` **(Default)** - Normal Priority.
- `FastImage.priority.high` - High Priority.
---
### `source.cache?: enum`
- `FastImage.cacheControl.immutable` - **(Default)** - Only updates if url changes.
- `FastImage.cacheControl.web` - Use headers and follow normal caching procedures.
- `FastImage.cacheControl.cacheOnly` - Only show images from cache, do not make any network requests.
---
......@@ -174,6 +182,13 @@ Called when the image finishes loading, whether it was successful or an error.
A React Native style. Supports using `borderRadius`.
---
### `fallback: boolean`
If true will fallback to using `Image`.
In this case the image will still be styled and laid out the same way as `FastImage`.
## Static Methods
### `FastImage.preload: (source[]) => void`
......
......@@ -3,40 +3,38 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath "com.android.tools.build:gradle:2.3.3"
}
}
apply plugin: 'com.android.library'
apply plugin: "com.android.library"
def _ext = rootProject.ext
def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}
def _reactNativeVersion = _ext.has('reactNative') ? _ext.reactNative : '+'
def _compileSdkVersion = _ext.has('compileSdkVersion') ? _ext.compileSdkVersion : 23
def _buildToolsVersion = _ext.has('buildToolsVersion') ? _ext.buildToolsVersion : '23.0.1'
def _minSdkVersion = _ext.has('minSdkVersion') ? _ext.minSdkVersion : 16
def _targetSdkVersion = _ext.has('targetSdkVersion') ? _ext.targetSdkVersion : 22
def _glideVersion = _ext.has('glideVersion') ? _ext.glideVersion : '4.7.1'
def _excludeAppGlideModule = _ext.has('excludeAppGlideModule') ? _ext.excludeAppGlideModule : false
def _reactNativeVersion = safeExtGet("reactNative", "+")
def _compileSdkVersion = safeExtGet("compileSdkVersion", 26)
def _glideVersion = safeExtGet("glideVersion", "4.7.1")
android {
compileSdkVersion _compileSdkVersion
buildToolsVersion _buildToolsVersion
buildToolsVersion safeExtGet("buildToolsVersion", "26.0.3")
sourceSets {
main {
java {
if (_excludeAppGlideModule) {
srcDir 'src'
exclude '**/FastImageGlideModule.java'
if (safeExtGet("excludeAppGlideModule", false)) {
srcDir "src"
exclude "**/FastImageGlideModule.java"
}
}
}
}
defaultConfig {
minSdkVersion _minSdkVersion
targetSdkVersion _targetSdkVersion
minSdkVersion safeExtGet("minSdkVersion", 16)
targetSdkVersion safeExtGet("targetSdkVersion", 26)
versionCode 1
versionName "1.0"
}
......@@ -54,17 +52,17 @@ repositories {
dependencies {
//noinspection GradleDynamicVersion
compile "com.facebook.react:react-native:${_reactNativeVersion}"
compile "com.android.support:support-v4:${_compileSdkVersion}"
compile("com.github.bumptech.glide:glide:${_glideVersion}") {
exclude group: "com.android.support"
implementation "com.facebook.react:react-native:${_reactNativeVersion}"
implementation "com.android.support:support-v4:${safeExtGet("supportLibVersion", "27.1.1")}"
implementation("com.github.bumptech.glide:glide:${_glideVersion}") {
exclude group: "com.android.support", module: "glide"
}
compile("com.github.bumptech.glide:annotations:${_glideVersion}") {
exclude group: "com.android.support"
implementation("com.github.bumptech.glide:annotations:${_glideVersion}") {
exclude group: "com.android.support", module: "annotations"
}
annotationProcessor "com.github.bumptech.glide:compiler:${_glideVersion}"
compile("com.github.bumptech.glide:okhttp3-integration:${_glideVersion}") {
exclude group: "com.android.support"
exclude group: 'glide-parent'
implementation("com.github.bumptech.glide:okhttp3-integration:${_glideVersion}") {
exclude group: "com.android.support", module: "okhttp3-integration"
exclude group: "com.android.support", module: "glide-parent"
}
}
package com.dylanvann.fastimage;
public enum FastImageCacheControl {
IMMUTABLE,
WEB,
CACHE_ONLY
}
......@@ -11,13 +11,13 @@ import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.LibraryGlideModule;
import com.facebook.react.modules.network.OkHttpClientProvider;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import okhttp3.Interceptor;
import okhttp3.MediaType;
......@@ -34,6 +34,8 @@ import okio.Source;
@GlideModule
public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
private static DispatchingProgressListener progressListener = new DispatchingProgressListener();
@Override
public void registerComponents(
@NonNull Context context,
......@@ -43,7 +45,7 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
OkHttpClient client = OkHttpClientProvider
.getOkHttpClient()
.newBuilder()
.addInterceptor(createInterceptor(new DispatchingProgressListener()))
.addInterceptor(createInterceptor(progressListener))
.build();
OkHttpUrlLoader.Factory factory = new OkHttpUrlLoader.Factory(client);
registry.replace(GlideUrl.class, InputStream.class, factory);
......@@ -65,11 +67,11 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
}
static void forget(String key) {
DispatchingProgressListener.forget(key);
progressListener.forget(key);
}
static void expect(String key, FastImageProgressListener listener) {
DispatchingProgressListener.expect(key, listener);
progressListener.expect(key, listener);
}
private interface ResponseProgressListener {
......@@ -77,8 +79,8 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
}
private static class DispatchingProgressListener implements ResponseProgressListener {
private static final Map<String, FastImageProgressListener> LISTENERS = new HashMap<>();
private static final Map<String, Long> PROGRESSES = new HashMap<>();
private final Map<String, FastImageProgressListener> LISTENERS = new WeakHashMap<>();
private final Map<String, Long> PROGRESSES = new HashMap<>();
private final Handler handler;
......@@ -86,12 +88,12 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
this.handler = new Handler(Looper.getMainLooper());
}
static void forget(String key) {
void forget(String key) {
LISTENERS.remove(key);
PROGRESSES.remove(key);
}
static void expect(String key, FastImageProgressListener listener) {
void expect(String key, FastImageProgressListener listener) {
LISTENERS.put(key, listener);
}
......
......@@ -17,7 +17,7 @@ public class FastImageRequestListener implements RequestListener<Drawable> {
static final String REACT_ON_LOAD_EVENT = "onFastImageLoad";
static final String REACT_ON_LOAD_END_EVENT = "onFastImageLoadEnd";
private String key = null;
private String key;
FastImageRequestListener(String key) {
this.key = key;
......
package com.dylanvann.fastimage;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.load.model.Headers;
import com.facebook.react.views.imagehelper.ImageSource;
import javax.annotation.Nullable;
public class FastImageSource extends ImageSource {
private static final String LOCAL_RESOURCE_SCHEME = "res";
private static final String ANDROID_RESOURCE_SCHEME = "android.resource";
private Headers mHeaders;
private Uri mUri;
public static boolean isLocalResourceUri (Uri uri) {
return LOCAL_RESOURCE_SCHEME.equals(uri.getScheme());
}
public static boolean isResourceUri (Uri uri) {
return ANDROID_RESOURCE_SCHEME.equals(uri.getScheme());
}
public FastImageSource(Context context, String source) {
this(context, source, null);
}
public FastImageSource(Context context, String source, @Nullable Headers headers) {
this(context, source, 0.0d, 0.0d, headers);
}
public FastImageSource(Context context, String source, double width, double height, @Nullable Headers headers) {
super(context, source, width, height);
mHeaders = headers == null ? Headers.DEFAULT : headers;
mUri = super.getUri();
if (isLocalResourceUri(mUri)) {
// Convert res:/ scheme to android.resource:// so
// glide can understand the uri.
mUri = Uri.parse(mUri.toString().replace("res:/", ANDROID_RESOURCE_SCHEME + "://" + context.getPackageName() + "/"));
}
}
public boolean isBase64Resource () {
return mUri != null && "data".equals(mUri.getScheme());
}
@Override
public Uri getUri() {
return mUri;
}
public Headers getHeaders() {
return mHeaders;
}
public GlideUrl getGlideUrl() {
return new GlideUrl(getUri().toString(), getHeaders());
}
}
package com.dylanvann.fastimage;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.media.Image;
import android.net.Uri;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.load.model.Headers;
import com.bumptech.glide.load.model.LazyHeaders;
import com.bumptech.glide.request.RequestOptions;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.NoSuchKeyException;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.views.imagehelper.ImageSource;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
class FastImageViewConverter {
static GlideUrl glideUrl(ReadableMap source) {
final String uriProp = source.getString("uri");
// Get the headers prop and add to glideUrl.
GlideUrl glideUrl;
try {
final ReadableMap headersMap = source.getMap("headers");
ReadableMapKeySetIterator headersIterator = headersMap.keySetIterator();
LazyHeaders.Builder headersBuilder = new LazyHeaders.Builder();
while (headersIterator.hasNextKey()) {
String key = headersIterator.nextKey();
String value = headersMap.getString(key);
headersBuilder.addHeader(key, value);
}
LazyHeaders headers = headersBuilder.build();
glideUrl = new GlideUrl(uriProp, headers);
} catch (NoSuchKeyException e) {
// If there is no headers object.
glideUrl = new GlideUrl(uriProp);
}
return glideUrl;
}
private static final Drawable TRANSPARENT_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
private static final Map<String, FastImageCacheControl> FAST_IMAGE_CACHE_CONTROL_MAP =
new HashMap<String, FastImageCacheControl>() {{
put("immutable", FastImageCacheControl.IMMUTABLE);
put("web", FastImageCacheControl.WEB);
put("cacheOnly", FastImageCacheControl.CACHE_ONLY);
}};
private static Map<String, Priority> REACT_PRIORITY_MAP =
private static final Map<String, Priority> FAST_IMAGE_PRIORITY_MAP =
new HashMap<String, Priority>() {{
put("low", Priority.LOW);
put("normal", Priority.NORMAL);
put("high", Priority.HIGH);
}};
static Priority priority(ReadableMap source) {
// Get the priority prop.
String priorityProp = "normal";
try {
priorityProp = source.getString("priority");
} catch (Exception e) {
// Noop.
}
final Priority priority = REACT_PRIORITY_MAP.get(priorityProp);
return priority;
}
private static Map<String, ImageView.ScaleType> REACT_RESIZE_MODE_MAP =
private static final Map<String, ImageView.ScaleType> FAST_IMAGE_RESIZE_MODE_MAP =
new HashMap<String, ImageView.ScaleType>() {{
put("contain", ScaleType.FIT_CENTER);
put("cover", ScaleType.CENTER_CROP);
put("stretch", ScaleType.FIT_XY);
put("center", ScaleType.CENTER);
}};
// Resolve the source uri to a file path that android understands.
static FastImageSource getImageSource(Context context, ReadableMap source) {
return new FastImageSource(context, source.getString("uri"), getHeaders(source));
}
static Headers getHeaders(ReadableMap source) {
Headers headers = Headers.DEFAULT;
if (source.hasKey("headers")) {
ReadableMap headersMap = source.getMap("headers");
ReadableMapKeySetIterator iterator = headersMap.keySetIterator();
LazyHeaders.Builder builder = new LazyHeaders.Builder();
while (iterator.hasNextKey()) {
String header = iterator.nextKey();
String value = headersMap.getString(header);
builder.addHeader(header, value);
}
public static ScaleType scaleType(String resizeMode) {
if (resizeMode == null) resizeMode = "cover";
final ImageView.ScaleType scaleType = REACT_RESIZE_MODE_MAP.get(resizeMode);
return scaleType;
headers = builder.build();
}
return headers;
}
static RequestOptions getOptions(ReadableMap source) {
// Get priority.
final Priority priority = FastImageViewConverter.getPriority(source);
// Get cache control method.
final FastImageCacheControl cacheControl = FastImageViewConverter.getCacheControl(source);
DiskCacheStrategy diskCacheStrategy = DiskCacheStrategy.AUTOMATIC;
Boolean onlyFromCache = false;
Boolean skipMemoryCache = false;
switch (cacheControl) {
case WEB:
// If using none then OkHttp integration should be used for caching.
diskCacheStrategy = DiskCacheStrategy.NONE;
skipMemoryCache = true;
break;
case CACHE_ONLY:
onlyFromCache = true;
break;
case IMMUTABLE:
// Use defaults.
break;
}
return new RequestOptions()
.diskCacheStrategy(diskCacheStrategy)
.onlyRetrieveFromCache(onlyFromCache)
.skipMemoryCache(skipMemoryCache)
.priority(priority)
.placeholder(TRANSPARENT_DRAWABLE);
}
private static FastImageCacheControl getCacheControl(ReadableMap source) {
return getValueFromSource("cache", "immutable", FAST_IMAGE_CACHE_CONTROL_MAP, source);
}
private static Priority getPriority(ReadableMap source) {
return getValueFromSource("priority", "normal", FAST_IMAGE_PRIORITY_MAP, source);
}
static ScaleType getScaleType(String propValue) {
return getValue("resizeMode", "cover", FAST_IMAGE_RESIZE_MODE_MAP, propValue);
}
private static <T> T getValue(String propName, String defaultPropValue, Map<String, T> map, String propValue) {
if (propValue == null) propValue = defaultPropValue;
T value = map.get(propValue);
if (value == null)
throw new JSApplicationIllegalArgumentException("FastImage, invalid " + propName + " : " + propValue);
return value;
}
private static <T> T getValueFromSource(String propName, String defaultProp, Map<String, T> map, ReadableMap source) {
String propValue;
try {
propValue = source != null ? source.getString(propName) : null;
} catch (NoSuchKeyException e) {
propValue = null;
}
return getValue(propName, defaultProp, map, propValue);
}
}
package com.dylanvann.fastimage;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Priority;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.request.RequestOptions;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
......@@ -21,9 +18,9 @@ import com.facebook.react.uimanager.events.RCTEventEmitter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import javax.annotation.Nullable;
......@@ -36,8 +33,9 @@ class FastImageViewManager extends SimpleViewManager<FastImageViewWithUrl> imple
private static final String REACT_CLASS = "FastImageView";
private static final String REACT_ON_LOAD_START_EVENT = "onFastImageLoadStart";
private static final String REACT_ON_PROGRESS_EVENT = "onFastImageProgress";
private static final Drawable TRANSPARENT_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
private static final Map<String, List<FastImageViewWithUrl>> VIEWS_FOR_URLS = new HashMap<>();
private static final Map<String, List<FastImageViewWithUrl>> VIEWS_FOR_URLS = new WeakHashMap<>();
@Nullable
private RequestManager requestManager = null;
@Override
......@@ -47,15 +45,21 @@ class FastImageViewManager extends SimpleViewManager<FastImageViewWithUrl> imple
@Override
protected FastImageViewWithUrl createViewInstance(ThemedReactContext reactContext) {
requestManager = Glide.with(reactContext);
if (isValidContextForGlide(reactContext)) {
requestManager = Glide.with(reactContext);
}
return new FastImageViewWithUrl(reactContext);
}
@ReactProp(name = "source")
public void setSrc(FastImageViewWithUrl view, @Nullable ReadableMap source) {
if (source == null) {
if (source == null || !source.hasKey("uri") || isNullOrEmpty(source.getString("uri"))) {
// Cancel existing requests.
requestManager.clear(view);
if (requestManager != null) {
requestManager.clear(view);
}
if (view.glideUrl != null) {
FastImageOkHttpProgressGlideModule.forget(view.glideUrl.toStringUrl());
}
......@@ -64,15 +68,15 @@ class FastImageViewManager extends SimpleViewManager<FastImageViewWithUrl> imple
return;
}
// Get the GlideUrl which contains header info.
GlideUrl glideUrl = FastImageViewConverter.glideUrl(source);
view.glideUrl = glideUrl;
// Get priority.
final Priority priority = FastImageViewConverter.priority(source);
//final GlideUrl glideUrl = FastImageViewConverter.getGlideUrl(view.getContext(), source);
final FastImageSource imageSource = FastImageViewConverter.getImageSource(view.getContext(), source);
final GlideUrl glideUrl = imageSource.getGlideUrl();
// Cancel existing request.
requestManager.clear(view);
view.glideUrl = glideUrl;
if (requestManager != null) {
requestManager.clear(view);
}
String key = glideUrl.toStringUrl();
FastImageOkHttpProgressGlideModule.expect(key, this);
......@@ -89,54 +93,59 @@ class FastImageViewManager extends SimpleViewManager<FastImageViewWithUrl> imple
int viewId = view.getId();
eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_START_EVENT, new WritableNativeMap());
RequestOptions options = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.priority(priority)
.dontTransform()
.placeholder(TRANSPARENT_DRAWABLE);
requestManager
.load(glideUrl)
.apply(options)
.listener(new FastImageRequestListener(key))
.into(view);
if (requestManager != null) {
requestManager
// This will make this work for remote and local images. e.g.
// - file:///
// - content://
// - res:/
// - android.resource://
// - data:image/png;base64
.load(
imageSource.isBase64Resource() ? imageSource.getSource() :
imageSource.isResource() ? imageSource.getUri() : imageSource.getGlideUrl()
)
.apply(FastImageViewConverter.getOptions(source))
.listener(new FastImageRequestListener(key))
.into(view);
}
}
@ReactProp(name = "resizeMode")
public void setResizeMode(FastImageViewWithUrl view, String resizeMode) {
final FastImageViewWithUrl.ScaleType scaleType = FastImageViewConverter.scaleType(resizeMode);
final FastImageViewWithUrl.ScaleType scaleType = FastImageViewConverter.getScaleType(resizeMode);
view.setScaleType(scaleType);
}
@Override
public void onDropViewInstance(FastImageViewWithUrl view) {
// This will cancel existing requests.
requestManager.clear(view);
final String key = view.glideUrl.toString();
FastImageOkHttpProgressGlideModule.forget(key);
List<FastImageViewWithUrl> viewsForKey = VIEWS_FOR_URLS.get(key);
if (viewsForKey != null) {
viewsForKey.remove(view);
if (viewsForKey.size() == 0) VIEWS_FOR_URLS.remove(key);
if (requestManager != null) {
requestManager.clear(view);
}
if (view.glideUrl != null) {
final String key = view.glideUrl.toString();
FastImageOkHttpProgressGlideModule.forget(key);
List<FastImageViewWithUrl> viewsForKey = VIEWS_FOR_URLS.get(key);
if (viewsForKey != null) {
viewsForKey.remove(view);
if (viewsForKey.size() == 0) VIEWS_FOR_URLS.remove(key);
}
}
super.onDropViewInstance(view);
}
@Override
@Nullable
public Map getExportedCustomDirectEventTypeConstants() {
return MapBuilder.of(
REACT_ON_LOAD_START_EVENT,
MapBuilder.of("registrationName", REACT_ON_LOAD_START_EVENT),
REACT_ON_PROGRESS_EVENT,
MapBuilder.of("registrationName", REACT_ON_PROGRESS_EVENT),
REACT_ON_LOAD_EVENT,
MapBuilder.of("registrationName", REACT_ON_LOAD_EVENT),
REACT_ON_ERROR_EVENT,
MapBuilder.of("registrationName", REACT_ON_ERROR_EVENT),
REACT_ON_LOAD_END_EVENT,
MapBuilder.of("registrationName", REACT_ON_LOAD_END_EVENT)
);
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return MapBuilder.<String, Object>builder()
.put(REACT_ON_LOAD_START_EVENT, MapBuilder.of("registrationName", REACT_ON_LOAD_START_EVENT))
.put(REACT_ON_PROGRESS_EVENT, MapBuilder.of("registrationName", REACT_ON_PROGRESS_EVENT))
.put(REACT_ON_LOAD_EVENT, MapBuilder.of("registrationName", REACT_ON_LOAD_EVENT))
.put(REACT_ON_ERROR_EVENT, MapBuilder.of("registrationName", REACT_ON_ERROR_EVENT))
.put(REACT_ON_LOAD_END_EVENT, MapBuilder.of("registrationName", REACT_ON_LOAD_END_EVENT))
.build();
}
@Override
......@@ -160,4 +169,39 @@ class FastImageViewManager extends SimpleViewManager<FastImageViewWithUrl> imple
return 0.5f;
}
private boolean isNullOrEmpty(final String url) {
return url == null || url.trim().isEmpty();
}
private static boolean isValidContextForGlide(final Context context) {
if (context == null) {
return false;
}
if (context instanceof Activity) {
final Activity activity = (Activity) context;
if (isActivityDestroyed(activity)) {
return false;
}
}
if (context instanceof ThemedReactContext) {
final Context baseContext = ((ThemedReactContext) context).getBaseContext();
if (baseContext instanceof Activity) {
final Activity baseActivity = (Activity) baseContext;
return !isActivityDestroyed(baseActivity);
}
}
return true;
}
private static boolean isActivityDestroyed(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return activity.isDestroyed() || activity.isFinishing();
} else {
return activity.isFinishing() || activity.isChangingConfigurations();
}
}
}
package com.dylanvann.fastimage;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.request.RequestOptions;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.views.imagehelper.ImageSource;
class FastImageViewModule extends ReactContextBaseJavaModule {
......@@ -29,8 +24,6 @@ class FastImageViewModule extends ReactContextBaseJavaModule {
return REACT_CLASS;
}
private static Drawable TRANSPARENT_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
@ReactMethod
public void preload(final ReadableArray sources) {
final Activity activity = getCurrentActivity();
......@@ -40,18 +33,21 @@ class FastImageViewModule extends ReactContextBaseJavaModule {
public void run() {
for (int i = 0; i < sources.size(); i++) {
final ReadableMap source = sources.getMap(i);
final GlideUrl glideUrl = FastImageViewConverter.glideUrl(source);
final Priority priority = FastImageViewConverter.priority(source);
RequestOptions options = new RequestOptions()
.placeholder(TRANSPARENT_DRAWABLE)
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.priority(priority);
final FastImageSource imageSource = FastImageViewConverter.getImageSource(activity, source);
Glide
.with(activity.getApplicationContext())
.applyDefaultRequestOptions(options)
.load(glideUrl)
// This will make this work for remote and local images. e.g.
// - file:///
// - content://
// - res:/
// - android.resource://
// - data:image/png;base64
.load(
imageSource.isBase64Resource() ? imageSource.getSource() :
imageSource.isResource() ? imageSource.getUri() : imageSource.getGlideUrl()
)
.apply(FastImageViewConverter.getOptions(source))
.preload();
}
}
......
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, FFFPriority) {
FFFPriorityLow,
......@@ -6,17 +7,27 @@ typedef NS_ENUM(NSInteger, FFFPriority) {
FFFPriorityHigh
};
/**
* Object containing an image URL and associated metadata.
*/
typedef NS_ENUM(NSInteger, FFFCacheControl) {
FFFCacheControlImmutable,
FFFCacheControlWeb,
FFFCacheControlCacheOnly
};
// Object containing an image uri and metadata.
@interface FFFastImageSource : NSObject
@property (nonatomic) NSURL* uri;
// uri for image, or base64
@property (nonatomic) NSURL* url;
// priority for image request
@property (nonatomic) FFFPriority priority;
// headers for the image request
@property (nonatomic) NSDictionary *headers;
// cache control mode
@property (nonatomic) FFFCacheControl cacheControl;
- (instancetype)initWithURL:(NSURL *)url
priority:(FFFPriority)priority
headers:(NSDictionary *)headers;
headers:(NSDictionary *)headers
cacheControl:(FFFCacheControl)cacheControl;
@end
......@@ -5,12 +5,14 @@
- (instancetype)initWithURL:(NSURL *)url
priority:(FFFPriority)priority
headers:(NSDictionary *)headers
cacheControl:(FFFCacheControl)cacheControl
{
self = [super init];
if (self) {
_uri = url;
_url = url;
_priority = priority;
_headers = headers;
_cacheControl = cacheControl;
}
return self;
}
......
......@@ -54,10 +54,46 @@
}
}
- (void)sendOnLoad:(UIImage *)image {
onLoadEvent = @{
@"width":[NSNumber numberWithDouble:image.size.width],
@"height":[NSNumber numberWithDouble:image.size.height]
};
if (_onFastImageLoad) {
_onFastImageLoad(onLoadEvent);
}
}
- (void)setSource:(FFFastImageSource *)source {
if (_source != source) {
_source = source;
// Load base64 images.
NSString* url = [_source.url absoluteString];
if (url && [url hasPrefix:@"data:image"]) {
if (_onFastImageLoadStart) {
_onFastImageLoadStart(@{});
hasSentOnLoadStart = YES;
} {
hasSentOnLoadStart = NO;
}
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:_source.url]];
[self setImage:image];
if (_onFastImageProgress) {
_onFastImageProgress(@{
@"loaded": @(1),
@"total": @(1)
});
}
hasCompleted = YES;
[self sendOnLoad:image];
if (_onFastImageLoadEnd) {
_onFastImageLoadEnd(@{});
}
return;
}
// Set headers.
[_source.headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString* header, BOOL *stop) {
[[SDWebImageDownloader sharedDownloader] setValue:header forHTTPHeaderField:key];
......@@ -78,6 +114,17 @@
break;
}
switch (_source.cacheControl) {
case FFFCacheControlWeb:
options |= SDWebImageRefreshCached;
break;
case FFFCacheControlCacheOnly:
options |= SDWebImageCacheMemoryOnly;
break;
case FFFCacheControlImmutable:
break;
}
if (_onFastImageLoadStart) {
_onFastImageLoadStart(@{});
hasSentOnLoadStart = YES;
......@@ -88,7 +135,12 @@
hasErrored = NO;
// Load the new source.
[self sd_setImageWithURL:_source.uri
// This will work for:
// - https://
// - file:///var/containers/Bundle/Application/50953EA3-CDA8-4367-A595-DE863A012336/ReactNativeFastImageExample.app/assets/src/images/fields.jpg
// - file:///var/containers/Bundle/Application/545685CB-777E-4B07-A956-2D25043BC6EE/ReactNativeFastImageExample.app/assets/src/images/plankton.gif
// - file:///Users/dylan/Library/Developer/CoreSimulator/Devices/61DC182B-3E72-4A18-8908-8A947A63A67F/data/Containers/Data/Application/AFC2A0D2-A1E5-48C1-8447-C42DA9E5299D/Documents/images/E1F1D5FC-88DB-492F-AD33-B35A045D626A.jpg"
[self sd_setImageWithURL:_source.url
placeholderImage:nil
options:options
progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
......@@ -112,13 +164,7 @@
}
} else {
hasCompleted = YES;
onLoadEvent = @{
@"width":[NSNumber numberWithDouble:image.size.width],
@"height":[NSNumber numberWithDouble:image.size.height]
};
if (_onFastImageLoad) {
_onFastImageLoad(onLoadEvent);
}
[self sendOnLoad:image];
if (_onFastImageLoadEnd) {
_onFastImageLoadEnd(@{});
}
......
......@@ -27,7 +27,7 @@ RCT_EXPORT_METHOD(preload:(nonnull NSArray<FFFastImageSource *> *)sources)
[source.headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString* header, BOOL *stop) {
[[SDWebImageDownloader sharedDownloader] setValue:header forHTTPHeaderField:key];
}];
[urls setObject:source.uri atIndexedSubscript:idx];
[urls setObject:source.url atIndexedSubscript:idx];
}];
[[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:urls];
......
......@@ -4,27 +4,35 @@
@implementation RCTConvert (FFFastImage)
RCT_ENUM_CONVERTER(FFFPriority, (@{
@"low": @(FFFPriorityLow),
@"normal": @(FFFPriorityNormal),
@"high": @(FFFPriorityHigh),
}), FFFPriorityNormal, integerValue);
@"low": @(FFFPriorityLow),
@"normal": @(FFFPriorityNormal),
@"high": @(FFFPriorityHigh),
}), FFFPriorityNormal, integerValue);
RCT_ENUM_CONVERTER(FFFCacheControl, (@{
@"immutable": @(FFFCacheControlImmutable),
@"web": @(FFFCacheControlWeb),
@"cacheOnly": @(FFFCacheControlCacheOnly),
}), FFFCacheControlImmutable, integerValue);
+ (FFFastImageSource *)FFFastImageSource:(id)json {
if (!json) {
return nil;
}
NSString *URLString = json[@"uri"];
NSURL *url = [self NSURL:URLString];
NSString *uriString = json[@"uri"];
NSURL *uri = [self NSURL:uriString];
FFFPriority priority = [self FFFPriority:json[@"priority"]];
FFFCacheControl cacheControl = [self FFFCacheControl:json[@"cache"]];
NSDictionary *headers = [self NSDictionary:json[@"headers"]];
if (headers) {
__block BOOL allHeadersAreStrings = YES;
[headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, id header, BOOL *stop) {
if (![header isKindOfClass:[NSString class]]) {
RCTLogError(@"Values of HTTP headers passed must be of type string. "
"Value of header '%@' is not a string.", key);
"Value of header '%@' is not a string.", key);
allHeadersAreStrings = NO;
*stop = YES;
}
......@@ -34,9 +42,9 @@ RCT_ENUM_CONVERTER(FFFPriority, (@{
headers = nil;
}
}
FFFastImageSource *imageSource = [[FFFastImageSource alloc] initWithURL:url priority:priority headers:headers];
FFFastImageSource *imageSource = [[FFFastImageSource alloc] initWithURL:uri priority:priority headers:headers cacheControl:cacheControl];
return imageSource;
}
......
Subproject commit ad9f1a24360b2c7581f136e3bd987ff700862ce7
Subproject commit dc5c974b89509992d6c6e0d0510344fd0e35baa6
module.exports = {
preset: 'react-native',
modulePathIgnorePatterns: ['react-native-fast-image-example*'],
"transform": {
"^.+\\.(js)$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
},
modulePathIgnorePatterns: [
'react-native-fast-image-example*',
'react-native-fast-image-example-cocoapods*',
],
}
{
"name": "react-native-fast-image",
"version": "4.0.14",
"version": "5.0.11",
"description": "🚩 FastImage, performant React Native image component.",
"keywords": [
"cache",
......@@ -14,28 +14,30 @@
"url": "https://github.com/DylanVann/react-native-fast-image/issues"
},
"license": "(MIT AND Apache-2.0)",
"author": "Dylan Vann <dylanvann@gmail.com> (http://dylanvann.com)",
"author": "Dylan Vann <dylan@dylanvann.com> (https://dylanvann.com)",
"main": "src/index.js",
"types": "src/index.d.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/DylanVann/react-native-fast-image.git"
},
"scripts": {
"format": "prettier --write --list-different ./**/*.js",
"format": "prettier --write --list-different ./src/*.js",
"prepare": "git submodule update --init --recursive",
"test": "yarn run format && yarn run test:jest",
"test:jest": "jest ./src/*.js"
},
"devDependencies": {
"babel-jest": "^22.4.4",
"babel-preset-react-native": "^4.0.0",
"jest": "^22.4.4",
"prettier": "^1.12.1",
"@babel/core": "^7.1.2",
"babel-jest": "^23.6.0",
"jest": "^23.6.0",
"metro-react-native-babel-preset": "^0.48.1",
"prettier": "^1.14.3",
"prettier-check": "^2.0.0",
"prop-types": "^15.6.1",
"react": "^16.4.0",
"react-native": "^0.55.4",
"react-test-renderer": "16.4.0"
"prop-types": "^15.6.2",
"react": "^16.5.2",
"react-native": "^0.57.3",
"react-test-renderer": "16.5.2"
},
"peerDependencies": {
"prop-types": "*",
......
{
"presets": ["react-native"]
"presets": ["module:metro-react-native-babel-preset"]
}
......@@ -29,7 +29,23 @@ node_modules/react-native/flow-github/
[options]
emoji=true
esproposal.optional_chaining=enable
esproposal.nullish_coalescing=enable
module.system=haste
module.system.haste.use_name_reducers=true
# get basename
module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1'
# strip .js or .js.flow suffix
module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1'
# strip .ios suffix
module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1'
module.system.haste.paths.blacklist=.*/__tests__/.*
module.system.haste.paths.blacklist=.*/__mocks__/.*
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Animated/src/polyfills/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/Libraries/.*
munge_underscores=true
......@@ -51,4 +67,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
[version]
^0.67.0
^0.78.0
......@@ -33,6 +33,7 @@ local.properties
# node.js
#
node_modules/
ios/Pods/
npm-debug.log
yarn-error.log
......@@ -54,6 +55,3 @@ buck-out/
# Bundle artifact
*.jsbundle
# CocoaPods
ios/Pods
import React from 'react'
import { ScrollView, StatusBar, StyleSheet, Text, View } from 'react-native'
import Icon from './Icons/Icon'
import Section from './Section'
import PriorityExample from './PriorityExample'
import GifExample from './GifExample'
import BorderRadiusExample from './BorderRadiusExample'
import FeatureText from './FeatureText'
import ProgressExample from './ProgressExample'
import PreloadExample from './PreloadExample'
import StatusBarUnderlay, { STATUS_BAR_HEIGHT } from './StatusBarUnderlay'
const FastImageExample = () => (
<View style={styles.container}>
<StatusBar
translucent
barStyle="dark-content"
backgroundColor="transparent"
/>
<ScrollView
style={styles.scrollContainer}
contentContainerStyle={styles.scrollContentContainer}
>
<View style={styles.contentContainer}>
<Section>
<Text style={styles.titleText}>🚩 FastImage</Text>
<FeatureText text="Tap images to reload examples." />
</Section>
<PriorityExample />
<GifExample />
<BorderRadiusExample />
<ProgressExample />
<PreloadExample />
</View>
</ScrollView>
<StatusBarUnderlay />
</View>
)
FastImageExample.navigationOptions = {
tabBarLabel: 'FastImage Example',
tabBarIcon: props => (
<Icon
name="ios-information-circle-outline"
focusedName="ios-information-circle"
{...props}
/>
),
}
const styles = StyleSheet.create({
titleText: {
fontWeight: '900',
marginBottom: 20,
color: '#222',
},
contentContainer: {
marginTop: 20,
marginBottom: 20,
},
image: {
flex: 1,
height: 100,
backgroundColor: '#ddd',
margin: 10,
},
container: {
flex: 1,
alignItems: 'stretch',
backgroundColor: '#fff',
},
scrollContainer: {
marginTop: STATUS_BAR_HEIGHT,
},
scrollContentContainer: {
alignItems: 'stretch',
flex: 0,
},
})
export default FastImageExample
import React, { Component } from 'react'
import { FlatList, StyleSheet, Text, View } from 'react-native'
import StatusBarUnderlay, { STATUS_BAR_HEIGHT } from './StatusBarUnderlay'
const getImageUrl = (id, width, height) =>
`https://unsplash.it/${width}/${height}?image=${id}`
class ImageGrid extends Component {
constructor(props: Object) {
super(props)
fetch('https://unsplash.it/list')
.then(res => res.json())
.then(this._onFetchImagesSuccess)
.catch(this._onFetchImagesError)
}
state = {
images: [],
itemHeight: 0,
}
_onLayout = e => {
const width = e.nativeEvent.layout.width
this.setState({
itemHeight: width / 4,
})
}
_onFetchImagesError = () => {
this.setState({
error: true,
})
}
_onFetchImagesSuccess = images => {
this.setState({
images,
})
}
_getItemLayout = (data, index) => {
const { itemHeight } = this.state
return { length: itemHeight, offset: itemHeight * index, index }
}
_renderItem = ({ item }) => {
const ImageComponent = this.props.ImageComponent
const uri = getImageUrl(item.id, 100, 100)
return (
<View style={styles.imageContainer}>
<ImageComponent source={{ uri }} style={styles.image} />
</View>
)
}
_extractKey = item => {
return item.id
}
render() {
if (this.state.error) {
return (
<View style={styles.container}>
<Text style={styles.text}>Error fetching images.</Text>
</View>
)
}
return (
<View style={styles.container}>
<FlatList
onLayout={this._onLayout}
style={styles.list}
columnWrapperStyle={[
styles.columnWrapper,
{ height: this.state.itemHeight },
]}
data={this.state.images}
renderItem={this._renderItem}
numColumns={4}
keyExtractor={this._extractKey}
getItemLayout={this._getItemLayout}
/>
<StatusBarUnderlay />
</View>
)
}
}
const MARGIN = 2
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'stretch',
justifyContent: 'center',
},
text: {
textAlign: 'center',
},
list: {
marginTop: STATUS_BAR_HEIGHT,
flex: 1,
},
columnWrapper: {
flex: 1,
flexDirection: 'row',
marginLeft: -MARGIN,
marginRight: -MARGIN,
},
image: {
flex: 1,
width: null,
height: null,
margin: MARGIN,
backgroundColor: '#eee',
},
imageContainer: {
flex: 1,
alignItems: 'stretch',
},
})
export default ImageGrid
import React, { Component } from 'react'
import { StyleSheet, View } from 'react-native'
import SectionFlex from './SectionFlex'
import FastImage from 'react-native-fast-image'
import Section from './Section'
import FeatureText from './FeatureText'
import uuid from 'uuid/v4'
import Button from './Button'
import { createImageProgress } from 'react-native-image-progress'
const IMAGE_URL =
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
const Image = createImageProgress(FastImage)
class PreloadExample extends Component {
state = {
show: false,
url: IMAGE_URL,
}
bustCache = () => {
const key = uuid()
const bust = `?bust=${key}`
// Preload images. This can be called anywhere.
const url = IMAGE_URL + bust
this.setState({
url,
show: false,
})
}
preload = () => {
FastImage.preload([{ uri: this.state.url }])
}
showImage = () => {
this.setState({ show: true })
}
render() {
return (
<View>
<Section>
<FeatureText text="• Preloading." />
<FeatureText text="• Progress indication using react-native-image-progress." />
</Section>
<SectionFlex style={styles.section} onPress={this.props.onPressReload}>
{this.state.show ? (
<Image style={styles.image} source={{ uri: this.state.url }} />
) : (
<View style={styles.image} />
)}
<View style={{ flexDirection: 'row', marginHorizontal: 10 }}>
<View style={{ flex: 1 }}>
<Button text="Bust" onPress={this.bustCache} />
</View>
<View style={{ flex: 1 }}>
<Button text="Preload" onPress={this.preload} />
</View>
<View style={{ flex: 1 }}>
<Button text="Render" onPress={this.showImage} />
</View>
</View>
</SectionFlex>
</View>
)
}
}
const styles = StyleSheet.create({
section: {
flexDirection: 'column',
alignItems: 'center',
},
image: {
backgroundColor: '#ddd',
margin: 10,
height: 100,
width: 100,
},
})
export default PreloadExample
import React from 'react'
import { StyleSheet, View } from 'react-native'
import withCacheBust from './withCacheBust'
import SectionFlex from './SectionFlex'
import FastImage from 'react-native-fast-image'
import Section from './Section'
import FeatureText from './FeatureText'
const IMAGE_URL = 'https://media.giphy.com/media/GEsoqZDGVoisw/giphy.gif'
const getTestProgressCallbacks = label => ({
onLoadStart: () => console.log(`${label} - onLoadStart`),
onProgress: e =>
console.log(
`${label} - onProgress - ${e.nativeEvent.loaded / e.nativeEvent.total}`,
),
onLoad: e => console.log(`${label} - onLoad`, e.nativeEvent),
onError: () => console.log(`${label} - onError`),
onLoadEnd: () => console.log(`${label} - onLoadEnd`),
})
const ProgressExample = ({ onPressReload, bust }) => (
<View>
<Section>
<FeatureText text="• Progress callbacks." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage
style={styles.image}
source={{
uri: IMAGE_URL + bust,
}}
{...getTestProgressCallbacks('ProgressExample')}
/>
</SectionFlex>
</View>
)
const styles = StyleSheet.create({
image: {
height: 100,
backgroundColor: '#ddd',
margin: 20,
width: 100,
flex: 0,
},
})
export default withCacheBust(ProgressExample)
import React from 'react'
import { StyleSheet, TouchableOpacity } from 'react-native'
export default ({ children, onPress, style }) => (
<TouchableOpacity style={[styles.sectionFlex, style]} onPress={onPress}>
{children}
</TouchableOpacity>
)
const styles = StyleSheet.create({
sectionFlex: {
backgroundColor: '#eee',
flexDirection: 'row',
justifyContent: 'center',
marginTop: 10,
marginBottom: 10,
marginLeft: -10,
marginRight: -10,
},
})
import React, { Component } from 'react'
import uuid from 'uuid/v4'
export default BaseComponent => {
class WithCacheBust extends Component {
state = { bust: '?bust' }
onPressReload = () => {
// Force complete re-render and bust image cache.
const key = uuid()
const bust = `?bust=${key}`
this.setState({ bust })
}
render() {
return (
<BaseComponent
bust={this.state.bust}
onPressReload={this.onPressReload}
/>
)
}
}
WithCacheBust.displayName = `withCacheBust${BaseComponent.displayName}`
return WithCacheBust
}
import 'react-native';
import React from 'react';
import App from '../App';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
const tree = renderer.create(
<App />
);
});
......@@ -45,12 +45,12 @@ android_library(
android_build_config(
name = "build_config",
package = "com.reactnativefastimagecocoapodsexample",
package = "com.reactnativefastimageexamplecocoapods",
)
android_resource(
name = "res",
package = "com.reactnativefastimagecocoapodsexample",
package = "com.reactnativefastimageexamplecocoapods",
res = "src/main/res",
)
......
......@@ -94,13 +94,13 @@ def enableSeparateBuildPerCPUArchitecture = false
def enableProguardInReleaseBuilds = false
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "com.reactnativefastimagecocoapodsexample"
minSdkVersion 16
targetSdkVersion 22
applicationId "com.reactnativefastimageexamplecocoapods"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
ndk {
......@@ -137,9 +137,12 @@ android {
}
dependencies {
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:+" // From node_modules
compile project(':react-native-vector-icons')
compile project(':react-native-image-picker')
compile project(':react-native-fast-image')
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation "com.facebook.react:react-native:+" // From node_modules
}
// Run this once to be able to run the application with BUCK
......
......@@ -15,56 +15,3 @@
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Disabling obfuscation is useful if you collect stack traces from production crashes
# (unless you are using a system that supports de-obfuscate the stack traces).
-dontobfuscate
# React Native
# Keep our interfaces so they can be used by other ProGuard rules.
# See http://sourceforge.net/p/proguard/bugs/466/
-keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
-keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
# Do not strip any method/class that is annotated with @DoNotStrip
-keep @com.facebook.proguard.annotations.DoNotStrip class *
-keep @com.facebook.common.internal.DoNotStrip class *
-keepclassmembers class * {
@com.facebook.proguard.annotations.DoNotStrip *;
@com.facebook.common.internal.DoNotStrip *;
}
-keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
void set*(***);
*** get*();
}
-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
-keep class * extends com.facebook.react.bridge.NativeModule { *; }
-keepclassmembers,includedescriptorclasses class * { native <methods>; }
-keepclassmembers class * { @com.facebook.react.uimanager.UIProp <fields>; }
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp <methods>; }
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup <methods>; }
-dontwarn com.facebook.react.**
# TextLayoutBuilder uses a non-public Android constructor within StaticLayout.
# See libs/proxy/src/main/java/com/facebook/fbui/textlayoutbuilder/proxy for details.
-dontwarn android.text.StaticLayout
# okhttp
-keepattributes Signature
-keepattributes *Annotation*
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
# okio
-keep class sun.misc.Unsafe { *; }
-dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.**
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.reactnativefastimagecocoapodsexample">
package="com.reactnativefastimageexamplecocoapods">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:name=".MainApplication"
......
package com.reactnativefastimagecocoapodsexample;
package com.reactnativefastimageexamplecocoapods;
import com.facebook.react.ReactActivity;
......@@ -10,6 +10,6 @@ public class MainActivity extends ReactActivity {
*/
@Override
protected String getMainComponentName() {
return "ReactNativeFastImageCocoaPodsExample";
return "ReactNativeFastImageExampleCocoaPods";
}
}
package com.reactnativefastimagecocoapodsexample;
package com.reactnativefastimageexample;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.oblador.vectoricons.VectorIconsPackage;
import com.imagepicker.ImagePickerPackage;
import com.dylanvann.fastimage.FastImageViewPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
......@@ -22,7 +25,10 @@ public class MainApplication extends Application implements ReactApplication {
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage()
new MainReactPackage(),
new VectorIconsPackage(),
new ImagePickerPackage(),
new FastImageViewPackage()
);
}
......
<resources>
<string name="app_name">ReactNativeFastImageCocoaPodsExample</string>
<string name="app_name">ReactNativeFastImageExampleCocoaPods</string>
</resources>
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
buildToolsVersion = "27.0.3"
minSdkVersion = 16
compileSdkVersion = 27
targetSdkVersion = 26
supportLibVersion = "27.1.1"
}
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.android.tools.build:gradle:3.1.4'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......@@ -16,12 +24,16 @@ allprojects {
repositories {
mavenLocal()
jcenter()
maven {
url "https://maven.google.com"
}
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
google()
}
}
task wrapper(type: Wrapper) {
gradleVersion = '4.4'
distributionUrl = distributionUrl.replace("bin", "all")
}
......@@ -16,5 +16,3 @@
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.useDeprecatedNdk=true
......@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
#!/usr/bin/env bash
#!/usr/bin/env sh
##############################################################################
##
......@@ -6,20 +6,38 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
warn () {
echo "$*"
}
die ( ) {
die () {
echo
echo "$*"
echo
......@@ -30,6 +48,7 @@ die ( ) {
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
......@@ -40,31 +59,11 @@ case "`uname`" in
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
......@@ -90,7 +89,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
......@@ -114,6 +113,7 @@ fi
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
......@@ -154,11 +154,19 @@ if $cygwin ; then
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
exec "$JAVACMD" "$@"
......@@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
......@@ -46,10 +46,9 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
......@@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
......
rootProject.name = 'ReactNativeFastImageCocoaPodsExample'
rootProject.name = 'ReactNativeFastImageExampleCocoaPods'
include ':react-native-image-picker'
project(':react-native-image-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-picker/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
include ':react-native-fast-image'
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fast-image/android')
include ':app'
{
"name": "ReactNativeFastImageCocoaPodsExample",
"displayName": "ReactNativeFastImageCocoaPodsExample"
"name": "ReactNativeFastImageExampleCocoaPods",
"displayName": "ReactNativeFastImageExampleCocoaPods"
}
\ No newline at end of file
import { AppRegistry } from 'react-native'
import App from './FastImage/App'
/** @format */
AppRegistry.registerComponent('ReactNativeFastImageCocoaPodsExample', () => App)
import {AppRegistry} from 'react-native';
import App from './src';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
platform :ios, '9.0'
target 'ReactNativeFastImageCocoaPodsExample' do
target 'ReactNativeFastImageExampleCocoaPods' do
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'CxxBridge',
......@@ -8,10 +8,15 @@ target 'ReactNativeFastImageCocoaPodsExample' do
'RCTText',
'RCTNetwork',
'RCTWebSocket',
'RCTAnimation',
'RCTImage',
]
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
pod 'react-native-image-picker', :path => '../node_modules/react-native-image-picker'
pod 'react-native-fast-image', :path => '../node_modules/react-native-fast-image'
end
\ No newline at end of file
PODS:
- boost-for-react-native (1.63.0)
- DoubleConversion (1.1.5)
- DoubleConversion (1.1.6)
- FLAnimatedImage (1.0.12)
- Folly (2016.09.26.00):
- Folly (2016.10.31.00):
- boost-for-react-native
- DoubleConversion
- glog
- glog (0.3.4)
- React (0.55.3):
- React/Core (= 0.55.3)
- react-native-fast-image (4.0.6):
- glog (0.3.5)
- React (0.57.3):
- React/Core (= 0.57.3)
- react-native-fast-image (5.0.10):
- FLAnimatedImage
- React
- SDWebImage/Core
- SDWebImage/GIF
- React/Core (0.55.3):
- yoga (= 0.55.3.React)
- React/CxxBridge (0.55.3):
- Folly (= 2016.09.26.00)
- react-native-image-picker (0.27.1):
- React
- React/Core (0.57.3):
- yoga (= 0.57.3.React)
- React/CxxBridge (0.57.3):
- Folly (= 2016.10.31.00)
- React/Core
- React/cxxreact
- React/cxxreact (0.55.3):
- React/cxxreact (0.57.3):
- boost-for-react-native (= 1.63.0)
- Folly (= 2016.09.26.00)
- Folly (= 2016.10.31.00)
- React/jschelpers
- React/jsinspector
- React/DevSupport (0.55.3):
- React/DevSupport (0.57.3):
- React/Core
- React/RCTWebSocket
- React/fishhook (0.55.3)
- React/jschelpers (0.55.3):
- Folly (= 2016.09.26.00)
- React/fishhook (0.57.3)
- React/jschelpers (0.57.3):
- Folly (= 2016.10.31.00)
- React/PrivateDatabase
- React/jsinspector (0.55.3)
- React/PrivateDatabase (0.55.3)
- React/RCTBlob (0.55.3):
- React/jsinspector (0.57.3)
- React/PrivateDatabase (0.57.3)
- React/RCTAnimation (0.57.3):
- React/Core
- React/RCTBlob (0.57.3):
- React/Core
- React/RCTImage (0.55.3):
- React/RCTImage (0.57.3):
- React/Core
- React/RCTNetwork
- React/RCTNetwork (0.55.3):
- React/RCTNetwork (0.57.3):
- React/Core
- React/RCTText (0.55.3):
- React/RCTText (0.57.3):
- React/Core
- React/RCTWebSocket (0.55.3):
- React/RCTWebSocket (0.57.3):
- React/Core
- React/fishhook
- React/RCTBlob
- RNVectorIcons (4.5.0):
- RNVectorIcons (6.0.2):
- React
- SDWebImage/Core (4.3.3)
- SDWebImage/GIF (4.3.3):
- SDWebImage/Core (4.4.2)
- SDWebImage/GIF (4.4.2):
- FLAnimatedImage (~> 1.0)
- SDWebImage/Core
- yoga (0.55.3.React)
- yoga (0.57.3.React)
DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- react-native-fast-image (from `../node_modules/react-native-fast-image`)
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
- React/Core (from `../node_modules/react-native`)
- React/CxxBridge (from `../node_modules/react-native`)
- React/DevSupport (from `../node_modules/react-native`)
- React/RCTAnimation (from `../node_modules/react-native`)
- React/RCTImage (from `../node_modules/react-native`)
- React/RCTNetwork (from `../node_modules/react-native`)
- React/RCTText (from `../node_modules/react-native`)
......@@ -68,19 +77,24 @@ DEPENDENCIES:
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
https://github.com/CocoaPods/Specs.git:
https://github.com/cocoapods/specs.git:
- boost-for-react-native
- DoubleConversion
- FLAnimatedImage
- Folly
- glog
- SDWebImage
EXTERNAL SOURCES:
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
glog:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
React:
:path: "../node_modules/react-native"
react-native-fast-image:
:path: "../node_modules/react-native-fast-image"
react-native-image-picker:
:path: "../node_modules/react-native-image-picker"
RNVectorIcons:
:path: "../node_modules/react-native-vector-icons"
yoga:
......@@ -88,16 +102,17 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
DoubleConversion: e22e0762848812a87afd67ffda3998d9ef29170c
DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd
FLAnimatedImage: 4a0b56255d9b05f18b6dd7ee06871be5d3b89e31
Folly: 211775e49d8da0ca658aebc8eab89d642935755c
glog: 1de0bb937dccdc981596d3b5825ebfb765017ded
React: aa2040dbb6f317b95314968021bd2888816e03d5
Folly: c89ac2d5c6ab169cd7397ef27485c44f35f742c7
glog: e8acf0ebbf99759d3ff18c86c292a5898282dcde
React: 1fe0eb13d90b625d94c3b117c274dcfd2e760e11
react-native-fast-image: cba3d9bf9c2cf8ddb643d887a686c53a5dd90a2c
RNVectorIcons: c0dbfbf6068fefa240c37b0f71bd03b45dddac44
SDWebImage: de4d90b5bff3571eae7bd16202b1f43135409fa5
yoga: a23273df0088bf7f2bb7e5d7b00044ea57a2a54a
react-native-image-picker: f42de90075c5b1af53417af927631d909a1a746e
RNVectorIcons: 8c52e1e8da1153613fdef44748e865c25556cb9c
SDWebImage: 624d6e296c69b244bcede364c72ae0430ac14681
yoga: b1ce48b6cf950b98deae82838f5173ea7cf89e85
PODFILE CHECKSUM: ee9eca64053ac06cb269faee8f128dfd0a4c1de4
PODFILE CHECKSUM: 9c1b580892a7e8ba16c3ef11342f53e075ff596a
COCOAPODS: 1.5.0
COCOAPODS: 1.5.3
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0820"
LastUpgradeVersion = "0940"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
......@@ -29,9 +29,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "ReactNativeFastImageCocoaPodsExample-tvOS.app"
BlueprintName = "ReactNativeFastImageCocoaPodsExample-tvOS"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPods-tvOS.app"
BlueprintName = "ReactNativeFastImageExampleCocoaPods-tvOS"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
......@@ -43,9 +43,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E48F1E0B4A5D006451C7"
BuildableName = "ReactNativeFastImageCocoaPodsExample-tvOSTests.xctest"
BlueprintName = "ReactNativeFastImageCocoaPodsExample-tvOSTests"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPods-tvOSTests.xctest"
BlueprintName = "ReactNativeFastImageExampleCocoaPods-tvOSTests"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
......@@ -61,9 +61,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E48F1E0B4A5D006451C7"
BuildableName = "ReactNativeFastImageCocoaPodsExample-tvOSTests.xctest"
BlueprintName = "ReactNativeFastImageCocoaPodsExample-tvOSTests"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPods-tvOSTests.xctest"
BlueprintName = "ReactNativeFastImageExampleCocoaPods-tvOSTests"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
......@@ -71,9 +71,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "ReactNativeFastImageCocoaPodsExample-tvOS.app"
BlueprintName = "ReactNativeFastImageCocoaPodsExample-tvOS"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPods-tvOS.app"
BlueprintName = "ReactNativeFastImageExampleCocoaPods-tvOS"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
......@@ -94,9 +94,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "ReactNativeFastImageCocoaPodsExample-tvOS.app"
BlueprintName = "ReactNativeFastImageCocoaPodsExample-tvOS"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPods-tvOS.app"
BlueprintName = "ReactNativeFastImageExampleCocoaPods-tvOS"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
......@@ -113,9 +113,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "ReactNativeFastImageCocoaPodsExample-tvOS.app"
BlueprintName = "ReactNativeFastImageCocoaPodsExample-tvOS"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPods-tvOS.app"
BlueprintName = "ReactNativeFastImageExampleCocoaPods-tvOS"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
......
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
LastUpgradeVersion = "0940"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
......@@ -29,9 +29,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "ReactNativeFastImageCocoaPodsExample.app"
BlueprintName = "ReactNativeFastImageCocoaPodsExample"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPods.app"
BlueprintName = "ReactNativeFastImageExampleCocoaPods"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
......@@ -43,9 +43,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
BuildableName = "ReactNativeFastImageCocoaPodsExampleTests.xctest"
BlueprintName = "ReactNativeFastImageCocoaPodsExampleTests"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPodsTests.xctest"
BlueprintName = "ReactNativeFastImageExampleCocoaPodsTests"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
......@@ -61,9 +61,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
BuildableName = "ReactNativeFastImageCocoaPodsExampleTests.xctest"
BlueprintName = "ReactNativeFastImageCocoaPodsExampleTests"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPodsTests.xctest"
BlueprintName = "ReactNativeFastImageExampleCocoaPodsTests"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
......@@ -71,9 +71,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "ReactNativeFastImageCocoaPodsExample.app"
BlueprintName = "ReactNativeFastImageCocoaPodsExample"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPods.app"
BlueprintName = "ReactNativeFastImageExampleCocoaPods"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
......@@ -94,9 +94,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "ReactNativeFastImageCocoaPodsExample.app"
BlueprintName = "ReactNativeFastImageCocoaPodsExample"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPods.app"
BlueprintName = "ReactNativeFastImageExampleCocoaPods"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
......@@ -113,9 +113,9 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "ReactNativeFastImageCocoaPodsExample.app"
BlueprintName = "ReactNativeFastImageCocoaPodsExample"
ReferencedContainer = "container:ReactNativeFastImageCocoaPodsExample.xcodeproj">
BuildableName = "ReactNativeFastImageExampleCocoaPods.app"
BlueprintName = "ReactNativeFastImageExampleCocoaPods"
ReferencedContainer = "container:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
......
......@@ -2,7 +2,7 @@
<Workspace
version = "1.0">
<FileRef
location = "group:ReactNativeFastImageCocoaPodsExample.xcodeproj">
location = "group:ReactNativeFastImageExampleCocoaPods.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
......@@ -19,7 +19,7 @@
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"ReactNativeFastImageCocoaPodsExample"
moduleName:@"ReactNativeFastImageExampleCocoaPods"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
......
......@@ -18,7 +18,7 @@
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="ReactNativeFastImageCocoaPodsExample" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="ReactNativeFastImageExampleCocoaPods" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
......
......@@ -5,11 +5,11 @@
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>ReactNativeFastImageCocoaPodsExample</string>
<string>ReactNativeFastImageExample</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
......@@ -26,6 +26,8 @@
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
......@@ -35,14 +37,22 @@
</dict>
</dict>
</dict>
<key>NSAppleMusicUsageDescription</key>
<string>We need access to your media.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photos.</string>
<key>UIAppFonts</key>
<array>
<string>AntDesign.ttf</string>
<string>Entypo.ttf</string>
<string>EvilIcons.ttf</string>
<string>Feather.ttf</string>
<string>FontAwesome.ttf</string>
<string>FontAwesome5_Brands.ttf</string>
<string>FontAwesome5_Regular.ttf</string>
<string>FontAwesome5_Solid.ttf</string>
<string>Foundation.ttf</string>
<string>Ionicons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
......
......@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
......
......@@ -14,11 +14,11 @@
#define TIMEOUT_SECONDS 600
#define TEXT_TO_LOOK_FOR @"Welcome to React Native!"
@interface ReactNativeFastImageCocoaPodsExampleTests : XCTestCase
@interface ReactNativeFastImageExampleCocoaPodsTests : XCTestCase
@end
@implementation ReactNativeFastImageCocoaPodsExampleTests
@implementation ReactNativeFastImageExampleCocoaPodsTests
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
{
......
{
"name": "ReactNativeFastImageCocoaPodsExample",
"name": "ReactNativeFastImageExampleCocoaPods",
"version": "0.0.1",
"private": true,
"scripts": {
......@@ -7,20 +7,22 @@
"test": "jest"
},
"dependencies": {
"react": "16.3.1",
"react-native": "0.55.3",
"react-native-fast-image": "file:../react-native-fast-image-4.0.6.tgz",
"react-native-image-progress": "^1.1.0",
"react-native-vector-icons": "^4.5.0",
"react-navigation": "^1.5.7",
"react-timeout": "^1.1.1",
"uuid": "3.0.1"
"react": "16.6.0-alpha.8af6728",
"react-native": "0.57.3",
"react-native-fast-image": "^5.0.11",
"react-native-image-picker": "^0.27.1",
"react-native-image-progress": "^1.1.1",
"react-native-status-bar-height": "^2.1.0",
"react-native-vector-icons": "^6.0.2",
"react-navigation": "^2.18.0",
"react-timeout": "^1.1.2",
"uuid": "^3.3.2"
},
"devDependencies": {
"babel-jest": "23.0.0-alpha.0",
"babel-preset-react-native": "4.0.0",
"jest": "22.4.2",
"react-test-renderer": "^16.3.0-alpha.1"
"babel-jest": "23.6.0",
"jest": "23.6.0",
"metro-react-native-babel-preset": "0.48.1",
"react-test-renderer": "16.6.0-alpha.8af6728"
},
"jest": {
"preset": "react-native"
......
import React, { Component } from 'react'
import { StyleSheet, View } from 'react-native'
import withCacheBust from './withCacheBust'
import SectionFlex from './SectionFlex'
import FastImage from 'react-native-fast-image'
import Section from './Section'
import FeatureText from './FeatureText'
const GIF_URL =
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
class AutoSizingImage extends Component {
state = {
height: 0,
width: 0,
}
onLoad = e => {
const {
nativeEvent: { width, height },
} = e
this.setState({ width, height })
if (this.props.onLoad) this.props.onLoad(e)
}
getHeight = () => {
if (!this.state.height) return this.props.defaultHeight
const ratio = this.state.height / this.state.width
const height = this.props.width * ratio
return height
}
render() {
const height = this.getHeight()
return (
<FastImage
{...this.props}
onLoad={this.onLoad}
style={[{ width: this.props.width, height }, this.props.style]}
/>
)
}
}
AutoSizingImage.defaultProps = {
defaultHeight: 300,
}
const AutoSizeExample = ({ onPressReload, bust }) => (
<View>
<Section>
<FeatureText text="• AutoSize." />
</Section>
<SectionFlex onPress={onPressReload}>
<AutoSizingImage
style={styles.image}
width={200}
source={{ uri: GIF_URL + bust }}
/>
</SectionFlex>
</View>
)
const styles = StyleSheet.create({
image: {
backgroundColor: '#ddd',
margin: 20,
flex: 0,
},
})
export default withCacheBust(AutoSizeExample)
......@@ -9,52 +9,52 @@ import FeatureText from './FeatureText'
const IMAGE_URL = 'https://media.giphy.com/media/GEsoqZDGVoisw/giphy.gif'
const BorderRadiusExample = ({ onPressReload, bust }) => (
<View>
<Section>
<FeatureText text="• Border radius." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage
style={styles.imageSquare}
source={{
uri: IMAGE_URL + bust,
}}
/>
<FastImage
style={styles.imageRectangular}
source={{
uri: IMAGE_URL + bust,
}}
/>
</SectionFlex>
</View>
<View>
<Section>
<FeatureText text="• Border radius." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage
style={styles.imageSquare}
source={{
uri: IMAGE_URL + bust,
}}
/>
<FastImage
style={styles.imageRectangular}
source={{
uri: IMAGE_URL + bust,
}}
/>
</SectionFlex>
</View>
)
const styles = StyleSheet.create({
imageSquare: {
borderRadius: 50,
height: 100,
backgroundColor: '#ddd',
margin: 20,
width: 100,
flex: 0,
},
imageRectangular: {
borderRadius: 50,
borderTopLeftRadius: 10,
borderBottomRightRadius: 10,
height: 100,
backgroundColor: '#ddd',
margin: 20,
flex: 1,
},
plus: {
width: 30,
height: 30,
position: 'absolute',
bottom: 0,
right: 0,
},
imageSquare: {
borderRadius: 50,
height: 100,
backgroundColor: '#ddd',
margin: 20,
width: 100,
flex: 0,
},
imageRectangular: {
borderRadius: 50,
borderTopLeftRadius: 10,
borderBottomRightRadius: 10,
height: 100,
backgroundColor: '#ddd',
margin: 20,
flex: 1,
},
plus: {
width: 30,
height: 30,
position: 'absolute',
bottom: 0,
right: 0,
},
})
export default withCacheBust(BorderRadiusExample)
import React from 'react'
import FeatureText from './FeatureText'
const BulletText = ({ text, children }) => (
<FeatureText text={`• ${text || children} •`} />
)
export default BulletText
......@@ -2,27 +2,27 @@ import React from 'react'
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'
const Button = ({ text, onPress }) => (
<TouchableOpacity onPress={onPress}>
<View style={styles.button}>
<Text style={styles.text}>{text}</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={onPress}>
<View style={styles.button}>
<Text style={styles.text}>{text}</Text>
</View>
</TouchableOpacity>
)
const styles = StyleSheet.create({
button: {
backgroundColor: 'black',
margin: 5,
height: 44,
paddingLeft: 10,
paddingRight: 10,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'center',
},
text: {
color: 'white',
},
button: {
backgroundColor: 'black',
margin: 10,
height: 44,
paddingLeft: 10,
paddingRight: 10,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'center',
},
text: {
color: 'white',
},
})
export default Button
......@@ -7,10 +7,10 @@ import ImageGrid from './ImageGrid'
const DefaultImageGrid = () => <ImageGrid ImageComponent={Image} />
DefaultImageGrid.navigationOptions = {
tabBarLabel: 'Image Grid',
tabBarIcon: props => (
<Icon name="ios-image-outline" focusedName="ios-image" {...props} />
),
tabBarLabel: 'Image Grid',
tabBarIcon: props => (
<Icon name="ios-image" {...props} />
),
}
export default DefaultImageGrid
import React from 'react'
import { ScrollView, StatusBar, StyleSheet, Text, View } from 'react-native'
import Icon from './Icons/Icon'
import Section from './Section'
import PriorityExample from './PriorityExample'
import GifExample from './GifExample'
import BorderRadiusExample from './BorderRadiusExample'
import FeatureText from './FeatureText'
import ProgressExample from './ProgressExample'
import PreloadExample from './PreloadExample'
import ResizeModeExample from './ResizeModeExample'
import LocalImagesExample from './LocalImagesExample'
import StatusBarUnderlay, { STATUS_BAR_HEIGHT } from './StatusBarUnderlay'
import AutoSizeExample from './AutoSizeExample'
const FastImageExample = () => (
<View style={styles.container}>
<StatusBar
translucent
barStyle="dark-content"
backgroundColor="transparent"
/>
<ScrollView
style={styles.scrollContainer}
contentContainerStyle={styles.scrollContentContainer}
>
<View style={styles.contentContainer}>
<Section>
<Text style={styles.titleText}>🚩 FastImage</Text>
<FeatureText text="Tap images to reload examples." />
</Section>
<PriorityExample />
<GifExample />
<BorderRadiusExample />
<ProgressExample />
<PreloadExample />
<ResizeModeExample />
<LocalImagesExample />
<AutoSizeExample />
</View>
</ScrollView>
<StatusBarUnderlay />
</View>
)
FastImageExample.navigationOptions = {
tabBarLabel: 'FastImage Example',
tabBarIcon: props => (
<Icon
name="ios-information-circle"
{...props}
/>
),
}
const styles = StyleSheet.create({
titleText: {
fontWeight: '900',
marginBottom: 20,
color: '#222',
},
contentContainer: {
marginTop: 20,
},
image: {
flex: 1,
height: 100,
backgroundColor: '#ddd',
margin: 10,
},
container: {
flex: 1,
alignItems: 'stretch',
backgroundColor: '#fff',
},
scrollContainer: {
marginTop: STATUS_BAR_HEIGHT,
},
scrollContentContainer: {
alignItems: 'stretch',
flex: 0,
},
})
export default FastImageExample
......@@ -6,10 +6,10 @@ import ImageGrid from './ImageGrid'
const FastImageGrid = () => <ImageGrid ImageComponent={FastImage} />
FastImageGrid.navigationOptions = {
tabBarLabel: 'FastImage Grid',
tabBarIcon: props => (
<Icon name="ios-photos-outline" focusedName="ios-photos" {...props} />
),
tabBarLabel: 'FastImage Grid',
tabBarIcon: props => (
<Icon name="ios-photos" {...props} />
),
}
export default FastImageGrid
import React from 'react'
import { StyleSheet, Text } from 'react-native'
export default ({ text }) => <Text style={styles.style}>{text}</Text>
export default ({ text, style, children }) => (
<Text style={[styles.style, style]}>{text || children}</Text>
)
const styles = StyleSheet.create({
style: {
color: '#222',
},
style: {
color: '#222',
},
})
......@@ -7,27 +7,27 @@ import Section from './Section'
import FeatureText from './FeatureText'
const GIF_URL =
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
const GifExample = ({ onPressReload, bust }) => (
<View>
<Section>
<FeatureText text="• GIF support." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage style={styles.image} source={{ uri: GIF_URL + bust }} />
</SectionFlex>
</View>
<View>
<Section>
<FeatureText text="• GIF support." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage style={styles.image} source={{ uri: GIF_URL + bust }} />
</SectionFlex>
</View>
)
const styles = StyleSheet.create({
image: {
backgroundColor: '#ddd',
margin: 10,
height: 100,
width: 100,
flex: 0,
},
image: {
backgroundColor: '#ddd',
margin: 20,
height: 100,
width: 100,
flex: 0,
},
})
export default withCacheBust(GifExample)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment