Created
March 8, 2019 18:56
-
-
Save komendantaa/db2a2cebdf14b1d5e8babe259941e537 to your computer and use it in GitHub Desktop.
ionic-imageSourcePopup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { ActionSheetController, normalizeURL, Platform } from 'ionic-angular'; | |
import { File, FileEntry, IFile } from '@ionic-native/file'; | |
import { Crop } from '@ionic-native/crop'; | |
import { Camera, CameraOptions } from '@ionic-native/camera'; | |
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; | |
import { IOSFilePicker } from '@ionic-native/file-picker'; | |
export interface ImageData { | |
imagePath: string; | |
blob: Blob; | |
} | |
export interface FileData { | |
fileName: string; | |
blob: Blob; | |
} | |
@Injectable() | |
export class FileTransferProvider { | |
private _imageSubject: BehaviorSubject<ImageData>; | |
private _imageData: ImageData = { | |
imagePath: null, | |
blob: null, | |
}; | |
private _fileSubject: BehaviorSubject<FileData>; | |
private _fileData: FileData = { | |
fileName: null, | |
blob: null, | |
}; | |
constructor( | |
private actionSheet: ActionSheetController, | |
private camera: Camera, | |
private crop: Crop, | |
private file: File, | |
private platform: Platform, | |
private filePicker: IOSFilePicker | |
) {} | |
/** | |
* @description | |
* Works only for Android, Desktops and iphone 6 and more !!! | |
* | |
* upload via input type="file" | |
* | |
* @usage | |
* ```html | |
* | |
* <input type="file" (change)="uploadFileProvider.onFileSelected($event, formGroup.get('resumeFileName'))" | |
* accept="application/pdf"> | |
* ``` | |
* | |
* @param {event} e | |
*/ | |
onFileSelected(e): BehaviorSubject<FileData> { | |
this._fileSubject = new BehaviorSubject<FileData>(null); | |
if (e.target.files && e.target.files.length > 0) { | |
let file = e.target.files[0]; | |
// set file data | |
this._fileData.blob = file; | |
this._fileData.fileName = file.name; | |
// pass data | |
this._fileSubject.next(this._fileData); | |
} | |
return this._fileSubject; | |
} | |
//TODO file validaors! | |
/** | |
* @description | |
* Workaround for iphone 5 - give ability to browse clouds | |
* | |
* @returns {BehaviorSubject<FileData>} | |
*/ | |
initFileUpload(): BehaviorSubject<FileData> { | |
this.getFromIosClouds(); | |
this._fileSubject = new BehaviorSubject<FileData>(null); | |
return this._fileSubject; | |
} | |
private getFromIosClouds() { | |
this.filePicker | |
.pickFile() | |
.then(uri => { | |
console.log('uri', uri); | |
this.file | |
.resolveLocalFilesystemUrl('file:///' + uri) | |
.then(entry => (<FileEntry>entry).file(file => this.readFileIOS(file))) | |
.catch(err => console.error(' resolveFileSystem ERROR: ', JSON.stringify(err))); | |
}) | |
.catch(err => console.error('pickFile ERROR: ', JSON.stringify(err))); | |
} | |
private readFileIOS(file: IFile) { | |
const reader = new FileReader(); | |
reader.readAsArrayBuffer(file); | |
reader.onloadend = () => { | |
// create blob | |
const blob: any = new Blob([reader.result], { type: file.type }); | |
blob.name = file.name; | |
// set file data | |
this._fileData.blob = blob; | |
this._fileData.fileName = blob.name; | |
// pass data | |
this._fileSubject.next(this._fileData); | |
// clear data to prevent reusing | |
this._fileSubject.next(null); | |
}; | |
} | |
/** | |
* @description | |
* show popup which prefer source for image then pass selected image data to observer | |
* | |
* @usage | |
* | |
* ```html | |
* <div class="avatar-wrapp file-upload-block" (click)="uploadAvatar()"> | |
* <img [src]="tempData.avatarImage | sanitizer" alt="avatar"> | |
* </div> | |
* ``` | |
* Be attentive! | |
* For debugging on local host you should use sanitizer, because of CORS | |
* | |
* | |
* ```ts | |
* this.uploadFileProvider.initImageUpload().subscribe((data: ImageData) => { | |
* this.avatarImage = data.imagePath; | |
* this.formGroup.get('avatarFileName').setValue(data.blob); | |
* }) | |
* ``` | |
* | |
* @returns {BehaviorSubject<ImageData>} | |
*/ | |
initImageUpload(): BehaviorSubject<ImageData> { | |
this.popupImageSource(); | |
this._imageSubject = new BehaviorSubject<ImageData>(null); | |
return this._imageSubject; | |
} | |
private popupImageSource() { | |
let actionSheet = this.actionSheet.create({ | |
buttons: [ | |
{ | |
text: 'Load from gallery', | |
handler: () => this.addImage(this.camera.PictureSourceType.PHOTOLIBRARY), | |
}, | |
{ | |
text: 'Take a photo', | |
handler: () => { | |
this.addImage(this.camera.PictureSourceType.CAMERA); | |
}, | |
}, | |
{ | |
text: 'Cancel', | |
role: 'cancel', | |
}, | |
], | |
}); | |
actionSheet.present(); | |
} | |
private addImage(source) { | |
const options: CameraOptions = { | |
sourceType: source, | |
quality: 100, | |
targetWidth: 900, | |
targetHeight: 1600, | |
destinationType: this.camera.DestinationType.FILE_URI, | |
encodingType: this.camera.EncodingType.JPEG, | |
correctOrientation: false, | |
mediaType: this.camera.MediaType.PICTURE, | |
}; | |
this.camera | |
.getPicture(options) | |
.then(fileUri => { | |
return this.crop.crop(fileUri, { | |
quality: 100, | |
targetWidth: 900, | |
targetHeight: 1600, | |
}); | |
}) | |
.then(path => { | |
// set image path for ios | |
this.setPicturePreview(path, null); | |
this.resolveFileSystem(path); | |
}) | |
.catch(err => console.error(' normalized ERROR: ', JSON.stringify(err))); | |
} | |
private resolveFileSystem(imageFileUri: any) { | |
this.file | |
.resolveLocalFilesystemUrl(imageFileUri) | |
.then(entry => { | |
(<FileEntry>entry).file(file => this.readFile(file)); | |
}) | |
.catch(err => console.error('file ERROR: ', JSON.stringify(err))); | |
} | |
private readFile(file: IFile) { | |
const reader = new FileReader(); | |
reader.readAsArrayBuffer(file); | |
reader.onloadend = () => { | |
// create blob | |
const blob: any = new Blob([reader.result], { type: file.type }); | |
blob.name = file.name; | |
// set image data | |
this._imageData.blob = blob; | |
// set image path for android | |
this.setPicturePreview(null, blob); | |
// pass data | |
this._imageSubject.next(this._imageData); | |
// clear data to prevent reusing | |
this._imageSubject.next(null); | |
}; | |
} | |
private setPicturePreview(forIos: string, forAndroid: Blob) { | |
if (this.platform.is('ios')) { | |
forIos && (this._imageData.imagePath = normalizeURL(forIos)); | |
} else { | |
forAndroid && (this._imageData.imagePath = URL.createObjectURL(forAndroid)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment