From 19029eb6a297f4ce591b59f806d9a78d54577f42 Mon Sep 17 00:00:00 2001 From: Davaadorj Date: Thu, 24 May 2018 15:06:28 +0900 Subject: [PATCH] - Additional options added for iOS - Fix share issue with SDK version 24 or above on Android --- README.md | 19 +++- package.json | 4 +- plugin.xml | 2 +- src/android/PhotoActivity.java | 32 ++++--- src/android/PhotoViewer.java | 14 ++- src/ios/PhotoViewer.m | 170 ++++++++++++++++++++++++--------- www/PhotoViewer.js | 19 +++- 7 files changed, 191 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 004fc91..c2d062f 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,23 @@ $ npm install --save @ionic-native/photo-viewer PhotoViewer.show('http://my_site.com/my_image.jpg', 'Optional Title'); ``` -Optionally you can pass third parameter which can be used to hide the share button [ONLY FOR ANDROID] +Optionally you can pass third parameter option as object. + +Options: +* share: Option is used to hide and show the share option. +* closeBtn: Option for close button visibility when share false [ONLY FOR iOS] +* copyToReference: If you need to copy image to reference before show then set it true [ONLY FOR iOS] ##### Usage ``` -PhotoViewer.show('http://my_site.com/my_image.jpg', 'Optional Title', {share:false}); +var options = { + share: true, // default is false + closeButton: false, // default is true + copyToReference: true // default is false +}; + +PhotoViewer.show('http://my_site.com/my_image.jpg', 'Optional Title', options); ``` ### Versions @@ -71,3 +82,7 @@ PhotoViewer.show('http://my_site.com/my_image.jpg', 'Optional Title', {share:fal (1.1.9/10) - Fix how image is shown on Android + +(1.1.17) +- Additional options added for iOS +- Fix share issue with SDK version 24 or above on Android diff --git a/package.json b/package.json index ad2178f..6be020c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com-sarriaroman-photoviewer", - "version": "1.1.16", + "version": "1.1.17", "description": "This plugin is intended to show a picture from an URL into a Photo Viewer with zoom features.", "cordova": { "id": "com-sarriaroman-photoviewer", @@ -22,4 +22,4 @@ ], "author": "Román A. Sarria", "license": "MIT" -} \ No newline at end of file +} diff --git a/plugin.xml b/plugin.xml index 14f4763..c272dfc 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + PhotoViewer This plugin is intended to show a picture from an URL into a Photo Viewer with zoom features. diff --git a/src/android/PhotoActivity.java b/src/android/PhotoActivity.java index af45c14..68c1eb6 100644 --- a/src/android/PhotoActivity.java +++ b/src/android/PhotoActivity.java @@ -1,21 +1,20 @@ package com.sarriaroman.PhotoViewer; -import uk.co.senab.photoview.PhotoViewAttacher; - import android.app.Activity; +import android.content.Intent; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.os.StrictMode; import android.util.Base64; import android.view.View; import android.widget.ImageButton; import android.widget.ImageView; - -import android.content.Intent; -import android.net.Uri; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; @@ -24,11 +23,13 @@ import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.reflect.Method; + +import uk.co.senab.photoview.PhotoViewAttacher; public class PhotoActivity extends Activity { private PhotoViewAttacher mAttacher; @@ -43,7 +44,7 @@ public class PhotoActivity extends Activity { private String mImage; private String mTitle; - private JSONObject mOptions; + private boolean mShare; private File mTempImage; private int shareBtnVisibility; @@ -61,13 +62,13 @@ protected void onCreate(Bundle savedInstanceState) { try { this.mImage = mArgs.getString(0); this.mTitle = mArgs.getString(1); - this.mOptions = mArgs.getJSONObject(2); + this.mShare = mArgs.getBoolean(2); //Set the share button visibility - shareBtnVisibility = mOptions.getBoolean("share") ? View.VISIBLE : View.INVISIBLE; + shareBtnVisibility = this.mShare ? View.VISIBLE : View.INVISIBLE; } catch (JSONException exception) { - shareBtnVisibility = View.VISIBLE; + shareBtnVisibility = View.INVISIBLE; } shareBtn.setVisibility(shareBtnVisibility); //Change the activity title @@ -88,8 +89,17 @@ public void onClick(View v) { shareBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + if (Build.VERSION.SDK_INT >= 24) { + try { + Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure"); + m.invoke(null); + } catch (Exception e) { + e.printStackTrace(); + } + } + Uri imageUri; - if (mTempImage == null){ + if (mTempImage == null) { mTempImage = getLocalBitmapFileFromView(photo); } diff --git a/src/android/PhotoViewer.java b/src/android/PhotoViewer.java index 10281ef..9f7359a 100644 --- a/src/android/PhotoViewer.java +++ b/src/android/PhotoViewer.java @@ -1,16 +1,15 @@ package com.sarriaroman.PhotoViewer; -import org.apache.cordova.CordovaPlugin; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; + import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaPlugin; import org.apache.cordova.PluginResult; import org.json.JSONArray; -import org.json.JSONObject; import org.json.JSONException; -import android.Manifest; -import android.content.Intent; -import android.content.pm.PackageManager; - /** * Class to Open PhotoViewer with the Required Parameters from Cordova *

@@ -37,8 +36,7 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo boolean requiresExternalPermission = true; try { - JSONObject options = this.args.optJSONObject(2); - requiresExternalPermission = options.getBoolean("share"); + requiresExternalPermission = this.args.getBoolean(2); } catch (JSONException exception) { } diff --git a/src/ios/PhotoViewer.m b/src/ios/PhotoViewer.m index 9339f44..712b9b5 100644 --- a/src/ios/PhotoViewer.m +++ b/src/ios/PhotoViewer.m @@ -5,9 +5,13 @@ #import #import -@interface PhotoViewer : CDVPlugin { - // Member variables go here. - Boolean run; +@interface PhotoViewer : CDVPlugin { + // Member variables go here. + Boolean isOpen; + UIScrollView *fullView; + UIButton *closeBtn; + BOOL showCloseBtn; + BOOL copyToReference; } @property (nonatomic, strong) UIDocumentInteractionController *docInteractionController; @@ -16,6 +20,9 @@ @interface PhotoViewer : CDVPlugin { - (void)show:(CDVInvokedUrlCommand*)command; @end + + + @implementation PhotoViewer - (void)setupDocumentControllerWithURL:(NSURL *)url andTitle:(NSString *)title @@ -40,45 +47,58 @@ - (UIDocumentInteractionController *) setupControllerWithURL: (NSURL*) fileURL } - (UIViewController *) documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *) controller { - run = false; + isOpen = false; return self.viewController; } - (void)show:(CDVInvokedUrlCommand*)command { - if (run == false) { - run = true; + if (isOpen == false) { + isOpen = true; UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:self.viewController.view.frame]; [activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge]; [activityIndicator.layer setBackgroundColor:[[UIColor colorWithWhite:0.0 alpha:0.30] CGColor]]; CGPoint center = self.viewController.view.center; activityIndicator.center = center; [self.viewController.view addSubview:activityIndicator]; - + [activityIndicator startAnimating]; - - + + CDVPluginResult* pluginResult = nil; NSString* url = [command.arguments objectAtIndex:0]; NSString* title = [command.arguments objectAtIndex:1]; + BOOL isShareEnabled = [[command.arguments objectAtIndex:2] boolValue]; + showCloseBtn = [[command.arguments objectAtIndex:3] boolValue]; + copyToReference = [[command.arguments objectAtIndex:4] boolValue]; if (url != nil && [url length] > 0) { [self.commandDelegate runInBackground:^{ - self.documentURLs = [NSMutableArray array]; + if(isShareEnabled) { + self.documentURLs = [NSMutableArray array]; + } NSURL *URL = [self localFileURLForImage:url]; if (URL) { - [self.documentURLs addObject:URL]; - [self setupDocumentControllerWithURL:URL andTitle:title]; - double delayInSeconds = 0.1; - dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); - dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ - [activityIndicator stopAnimating]; - [self.docInteractionController presentPreviewAnimated:YES]; - //[self.docInteractionController presentPreviewAnimated:NO]; - - }); + if(isShareEnabled){ + [self.documentURLs addObject:URL]; + [self setupDocumentControllerWithURL:URL andTitle:title]; + double delayInSeconds = 0.1; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + [activityIndicator stopAnimating]; + [self.docInteractionController presentPreviewAnimated:YES]; + //[self.docInteractionController presentPreviewAnimated:NO]; + + }); + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + [self showFullScreen:URL andTitle:title]; + [activityIndicator stopAnimating]; + }); + } + } }]; pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; @@ -92,34 +112,21 @@ - (void)show:(CDVInvokedUrlCommand*)command - (NSURL *)localFileURLForImage:(NSString *)image { - // save this image to a temp folder - NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES]; - NSString *filename = [[NSUUID UUID] UUIDString]; - - - - NSString* webStringURL = [image stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + NSString* webStringURL = [image stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]; NSURL* fileURL = [NSURL URLWithString:webStringURL]; - - - //NSURL *fileURL = [NSURL URLWithString:webStringURL]; - - - if ([fileURL isFileReferenceURL]) { - return fileURL; - } - - NSData *data = [NSData dataWithContentsOfURL:fileURL]; - if( data ) { - fileURL = [[tmpDirURL URLByAppendingPathComponent:filename] URLByAppendingPathExtension:[self contentTypeForImageData:data]]; + if (copyToReference && ![fileURL isFileReferenceURL]) { + NSData *data = [NSData dataWithContentsOfURL:fileURL]; + if( data ) { + // save this image to a temp folder + NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES]; + NSString *filename = [[NSUUID UUID] UUIDString]; + fileURL = [[tmpDirURL URLByAppendingPathComponent:filename] URLByAppendingPathExtension:[self contentTypeForImageData:data]]; - [[NSFileManager defaultManager] createFileAtPath:[fileURL path] contents:data attributes:nil]; - - return fileURL; - } else { - return nil; + [[NSFileManager defaultManager] createFileAtPath:[fileURL path] contents:data attributes:nil]; + } } + return fileURL; } - (NSString *)contentTypeForImageData:(NSData *)data { @@ -142,4 +149,79 @@ - (NSString *)contentTypeForImageData:(NSData *)data { return nil; } + +-(UIView *) viewForZoomingInScrollView:(UIScrollView *)inScroll { + NSArray *subviews = [inScroll subviews]; + return subviews[0]; +} + +//This will create a temporary image view and animate it to fullscreen +- (void)showFullScreen:(NSURL *)url andTitle:(NSString *)title { + + CGFloat viewWidth = self.viewController.view.bounds.size.width; + CGFloat viewHeight = self.viewController.view.bounds.size.height; + + //fullView is gloabal, So we can acess any time to remove it + fullView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, viewWidth, viewHeight)]; + [fullView setBackgroundColor:[UIColor blackColor]]; + + // For supporting zoom, + fullView.minimumZoomScale = 1.0; + fullView.maximumZoomScale = 3.0; + fullView.clipsToBounds = YES; + fullView.delegate = self; + + UIImageView *imageView = [[UIImageView alloc]init]; + [imageView setContentMode:UIViewContentModeScaleAspectFit]; + UIImage *image = [UIImage imageWithContentsOfFile:url.path]; + [imageView setBackgroundColor:[UIColor clearColor]]; + imageView.image = image; + imageView.contentMode = UIViewContentModeScaleAspectFit; + + [imageView setFrame:CGRectMake(0, 0, self.viewController.view.bounds.size.width, self.viewController.view.bounds.size.height)]; + + [fullView addSubview:imageView]; + fullView.contentSize = imageView.frame.size; + + [self.viewController.view addSubview:fullView]; + + if(showCloseBtn) { + closeBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + [closeBtn setTitle:@"✕" forState:UIControlStateNormal]; + closeBtn.titleLabel.font = [UIFont systemFontOfSize: 20]; + [closeBtn setTitleColor:[UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:0.6] forState:UIControlStateNormal]; + closeBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight; + [closeBtn setFrame:CGRectMake(viewWidth - 45, 20, 40, 40)]; + [closeBtn setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0]]; + [closeBtn addTarget:self action:@selector(closeButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; + [self.viewController.view addSubview:closeBtn]; + } else { + UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(fullimagetapped:)]; + singleTap.numberOfTapsRequired = 1; + singleTap.numberOfTouchesRequired = 1; + [fullView addGestureRecognizer:singleTap]; + [fullView setUserInteractionEnabled:YES]; + } +} + +- (void)fullimagetapped:(UIGestureRecognizer *)gestureRecognizer { + [self closeImage]; +} + +- (void)closeButtonPressed:(UIButton *)button { + [closeBtn removeFromSuperview]; + closeBtn = nil; + [self closeImage]; +} + +- (void)closeImage { + isOpen = false; + [fullView removeFromSuperview]; + fullView = nil; +} + +-(BOOL)prefersStatusBarHidden { + return YES; +} + @end diff --git a/www/PhotoViewer.js b/www/PhotoViewer.js index f391442..c7f2dac 100644 --- a/www/PhotoViewer.js +++ b/www/PhotoViewer.js @@ -1,3 +1,4 @@ +cordova.define("com-sarriaroman-photoviewer.PhotoViewer", function(require, exports, module) { var exec = require('cordova/exec'); exports.show = function(url, title, options) { @@ -9,5 +10,21 @@ exports.show = function(url, title, options) { options = {}; } - exec(function(){}, function(){}, "PhotoViewer", "show", [url, title, options]); + if(options.share === undefined) { + options.share = false; + } + + if(options.closeButton === undefined) { + options.closeButton = true; + } + + if(options.copyToReference === undefined) { + options.copyToReference = false; + } + + var args = [url, title, options.share, options.closeButton, options.copyToReference]; + + exec(function(){}, function(){}, "PhotoViewer", "show", args); }; + +});