Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
env:
global:
- ANDROID_PACKAGE='imagepickerdemo-debug.apk'
- ANDROID_PACKAGE_FOLDER=$TRAVIS_BUILD_DIR/demo/platforms/android/app/build/outputs/apk
- ANDROID_PACKAGE='app-debug.apk'
- ANDROID_PACKAGE_FOLDER=$TRAVIS_BUILD_DIR/demo/platforms/android/app/build/outputs/apk/debug
- ANDROID_SAUCE_STORAGE="https://saucelabs.com/rest/v1/storage/$SAUCE_USER/$ANDROID_PACKAGE?overwrite=true"
- IOS_PACKAGE='imagepickerdemo.zip'
- IOS_PACKAGE_FOLDER=$TRAVIS_BUILD_DIR/demo/platforms/ios/build/emulator
Expand Down Expand Up @@ -78,7 +78,7 @@ android:
components:
- tools
- platform-tools
- build-tools-26.0.1
- build-tools-26.0.2
- android-26
- android-23
- extra-android-m2repository
Expand Down
39 changes: 14 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
[![Build Status](https://travis-ci.org/NativeScript/nativescript-imagepicker.svg?branch=master)](https://travis-ci.org/NativeScript/nativescript-imagepicker)

Imagepicker plugin supporting both single and multiple selection.
<br />Plugin supports **iOS8+** and uses [Photos Framework](https://developer.apple.com/library/prerelease/ios//documentation/Photos/Reference/Photos_Framework/index.html).
<br />Plugin supports **iOS8+** and uses [QBImagePicker](https://github.com/questbeat/QBImagePicker) cocoa pod.
<br />For **Android** it uses Intents to open the stock images or file pickers. For Android 6 (API 23) and above the permissions to read file storage should be explicitly required. See demo for implementation details.

<!-- TOC depthFrom:2 -->

- [Installation](#installation)
- [Configuration](#configuration)
- [Migrating from 5.x.x to 6.x.x](#migrating-from-5xx-to-6xx)
- [Migrating from 4.x.x to 5.x.x](#migrating-from-4xx-to-5xx)
- [Migrating from 3.x.x to 4.x.x](#migrating-from-3xx-to-4xx)
- [Usage](#usage)
Expand Down Expand Up @@ -41,6 +42,9 @@ tns run
## Configuration
No additional configuration required!

## Migrating from 5.x.x to 6.x.x
With version **6.x.x** the dependency to the `nativescript-ui-listview` plugin is removed and for iOS the [QBImagePicker](https://github.com/questbeat/QBImagePicker) cocoa pod is used. Now the plugin supports some new features, fixes some bugs and looks super native for iOS. You can remove any dependencies to `nativescript-pro-ui`, `nativescript-ui-listview`, etc. in case you've added them in your app specifically for this plugin. Also the options **doneText**, **cancelText**, **albumsText**, **newestFirst** and the methods **cancel()** and **done()** are no longer applicable. The image picker now returns the basic [{N} ImageAsset class](https://github.com/NativeScript/NativeScript/tree/master/tns-core-modules/image-asset) (and not custom asset as before).

## Migrating from 4.x.x to 5.x.x
With version **5.x.x** major update to the plugin there is a related dependency which needs to be updated inside your project. The plugin uses internally the `nativescript-ui-listview` plugin (part of the NativeScript Pro UI components). Recently the monolithic [NativeScript Pro UI plugin was split in multiple plugins](https://www.nativescript.org/blog/professional-components-from-nativescript-ui-the-big-breakup), each of them representing a single component. Now, instead of the monolithic package, nativescript-imagepicker uses only the component it needs. To use version 5.x.x of the plugin, you need to update any dependencies to `nativescript-pro-ui` in your project with the single component alternatives as described in the [migration guide](http://docs.telerik.com/devtools/nativescript-ui/migration).

Expand Down Expand Up @@ -116,33 +120,18 @@ context
| Option | Platform | Default | Description |
| --- | --- | --- | --- |
| mode | both | multiple | The mode if the imagepicker. Possible values are `single` for single selection and `multiple` for multiple selection. |
| doneText | iOS | Done | The text of the "Done" button on top right. |
| cancelText | iOS | Cancel | The text of the "Cancel" button on top left. |
| albumsText | iOS | Albums | The title of the "Albums" screen from where the selection of album and images can be done. |
| newestFirst | iOS | false | Set to `true` to sort the images in an album by newest first. |
| minimumNumberOfSelection | iOS | 0 | The minumum number of selected assets. |
| maximumNumberOfSelection | iOS | 0 | The maximum number of selected assets. |
| showsNumberOfSelectedAssets | iOS | True | Display the number of selected assets. |
| prompt | iOS | undefined | Display prompt text when selecting assets. |
| numberOfColumnsInPortrait | iOS | 4 | Set the number of columns in Portrait orientation. |
| numberOfColumnsInLandscape | iOS | 7 | Set the number of columns in Landscape orientation. |
| mediaType | iOS | Any | Choose whether to pick Image/Video/Any type of assets. |

The **hostView** parameter can be set to the view that hosts the image picker. Applicable in iOS only, intended to be used when open picker from a modal page.

* authorize() - request the required permissions.
* present() - show the albums to present the user the ability to select images. Returns an array of the selected images.
* cancel() - cancel selection. iOS only.
* done() - confirm the selection is ready. iOS only.


### Properties
| Property | Default | Description |
| --- | --- | --- |
| selection | null | An array of selected image assets. |
| albums | null | Albums from where the images are picked. |


### Image properties

Once image is picked some options can be applied to it before it is used:

| Option | Default | Description |
| --- | --- | --- |
| maxWidth | null | Image max width |
| maxHeight | null | Image max height |
| aspectRatio | fit | iOS only. Possible values are `fit` and `fill`. [Read more](https://developer.apple.com/documentation/photos/phimagecontentmode) |

## Contribute
We love PRs! Check out the [contributing guidelines](CONTRIBUTING.md). If you want to contribute, but you are not sure where to start - look for [issues labeled `help wanted`](https://github.com/NativeScript/nativescript-imagepicker/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22).
Expand Down
20 changes: 12 additions & 8 deletions demo-angular/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@
</ActionBar>

<GridLayout rows="*, auto, auto">
<ScrollView>
<StackLayout>
<GridLayout height="94" columns="94, *" rows="*, *" *ngFor="let item of items">
<Image rowSpan="2" width="94" height="94" [src]="item"></Image>
<Label col="1" [text]="item.uri"></Label>
<Label col="1" row="1" [text]="item.fileUri"></Label>
<ListView [items]="imageAssets">
<ng-template let-image="item" let-i="index">
<GridLayout columns="auto, *">
<Image
[width]="thumbSize"
[height]="thumbSize"
[src]="image" stretch="fill"></Image>
<Label col="1" [text]="'image ' + i"></Label>
</GridLayout>
</StackLayout>
</ScrollView>
</ng-template>
</ListView>

<Image [src]="imageSrc" *ngIf="isSingleMode" [width]="previewSize" [height]="previewSize" stretch="aspectFit"></Image>
<Button row="1" text="Pick Single" (tap)="onSelectSingleTap()" horizontalAlignment="center"></Button>
<Button row="2" text="Pick Multiple" (tap)="onSelectMultipleTap()" horizontalAlignment="center"></Button>
</GridLayout>
43 changes: 24 additions & 19 deletions demo-angular/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,56 @@
import { Component, ChangeDetectorRef } from "@angular/core";
import { ListView } from "tns-core-modules/ui/list-view";
import { isAndroid } from "tns-core-modules/platform";
import { Component } from "@angular/core";
import * as imagepicker from "nativescript-imagepicker";

@Component({
selector: "my-app",
templateUrl: "app.component.html",
})
export class AppComponent {
imageAssets = [];
imageSrc: any;
isSingleMode: boolean = true;
thumbSize: number = 80;
previewSize: number = 300;

items = [];
public onSelectMultipleTap() {
this.isSingleMode = false;

constructor(private _changeDetectionRef: ChangeDetectorRef) {
}

onSelectMultipleTap() {
let context = imagepicker.create({
mode: "multiple"
});
this.startSelection(context);
}

onSelectSingleTap() {
public onSelectSingleTap() {
this.isSingleMode = true;

let context = imagepicker.create({
mode: "single"
});
this.startSelection(context);
}

startSelection(context) {
let _that = this;
private startSelection(context) {
let that = this;

context
.authorize()
.then(() => {
_that.items = [];
that.imageAssets = [];
that.imageSrc = null;
return context.present();
})
.then((selection) => {
console.log("Selection done:");
selection.forEach(function (selected) {
console.log("----------------");
console.log("uri: " + selected.uri);
console.log("fileUri: " + selected.fileUri);
console.log("Selection done: " + JSON.stringify(selection));
that.imageSrc = that.isSingleMode && selection.length > 0 ? selection[0] : null;

// set the images to be loaded from the assets with optimal sizes (optimize memory usage)
selection.forEach(function (element) {
element.options.width = that.isSingleMode ? that.previewSize : that.thumbSize;
element.options.height = that.isSingleMode ? that.previewSize : that.thumbSize;
});
_that.items = selection;
_that._changeDetectionRef.detectChanges();

that.imageAssets = selection;
}).catch(function (e) {
console.log(e);
});
Expand Down
2 changes: 1 addition & 1 deletion demo-angular/app/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { platformNativeScriptDynamic } from "nativescript-angular/platform";
import { AppModule } from "./app.module";

platformNativeScriptDynamic().bootstrapModule(AppModule);
platformNativeScriptDynamic({ createFrameOnBootstrap: true }).bootstrapModule(AppModule);
11 changes: 6 additions & 5 deletions demo-angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"nativescript": {
"id": "org.nativescript.imagepickerdemoangular",
"tns-ios": {
"version": "3.4.0"
"version": "4.0.1"
},
"tns-android": {
"version": "3.4.0"
"version": "4.0.0"
}
},
"dependencies": {
Expand All @@ -23,7 +23,7 @@
"nativescript-unit-test-runner": "^0.3.4",
"reflect-metadata": "~0.1.8",
"rxjs": "^5.5.0",
"tns-core-modules": "^3.4.0"
"tns-core-modules": "^4.0.0"
},
"devDependencies": {
"@angular/compiler-cli": "~5.0.0",
Expand All @@ -42,7 +42,7 @@
"lazy": "1.0.11",
"nativescript-css-loader": "~0.26.0",
"nativescript-dev-typescript": "^0.6.0",
"nativescript-dev-webpack": "^0.9.0",
"nativescript-dev-webpack": "^0.10.1",
"nativescript-worker-loader": "~0.8.1",
"raw-loader": "~0.5.1",
"resolve-url-loader": "~2.1.0",
Expand All @@ -52,7 +52,8 @@
"webpack": "~3.8.1",
"webpack-bundle-analyzer": "^2.8.2",
"webpack-sources": "~1.0.1",
"zone.js": "^0.8.4"
"zone.js": "^0.8.4",
"uglifyjs-webpack-plugin": "~1.1.6"
},
"scripts": {
"build.plugin": "cd ../src && npm run build",
Expand Down
48 changes: 4 additions & 44 deletions demo/app/main-page.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,10 @@
import { EventData } from 'tns-core-modules/data/observable';
import { Page } from 'tns-core-modules/ui/page';
import { isAndroid } from "tns-core-modules/platform";
import * as imagepicker from "nativescript-imagepicker";
import { MainViewModel } from './main-view-model';

let list;
let imageSrc;

export function pageLoaded(args: EventData) {
export function onNavigatingTo(args: EventData) {
let viewModel = new MainViewModel();
let page = <Page>args.object;
list = page.getViewById("urls-list");
imageSrc = page.getViewById("imageSrc");
}

export function onSelectMultipleTap(args) {
let context = imagepicker.create({ mode: "multiple" });
startSelection(context, false);
}

export function onSelectSingleTap(args) {
let context = imagepicker.create({ mode: "single" });
startSelection(context, true);
}

function startSelection(context, isSingle) {
context
.authorize()
.then(function() {
list.items = [];
return context.present();
})
.then(function(selection) {
console.log("Selection done:");
selection.forEach(function(selected) {
console.log("----------------");
console.log("uri: " + selected.uri);
if (isSingle) {
selected.getImage({ maxWidth: 200, maxHeight: 200, aspectRatio: 'fill' })
.then((imageSource) => {
imageSrc.src = imageSource;
});
} else {
imageSrc.visibility = 'hidden';
}
});
list.items = selection;
}).catch(function (e) {
console.log(e);
});
page.bindingContext = viewModel;
}
18 changes: 8 additions & 10 deletions demo/app/main-page.xml
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
<Page xmlns="http://www.nativescript.org/tns.xsd" loaded="pageLoaded">
<Page xmlns="http://www.nativescript.org/tns.xsd" navigatingTo="onNavigatingTo">
<Page.actionBar>
<ActionBar title="Image Picker" />
</Page.actionBar>
<GridLayout rows="*, auto, auto">
<ListView id="urls-list">
<ListView itemLoading="{{ onItemLoading }}" items="{{ imageAssets }}">
<ListView.itemTemplate>
<GridLayout columns="94, *" rows="*, *">
<Image rowSpan="2" width="80" height="80" src="{{ $value }}" />
<Label col="1" text="{{ uri }}" />
<Label col="1" row="1" text="{{ fileUri }}" />
<GridLayout columns="auto, *">
<Image width="{{ $parents['ListView'].thumbSize }}" height="{{ $parents['ListView'].thumbSize }}" src="{{ $value }}" stretch="fill" />
<Label class="m-10" id="imageLabel" col="1" />
</GridLayout>
</ListView.itemTemplate>
</ListView>

<Image id="imageSrc" width="200" height="200" />
<Button row="1" text="Pick Single" tap="onSelectSingleTap" horizontalAlignment="center" />
<Button row="2" text="Pick Multiple" tap="onSelectMultipleTap" horizontalAlignment="center" />
<Image src="{{ imageSrc }}" visibility="{{ isSingleMode ? 'visible' : 'collapsed' }}" width="{{ previewSize }}" height="{{ previewSize }}" stretch="aspectFit" />
<Button row="1" text="Pick Single" tap="{{ onSelectSingleTap }}" horizontalAlignment="center" />
<Button row="2" text="Pick Multiple" tap="{{ onSelectMultipleTap }}" horizontalAlignment="center" />
</GridLayout>
</Page>
Loading