How use MediaFilePicker and PhotoEditor plugins in Nativescript - nativescript

I am trying to use MediaFilePicker on nativescript and at the same time use the PhotoEditor plugin to crop/edit the photo taken from the camera but I don't make it work... here is part of my code:
let options: ImagePickerOptions = {
android: {
isCaptureMood: true, // if true then camera will open directly.
isNeedCamera: true,
maxNumberFiles: 1,
isNeedFolderList: true
}, ios: {
isCaptureMood: true, // if true then camera will open directly.
maxNumberFiles: 1
}
};
let mediafilepicker = new Mediafilepicker();
mediafilepicker.openImagePicker(options);
mediafilepicker.on("getFiles", function (res) {
let results = res.object.get('results');
let result = results[0];
let source = new imageSourceModule.ImageSource();
source.fromAsset(result.rawData).then((source) => {
const photoEditor = new PhotoEditor();
photoEditor.editPhoto({
imageSource: source,
hiddenControls: [],
}).then((newImage) => {
}).catch((e) => {
reject();
});
});
});
The result object of the FilePicker comes like:
{
"type": "capturedImage",
"file": {},
"rawData": "[Circular]"
}
I believe if the picture was taken from the camera, then use the rawData field, but I dont know which format is coming and how to give it to PhotoEditor pluging to play with it.
Any suggestions?
Thanks!

The issue was at this line source.fromAsset(result.rawData) here, result.rawData is not an ImageAsset but it's PHAsset. You will have to create an ImageAsset from PHAsset and pass it on to fromAsset. So it would look like,
import { ImageAsset } from "tns-core-modules/image-asset";
....
....
imgSource.fromAsset(new ImageAsset(img)).then((source) => {
const photoEditor = new PhotoEditor();
console.log(source === imgSource);
photoEditor.editPhoto({
imageSource: source,
hiddenControls: [],
}).then((newImage: ImageSource) => {
console.log('Get files...');
// Here you can save newImage, send it to your backend or simply display it in your app
}).catch((e) => {
//reject();
});
});

Related

Electron check if a window is already open and close before creating

Is it possible to detect in electron if window is already created and close before creating another one?
here is my sample code
// video window listener
ipcMain.on("load-video-window", (event, data) => {
// create the window
//window.close() if window exist;
let videoPlayer = new BrowserWindow({
show: true,
width: 840,
height: 622,
webPreferences: {
nodeIntegration: true,
plugins: true,
},
});
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
videoPlayer.loadURL(
process.env.WEBPACK_DEV_SERVER_URL + "video_player.html"
);
if (!process.env.IS_TEST) videoPlayer.webContents.openDevTools();
} else {
videoPlayer.loadURL(`app://./video_player`);
}
videoPlayer.on("closed", () => {
videoPlayer = null;
});
// here we can send the data to the new window
videoPlayer.webContents.on("did-finish-load", () => {
videoPlayer.webContents.send("data", data);
});
});
I think this should work
let playerWindow;
ipcMain.on("load-video-window", (event, data) => {
if (playerWindow) {
playerWindow.close();
}
playerWindow = new BrowserWindow();
});
Extending #Lord Midi code, we can check to see if a window is not destroyed and is still focusable. You can do that with the following code:
let playerWindow;
const isPlayerWindowOpened = () => !playerWindow?.isDestroyed() && playerWindow?.isFocusable();
ipcMain.on("load-video-window", (event, data) => {
if (isPlayerWindowOpened()) {
playerWindow.close();
}
playerWindow = new BrowserWindow();
})

Nativescript imagepicker not working in iOS :: not picking up image path?

I am using Nativescript with Angular and have a page where I photograph a receipt or add from gallery and add a couple of text inputs and send to server.
The Add from gallery is working fine in Android but not in iOS.
Here is the template code:
<Image *ngIf="imageSrc" [src]="imageSrc" [width]="previewSize" [height]="previewSize" stretch="aspectFit"></Image>
<Button text="Pick from Gallery" (tap)="onSelectGalleryTap()" class="btn-outline btn-photo"> </Button>
and the component:
public onSelectGalleryTap() {
let context = imagepicker.create({
mode: "single"
});
let that = this;
context
.authorize()
.then(() => {
that.imageAssets = [];
that.imageSrc = null;
return context.present();
})
.then((selection) => {
alert("Selection done: " + JSON.stringify(selection));
that.imageSrc = selection.length > 0 ? selection[0] : null;
// convert ImageAsset to ImageSource
fromAsset(that.imageSrc).then(res => {
var myImageSource = res;
var base64 = myImageSource.toBase64String("jpeg", 20);
this.expense.receipt_data=base64;
})
that.cameraImage=null;
that.imageAssets = selection;
that.galleryProvided=true;
// set the images to be loaded from the assets with optimal sizes (optimize memory usage)
selection.forEach(function (element) {
element.options.width = that.previewSize;
element.options.height = that.previewSize;
});
}).catch(function (e) {
console.log(e);
});
}
I have posted below the Android and iOS screenshots of the line:
alert("Selection done: " + JSON.stringify(selection));
In Android there is a path to the location of the image in the file system but in iOS there are just empty curly brackets where I'd expect to see the path and then when submitted the message back is "Unable to save image" although the image preview is displaying on the page in Image.
Here are the screenshots:
Android:
iOS:
Any ideas why it is failing in iOS?
Thanks
==========
UPDATE
I am now saving the image to a temporary location and it is still not working in iOS. It works in Android.
Here is my code now.
import { ImageAsset } from 'tns-core-modules/image-asset';
import { ImageSource, fromAsset, fromFile } from 'tns-core-modules/image-source';
import * as fileSystem from "tns-core-modules/file-system";
...
...
public onSelectGalleryTap() {
alert("in onSelectGalleryTap");
var milliseconds=(new Date).getTime();
let context = imagepicker.create({
mode: "single"
});
let that = this;
context
.authorize()
.then(() => {
that.imageAssets = [];
that.previewSrc = null;
that.imageSrc = null;
return context.present();
})
.then((selection) => {
that.imageSrc = selection.length > 0 ? selection[0] : null;
// convert ImageAsset to ImageSource
fromAsset(that.imageSrc)
.then(res => {
var myImageSource = res;
let folder=fileSystem.knownFolders.documents();
var path=fileSystem.path.join(folder.path, milliseconds+".jpg");
var saved=myImageSource.saveToFile(path, "jpg");
that.previewSrc=path;
const imageFromLocalFile: ImageSource = <ImageSource> fromFile(path);
var base64 = imageFromLocalFile.toBase64String("jpeg", 20);
this.expense.receipt_data=base64;
})
that.cameraImage=null;
that.imageAssets = selection;
that.galleryProvided=true;
// set the images to be loaded from the assets with optimal sizes (optimize memory usage)
selection.forEach(function (element) {
element.options.width = that.previewSize;
element.options.height = that.previewSize;
});
}).catch(function (e) {
console.log(e);
});
}
Any ideas? Thanks.
It is an already communicated issue, several of us subscribed for, check here issue #321
for updates.

Webrtc connect peers on call function

I know this probaly is a longshot, but I was hoping for someone to point me in the right direction here.
I've made a simple peer to peer video connection, and wrapped it inside a function, so I can call it on a button click, but it's not running.
When it's not wrapped inside the "activateVideoStream" function, but just on load, it works fine. I have a feeling that the issue is around the async function, but I can't wrap my head around it.
Here is the code:
let isAlreadyCalling = false;
const remoteVideo = document.getElementById("remote-video");
const {
RTCPeerConnection,
RTCSessionDescription
} = window;
let peerConnection;
function activateVideoStream() {
const configuration = {
"iceServers": [{
"urls": "stun:stun.l.google.com:19302"
}]
};
console.log("Activate Video Stream");
peerConnection = new RTCPeerConnection(configuration);
navigator.getUserMedia({
video: true,
audio: true
},
stream => {
const localVideo = document.getElementById("local-video");
if (localVideo) {
localVideo.srcObject = stream;
}
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));
},
error => {
console.warn(error.message);
}
);
peerConnection.ontrack = function ({
streams: [stream]
}) {
if (remoteVideo) {
remoteVideo.srcObject = stream;
}
};
}
async function callUser(socketId) {
console.log("Call User");
remoteVideo.style.display = "block";
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(new RTCSessionDescription(offer));
socket.emit("callUser", {
offer,
to: socketId
});
}
socket.on("callMade", async data => {
console.log("Call made");
await peerConnection.setRemoteDescription(
new RTCSessionDescription(data.offer)
);
const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(new RTCSessionDescription(answer));
remoteVideo.style.display = "block";
socket.emit("makeAnswer", {
answer,
to: data.socket
});
});
socket.on("answerMade", async data => {
console.log("Answer made");
await peerConnection.setRemoteDescription(
new RTCSessionDescription(data.answer)
);
if (!isAlreadyCalling) {
callUser(data.socket);
isAlreadyCalling = true;
}
});
I've noticed that "peerConnection.connectionState" inside "callUser" is being set to "new", but without the function wrapped around, it's set to "complete", so that's probaly the issue.

How to upload image with FILE_URI distination to firebase storage in Ionic 2

I'm trying to upload captured image to firebase storage after edit it by some custom editor.
My problem under two cases:
Case1 : If I used this code, then I can upload the image but I can't use my custom editor
takePicture(){
let options: CameraOptions;
options = {
quality : 85,
destinationType: this.camera.DestinationType.DATA_URL,
sourceType : this.camera.PictureSourceType.CAMERA,
allowEdit : false,
encodingType: this.camera.EncodingType.JPEG,
correctOrientation: true,
saveToPhotoAlbum: true
}
this.camera.getPicture(options).then((imageData) => {
this.currentOriginalImageUri = 'data:image/jpeg;base64,' + imageData;
this.currentDocumentImageUri = 'data:image/jpeg;base64,' + imageData;
});
}
Case2 : If I used this code, then I can use the function of custom editor but I can't upload my image
takePicture(){
let options: CameraOptions;
options = {
quality : 85,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType : this.camera.PictureSourceType.CAMERA,
allowEdit : false,
encodingType: this.camera.EncodingType.JPEG,
correctOrientation: true,
saveToPhotoAlbum: true
}
this.camera.getPicture(options).then((imageData) => {
this.currentOriginalImageUri = imageData;
this.currentDocumentImageUri = imageData;
});
}
Note: This is my uploading function
private uploadPhoto(): void {
let loader = this.loadingCtrl.create({
content: ""
})
loader.present().then(_=>{
return this.myPhotosRef.child(this.generateUUID()).child('myPhoto.JPEG').putString(this.currentDocumentImageUri,firebase.storage.StringFormat.DATA_URL).then((savedPicture) => {
this.currentDocumentImageUri = savedPicture.downloadURL;
this.afd.list('/notesImages/').push({
note_id: this.appService.id,
url: this.currentDocumentImageUri,
date: new Date().toISOString()
});
});
}).then(_=>{
loader.dismiss();
this.viewCtrl.dismiss();
})
}
So is there any way to use the both cases?
You are saving image as a string in the database. If you want to upload a file using file path using the linked api (assuming data_url is not working for your custom editor)
Try put() instead of putString().
return this.myPhotosRef.child(this.generateUUID()).child('myPhoto.JPEG').put(this.currentDocumentImageUri).then((savedPicture) => {
// rest of code
});

How to return result from angular2-modal, or in general from ng2-components

I am using the this great angular2-modal but can't figure out how to return a result value from my custom modal.
I instantiate it like this:
let dialog: Promise<ModalDialogInstance>;
let bindings = Injector.resolve([
provide(ICustomModal, { useValue: this.gewaehltesBild })
]);
var self = this;
dialog = this.modal.open(
<any>ImagecropperComponent,
bindings,
new ModalConfig("md", true, 27));
dialog.then((resultPromise) => {
return resultPromise.result.then((result) => {
this.lastModalResult = result;
this.mitarbeiter.avatarImg = this.gewaehltesBild;
$(self.elementRef.nativeElement).find('#bildSelector').val("");
}, () => this.lastModalResult = 'Rejected!');
});
I have tried to send my returnvalue with
this.dialog.close(this.croppedImage);
but result is always null. Is there a convention in angular2 how to return values from components, that is used by angular2-modal?
Thank you!
Works fine for me, I too am using custom dialog and here is how i catch the result
var dialog = this._modal.open(VideoPlayerComponent,
resolvedBindings,
new ModalConfig('lg', true, 27));
dialog
.then((d) => d.result)
.then((r) => { console.log(r); }, (error) => { console.log(r); });
When i call close on the instance
this._dialog.close("Hello");
It does print Hello

Resources