Skip to content

Commit

Permalink
Merge pull request #185 from NativeScript/msaravitz/add-allows-editin…
Browse files Browse the repository at this point in the history
…g-ios

feat: allow editing on iOS
  • Loading branch information
DimitarTodorov authored Mar 25, 2019
2 parents 112fcdd + bd261bc commit 63bee12
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 12 deletions.
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@ npm install nativescript-camera --save
| isAvailable() | Is the device camera available to use. |

### CameraOptions
| Property | Default | Description |
| --- | --- | --- |
| width | 0 | Defines the desired width (in device independent pixels) of the taken image. It should be used with height property. If `keepAspectRatio` actual image width could be different in order to keep the aspect ratio of the original camera image. The actual image width will be greater than requested if the display density of the device is higher (than 1) (full HD+ resolutions). |
| height | 0 | Defines the desired height (in device independent pixels) of the taken image. It should be used with width property. If `keepAspectRatio` actual image width could be different in order to keep the aspect ratio of the original camera image. The actual image height will be greater than requested if the display density of the device is higher (than 1) (full HD+ resolutions). |
| keepAspectRatio | true | Defines if camera picture aspect ratio should be kept during picture resizing. This property could affect width or height return values. |
| saveToGallery | true | Defines if camera picture should be copied to photo Gallery (Android) or Photos (iOS) |
| cameraFacing | rear | The initial camera facing. Use 'front' for selfies. |
| Property | Default | Platform | Description |
| --- | --- | --- | --- |
| width | 0 | Both | Defines the desired width (in device independent pixels) of the taken image. It should be used with height property. If `keepAspectRatio` actual image width could be different in order to keep the aspect ratio of the original camera image. The actual image width will be greater than requested if the display density of the device is higher (than 1) (full HD+ resolutions). |
| height | 0 | Both | Defines the desired height (in device independent pixels) of the taken image. It should be used with width property. If `keepAspectRatio` actual image width could be different in order to keep the aspect ratio of the original camera image. The actual image height will be greater than requested if the display density of the device is higher (than 1) (full HD+ resolutions). |
| keepAspectRatio | true | Both | Defines if camera picture aspect ratio should be kept during picture resizing. This property could affect width or height return values. |
| saveToGallery | true | Both | Defines if camera picture should be copied to photo Gallery (Android) or Photos (iOS) |
| allowsEditing | false | iOS | Defines if camera "Retake" or "Use Photo" screen forces the user to crop camera picture to a square and optionally lets them zoom in. |
| cameraFacing | rear | Both | The initial camera facing. Use 'front' for selfies. |


> Note: The `saveToGallery` option might have unexpected behavior on Android! Some vendor camera apps (e.g. LG) will save all captured images to the gallery regardless of what the value of `saveToGallery` is. This behavior cannot be controlled by the camera plugin and if you must exclude the captured image from the photo gallery, you will need to get a local storage read/write permission and write custom code to find the gallery location and delete the new image from there.
Expand Down Expand Up @@ -131,6 +132,7 @@ __Example 2__ shows how to take a picture using the NativeScript camera module.
* __height__: The desired height of the picture (in device independent pixels).
* __keepAspectRatio__: A boolean parameter that indicates if the aspect ratio should be kept.
* __saveToGallery__: A boolean parameter that indicates if the original taken photo will be saved in "Photos" for Android and in "Camera Roll" in iOS
* __allowsEditing__: (iOS Only) A boolean parameter that indicates if the camera "Retake" or "Use Photo" screen forces the user to crop camera picture to a square and optionally lets them zoom in.
* __cameraFacing__: Start with either the "front" or "rear" (default) camera of the device. The current implementation doesn't work on all Android devices, in which case it falls back to the default behavior.

What does `device independent pixels` mean? The NativeScript layout mechanism uses device-independent pixels when measuring UI controls. This allows you to declare one layout and this layout will look similar to all devices (no matter the device's display resolution). In order to get a proper image quality for high resolution devices (like iPhone retina and Android Full HD), camera will return an image with bigger dimensions. For example, if we request an image that is 100x100, on iPhone 6 the actual image will be 200x200 (since its display density factor is 2 -> 100*2x100*2).
Expand Down
4 changes: 4 additions & 0 deletions demo-angular/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
<Label text="saveToGallery"></Label>
<Switch [(ngModel)]="saveToGallery"></Switch>
</StackLayout>
<StackLayout android:visibility="collapsed" orientation="horizontal" padding="10">
<Label text="allowsEditing"></Label>
<Switch [(ngModel)]="allowsEditing"></Switch>
</StackLayout>
<StackLayout orientation="horizontal" padding="10">
<Label text="keepAspectRatio"></Label>
<Switch [(ngModel)]="keepAspectRatio"></Switch>
Expand Down
3 changes: 2 additions & 1 deletion demo-angular/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ImageAsset } from 'tns-core-modules/image-asset';
})
export class AppComponent {
public saveToGallery: boolean = false;
public allowsEditing: boolean = false;
public keepAspectRatio: boolean = true;
public width: number = 320;
public height: number = 240;
Expand All @@ -20,7 +21,7 @@ export class AppComponent {
onTakePictureTap(args) {
requestPermissions().then(
() => {
takePicture({ width: this.width, height: this.height, keepAspectRatio: this.keepAspectRatio, saveToGallery: this.saveToGallery })
takePicture({ width: this.width, height: this.height, keepAspectRatio: this.keepAspectRatio, saveToGallery: this.saveToGallery, allowsEditing: this.allowsEditing })
.then((imageAsset: any) => {
this.cameraImage = imageAsset;
let that = this;
Expand Down
7 changes: 6 additions & 1 deletion demo-vue/app/components/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
<Label text="saveToGallery" />
<Switch v-model="saveToGallery"/>
</StackLayout>
<StackLayout android:visibility="collapsed" orientation="horizontal" row="0" padding="5">
<Label text="allowsEditing" />
<Switch v-model="allowsEditing"/>
</StackLayout>
<StackLayout orientation="horizontal" row="0" padding="5">
<Label text="keepAspectRatio" />
<Switch v-model="keepAspectRatio"/>
Expand Down Expand Up @@ -37,6 +41,7 @@
data() {
return {
saveToGallery: false,
allowsEditing: false,
keepAspectRatio: true,
width: 320,
height: 240,
Expand All @@ -50,7 +55,7 @@
let that = this;
requestPermissions().then(
() => {
takePicture({ width: that.width, height: that.height, keepAspectRatio: that.keepAspectRatio, saveToGallery: that.saveToGallery }).
takePicture({ width: that.width, height: that.height, keepAspectRatio: that.keepAspectRatio, saveToGallery: that.saveToGallery, allowsEditing: that.allowsEditing }).
then((imageAsset) => {
that.cameraImage = imageAsset;
imageAsset.getImageAsync(function (nativeImage) {
Expand Down
4 changes: 3 additions & 1 deletion demo/app/main-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export function navigatingTo(args: EventData) {
page.bindingContext = fromObject({
cameraImage: picturePath,
saveToGallery: false,
allowsEditing: false,
keepAspectRatio: true,
width: 320,
height: 240
Expand All @@ -23,12 +24,13 @@ export function navigatingTo(args: EventData) {
export function onTakePictureTap(args: EventData) {
let page = <Page>(<View>args.object).page;
let saveToGallery = page.bindingContext.get("saveToGallery");
let allowsEditing = page.bindingContext.get("allowsEditing");
let keepAspectRatio = page.bindingContext.get("keepAspectRatio");
let width = page.bindingContext.get("width");
let height = page.bindingContext.get("height");
requestPermissions().then(
() => {
takePicture({ width: width, height: height, keepAspectRatio: keepAspectRatio, saveToGallery: saveToGallery }).
takePicture({ width: width, height: height, keepAspectRatio: keepAspectRatio, saveToGallery: saveToGallery, allowsEditing: allowsEditing }).
then((imageAsset) => {
page.bindingContext.set("cameraImage", imageAsset);
imageAsset.getImageAsync(function (nativeImage) {
Expand Down
4 changes: 4 additions & 0 deletions demo/app/main-page.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
<Label text="saveToGallery" />
<Switch checked="{{ saveToGallery }}"/>
</StackLayout>
<StackLayout android:visibility="collapsed" orientation="horizontal" row="0" padding="5">
<Label text="allowsEditing" />
<Switch checked="{{ allowsEditing }}"/>
</StackLayout>
<StackLayout orientation="horizontal" row="0" padding="5">
<Label text="keepAspectRatio" />
<Switch checked="{{ keepAspectRatio }}"/>
Expand Down
12 changes: 10 additions & 2 deletions src/camera.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class UIImagePickerControllerDelegateImpl extends NSObject implements UIImagePic
private _height: number;
private _keepAspectRatio: boolean;
private _saveToGallery: boolean;
private _allowsEditing: boolean;

public initWithCallback(callback: (result?) => void, errorCallback: (result?) => void): UIImagePickerControllerDelegateImpl {
this._callback = callback;
Expand All @@ -32,6 +33,7 @@ class UIImagePickerControllerDelegateImpl extends NSObject implements UIImagePic
this._width = options.width;
this._height = options.height;
this._saveToGallery = options.saveToGallery;
this._allowsEditing = options.allowsEditing;
this._keepAspectRatio = types.isNullOrUndefined(options.keepAspectRatio) ? true : options.keepAspectRatio;
}
return this;
Expand All @@ -41,6 +43,9 @@ class UIImagePickerControllerDelegateImpl extends NSObject implements UIImagePic
if (info) {
let currentDate: Date = new Date();
let source = info.valueForKey(UIImagePickerControllerOriginalImage);
if (this._allowsEditing) {
source = info.valueForKey(UIImagePickerControllerEditedImage);
}
if (source) {
let imageSource: typeof imageSourceModule = require("image-source");
let imageSourceResult = imageSource.fromNativeSource(source);
Expand Down Expand Up @@ -129,11 +134,13 @@ export let takePicture = function (options): Promise<any> {
let reqHeight = 0;
let keepAspectRatio = true;
let saveToGallery = true;
let allowsEditing = false;
if (options) {
reqWidth = options.width || 0;
reqHeight = options.height || reqWidth;
keepAspectRatio = types.isNullOrUndefined(options.keepAspectRatio) ? keepAspectRatio : options.keepAspectRatio;
saveToGallery = types.isNullOrUndefined(options.saveToGallery) ? saveToGallery : options.saveToGallery;
allowsEditing = types.isNullOrUndefined(options.allowsEditing) ? allowsEditing : options.allowsEditing;
}

let authStatus = PHPhotoLibrary.authorizationStatus();
Expand All @@ -143,10 +150,10 @@ export let takePicture = function (options): Promise<any> {

if (reqWidth && reqHeight) {
listener = UIImagePickerControllerDelegateImpl.new().initWithCallbackAndOptions(
resolve, reject, { width: reqWidth, height: reqHeight, keepAspectRatio: keepAspectRatio, saveToGallery: saveToGallery });
resolve, reject, { width: reqWidth, height: reqHeight, keepAspectRatio: keepAspectRatio, saveToGallery: saveToGallery, allowsEditing: allowsEditing });
} else if (saveToGallery) {
listener = UIImagePickerControllerDelegateImpl.new().initWithCallbackAndOptions(
resolve, reject, { saveToGallery: saveToGallery, keepAspectRatio: keepAspectRatio });
resolve, reject, { saveToGallery: saveToGallery, keepAspectRatio: keepAspectRatio, allowsEditing: allowsEditing });
} else {
listener = UIImagePickerControllerDelegateImpl.new().initWithCallback(resolve, reject);
}
Expand All @@ -162,6 +169,7 @@ export let takePicture = function (options): Promise<any> {
imagePickerController.sourceType = sourceType;
imagePickerController.cameraDevice = options && options.cameraFacing === "front" ?
UIImagePickerControllerCameraDevice.Front : UIImagePickerControllerCameraDevice.Rear;
imagePickerController.allowsEditing = allowsEditing;
}

imagePickerController.modalPresentationStyle = UIModalPresentationStyle.CurrentContext;
Expand Down
6 changes: 6 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ export interface CameraOptions {
*/
saveToGallery?: boolean;

/**
* iOS Only
* Defines if camera "Retake" or "Use Photo" screen forces user to crop camera picture to a square and optionally lets them zoom in.
*/
allowsEditing?: boolean;

/**
* The initial camera. Default "rear".
* The current implementation doesn't work on all Android devices, in which case it falls back to the default behavior.
Expand Down

0 comments on commit 63bee12

Please sign in to comment.