Skip to content

Commit

Permalink
use MWPhotobrowser for iOS (alwx#74)
Browse files Browse the repository at this point in the history
* use MWPhotobrowser to show images in iOS, upgrade react native to v0.44.0 in example project

* add showsVerticalScrollIndicator and showsHorizontalScrollIndicator for iOS, update README

* showsHorizontalScrollIndicator and showsVerticalScrollIndicator

* fix prop types error
  • Loading branch information
greedbell authored and alwx committed Aug 11, 2017
1 parent 72d5e8c commit 9489a51
Show file tree
Hide file tree
Showing 44 changed files with 4,999 additions and 280 deletions.
33 changes: 16 additions & 17 deletions PhotoView.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,21 @@ export default class PhotoView extends Component {
}

if (source && source.uri) {
var {onLoadStart, onLoad, onLoadEnd} = this.props;
var {onLoadStart, onLoad, onLoadEnd, onTap, onViewTap, onScale, ...props} = this.props;

var nativeProps = {
onPhotoViewerLoadStart: this.props.onLoadStart,
onPhotoViewerLoad: this.props.onLoad,
onPhotoViewerLoadEnd: this.props.onLoadEnd,
onPhotoViewerTap: this.props.onTap,
onPhotoViewerViewTap: this.props.onViewTap,
onPhotoViewerScale: this.props.onScale,
...this.props,
onPhotoViewerLoadStart: onLoadStart,
onPhotoViewerLoad: onLoad,
onPhotoViewerLoadEnd: onLoadEnd,
onPhotoViewerTap: onTap,
onPhotoViewerViewTap: onViewTap,
onPhotoViewerScale: onScale,
...props,
shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd),
src: source,
loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null,
};

delete nativeProps.onLoadStart;
delete nativeProps.onLoad;
delete nativeProps.onLoadEnd;
delete nativeProps.onTap;
delete nativeProps.onViewTap;
delete nativeProps.onScale;

return <PhotoViewAndroid {...nativeProps} />
}
return null
Expand All @@ -78,9 +71,15 @@ export default class PhotoView extends Component {

var cfg = {
nativeOnly: {
onPhotoViewerLoadStart: true,
onPhotoViewerLoad: true,
onPhotoViewerLoadEnd: true,
onPhotoViewerTap: true,
onPhotoViewerViewTap: true,
onPhotoViewerScale: true,
shouldNotifyLoadEvents: true,
src: true,
loadingIndicatorSrc: true,
shouldNotifyLoadEvents: true
loadingIndicatorSrc: true
}
};
const PhotoViewAndroid = requireNativeComponent('PhotoViewAndroid', PhotoView, cfg);
96 changes: 74 additions & 22 deletions PhotoView.ios.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,83 @@
import React, {Component} from 'react';
import {
View,
ScrollView,
Image,
TouchableWithoutFeedback
} from 'react-native';
import React, { Component, PropTypes } from 'react';
import { requireNativeComponent, View } from 'react-native';
import ViewPropTypes from 'react-native/Libraries/Components/View/ViewPropTypes';

const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource');

export default class PhotoView extends Component {
static propTypes = {
source: PropTypes.oneOfType([
PropTypes.shape({
uri: PropTypes.string
}),
// Opaque type returned by require('./image.jpg')
PropTypes.number
]),
loadingIndicatorSource: PropTypes.oneOfType([
PropTypes.shape({
uri: PropTypes.string
}),
// Opaque type returned by require('./image.jpg')
PropTypes.number
]),
fadeDuration: PropTypes.number,
minimumZoomScale: PropTypes.number,
maximumZoomScale: PropTypes.number,
scale: PropTypes.number,
onLoadStart: PropTypes.func,
onLoad: PropTypes.func,
onLoadEnd: PropTypes.func,
onTap: PropTypes.func,
onViewTap: PropTypes.func,
onScale: PropTypes.func,
showsHorizontalScrollIndicator: PropTypes.bool,
showsVerticalScrollIndicator: PropTypes.bool,
...ViewPropTypes
};

render() {
return (
<ScrollView
contentContainerStyle={{ alignItems:'center', justifyContent:'center' }}
centerContent={true}
maximumZoomScale={this.props.maximumZoomScale}
minimumZoomScale={this.props.minimumZoomScale}
showsHorizontalScrollIndicator={this.props.showsHorizontalScrollIndicator}
showsVerticalScrollIndicator={this.props.showsVerticalScrollIndicator}
>
const source = resolveAssetSource(this.props.source);
var loadingIndicatorSource = resolveAssetSource(this.props.loadingIndicatorSource);

if (source && source.uri === '') {
console.warn('source.uri should not be an empty string');
}

<TouchableWithoutFeedback
onPress={this.props.onTap ? this.props.onTap : function() {}}>
if (this.props.src) {
console.warn('The <PhotoView> component requires a `source` property rather than `src`.');
}

<Image {...this.props}/>
if (source && source.uri) {
var {onLoadStart, onLoad, onLoadEnd, onTap, onViewTap, onScale, ...props} = this.props;

</TouchableWithoutFeedback>
var nativeProps = {
onPhotoViewerLoadStart: onLoadStart,
onPhotoViewerLoad: onLoad,
onPhotoViewerLoadEnd: onLoadEnd,
onPhotoViewerTap: onTap,
onPhotoViewerViewTap: onViewTap,
onPhotoViewerScale: onScale,
...props,
src: source,
loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null,
};

</ScrollView>
);
return <RNPhotoView {...nativeProps} />
}
return null
}
}

var cfg = {
nativeOnly: {
onPhotoViewerLoadStart: true,
onPhotoViewerLoad: true,
onPhotoViewerLoadEnd: true,
onPhotoViewerTap: true,
onPhotoViewerViewTap: true,
onPhotoViewerScale: true,
src: true,
loadingIndicatorSrc: true
}
};
const RNPhotoView = requireNativeComponent('RNPhotoView', PhotoView, cfg);
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
Provides custom Image view for React Native that allows to perform
pinch-to-zoom on images. Works on both iOS and Android.

This component uses [PhotoDraweeView](https://github.com/ongakuer/PhotoDraweeView) for Android and native
Scroll + Image approach on iOS.
This component uses [PhotoDraweeView](https://github.com/ongakuer/PhotoDraweeView) for Android and [MWPhotobrowser](https://github.com/mwaterfall/MWPhotoBrowser) on iOS.

## Usage

Expand Down Expand Up @@ -41,8 +40,8 @@ androidZoomTransitionDuration | int | **Android only**: Double-tap zoom transiti
| onLoad | func | Callback function |
| onLoadEnd | func | Callback function |
| onTap | func | Callback function (called on image tap) |
| onViewTap | func | Callback function (called on tap outside of image). Currently **Android only** (will be available for iOS later) |
| onScale | func | Callback function. Currently **Android only** (will be available for iOS later) |
| onViewTap | func | Callback function (called on tap outside of image) |
| onScale | func | Callback function |

## Compared to [react-native-image-zoom](https://github.com/Anthonyzou/react-native-image-zoom)

Expand Down
3 changes: 3 additions & 0 deletions example/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["react-native"]
}
32 changes: 19 additions & 13 deletions example/.flowconfig
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
[ignore]
; We fork some components by platform
.*/*[.]android.js

# We fork some components by platform.
.*/*.android.js
; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/

# Ignore templates with `@flow` in header
.*/local-cli/generator.*
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*

# Ignore malformed json
.*/node_modules/y18n/test/.*\.json
; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
.*/Libraries/react-native/ReactNative.js

[include]

Expand All @@ -17,25 +22,26 @@ node_modules/react-native/flow
flow/

[options]
module.system=haste
emoji=true

esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
module.system=haste

experimental.strict_type_args=true

munge_underscores=true

module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'

suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe

suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-7]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-7]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-2]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-2]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError

unsafe.enable_getters_and_setters=true

[version]
^0.27.0
^0.42.0
1 change: 1 addition & 0 deletions example/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pbxproj -text
20 changes: 16 additions & 4 deletions example/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,32 @@ DerivedData
*.xcuserstate
project.xcworkspace

# Android/IJ
# Android/IntelliJ
#
*.iml
build/
.idea
.gradle
local.properties
*.iml

# node.js
#
node_modules/
npm-debug.log
yarn-error.log

# BUCK
buck-out/
\.buckd/
android/app/libs
android/keystores/debug.keystore
*.keystore

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
55 changes: 27 additions & 28 deletions example/android/app/BUCK
Original file line number Diff line number Diff line change
@@ -1,66 +1,65 @@
import re

# To learn about Buck see [Docs](https://buckbuild.com/).
# To run your application with Buck:
# - install Buck
# - `npm start` - to start the packager
# - `cd android`
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US`
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
# - `buck install -r android/app` - compile, install and run application
#

lib_deps = []

for jarfile in glob(['libs/*.jar']):
name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile)
name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')]
lib_deps.append(':' + name)
prebuilt_jar(
name = name,
binary_jar = jarfile,
)

for aarfile in glob(['libs/*.aar']):
name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile)
name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')]
lib_deps.append(':' + name)
android_prebuilt_aar(
name = name,
aar = aarfile,
)

android_library(
name = 'all-libs',
exported_deps = lib_deps
name = "all-libs",
exported_deps = lib_deps,
)

android_library(
name = 'app-code',
srcs = glob([
'src/main/java/**/*.java',
]),
deps = [
':all-libs',
':build_config',
':res',
],
name = "app-code",
srcs = glob([
"src/main/java/**/*.java",
]),
deps = [
":all-libs",
":build_config",
":res",
],
)

android_build_config(
name = 'build_config',
package = 'com.example',
name = "build_config",
package = "com.example",
)

android_resource(
name = 'res',
res = 'src/main/res',
package = 'com.example',
name = "res",
package = "com.example",
res = "src/main/res",
)

android_binary(
name = 'app',
package_type = 'debug',
manifest = 'src/main/AndroidManifest.xml',
keystore = '//android/keystores:debug',
deps = [
':app-code',
],
name = "app",
keystore = "//android/keystores:debug",
manifest = "src/main/AndroidManifest.xml",
package_type = "debug",
deps = [
":app-code",
],
)
Loading

0 comments on commit 9489a51

Please sign in to comment.