I am implementing a picture upload functionality to my app which I am developing with Ionic 4. I'm using the native plugin camera and a few others to do the following:
async selectImage() {
const actionSheet = await this.actionsheet.create({
header: "Select Image source",
buttons: [{
text: 'Load from Library',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
}
},
{
text: 'Use Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
await actionSheet.present();
}
takePicture(sourceType: PictureSourceType) {
var options: CameraOptions = {
quality: 100,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
this.camera.getPicture(options).then(imagePath => {
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
});
}
copyFileToLocalDir(namePath, currentName, newFileName) {
this.file.copyFile(namePath, currentName, this.file.dataDirectory, newFileName).then(success => {
this.presentToast('Dispongo a actualizar.');
this.updateStoredImages(newFileName);
}, error => {
// this.presentToast('Error while storing file.');
});
}
updateStoredImages(name) {
this.storage.get(STORAGE_KEY).then(images => {
let arr = JSON.parse(images);
if (!arr) {
let newImages = [name];
this.storage.set(STORAGE_KEY, JSON.stringify(newImages));
} else {
arr.push(name);
this.storage.set(STORAGE_KEY, JSON.stringify(arr));
}
let filePath = this.file.dataDirectory + name;
let resPath = this.pathForImage(filePath);
let newEntry = {
name: name,
path: resPath,
filePath: filePath
};
this.images = [newEntry, ...this.images];
this.ref.detectChanges(); // trigger change detection cycle
});
}
So, in the action sheet, when I press the first option (Load from Library) it opens the library and I can choose the picture without any problem. When I press ok, it throws an error: the error expected from the copyFileToLocalDir. However, if I do the same with the second option (Use Camera) and I take a photo with the camera, it loads it fine and I can store it later.
I can't find the problem, please help.
im using this code using ionic 3 and it's working fine .
and after i chose one image it will be uploading to firebase and on the same time view it at page.html
app.module.ts
you have to import
import { Camera } from "#ionic-native/camera";
import { File } from "#ionic-native/file";
and added them #providers
then use this code at page.ts which you will chose one image :
html view
<button ion-button full (click)="openGallery()">open gallery</button>
<img [src]="camel_profile_image_path" />
ts page
import { Camera, CameraOptions } from "#ionic-native/camera";
private camera: Camera,
async openGallery() {
try {
const opstions: CameraOptions = {
quality: 100,
targetHeight: 600,
targetWidth: 600,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
correctOrientation: true
}
const result = await this.camera.getPicture(opstions);
const image = 'data:image/jpeg;base64,' + result;
const pictures = storage().ref('Profile Images/' + this.randomNumber + '.jpg');
pictures.putString(image, 'data_url');
this.base64Image = image;
this.camel_profile_image_path = this.randomNumber; // view the image on html page
this.slidetothis();
} catch (error) {
console.error(error);
}
}
Related
I try to build a simple Text Editor using Electron.
At the moment I want to add a custom title bar which doesn't really work as the buttons are not clickable...
I added an onclick tag to the buttons.
main.js:
//-- variables --\\
const { BrowserWindow, app, Menu, dialog, ipcMain } = require("electron")
let window
let filePath = null //currently opened file
let openFiles = [] //opened files
//-- startup --\\
app.whenReady().then(function()
{
createWindow()
createMenu()
})
//-- functions --\\
function createWindow()
{
window = new BrowserWindow
({
width: 1000,
height: 600,
frame: false,
icon: "./assets/icon.png",
darkTheme: true,
autoHideMenuBar: true,
webPreferences:
{
nodeIntegration: true,
contextIsolation: false
}
})
//window.maximize()
window.loadFile("./frontend/index.html")
window.webContents.openDevTools()
}
function createMenu()
{
Menu.setApplicationMenu(Menu.buildFromTemplate
([
{
label: "File",
submenu:
[
{
label: "Save",
click: saveFile,
accelerator: "CmdOrCtrl+S"
},
{
label: "Open",
click: openFile,
accelerator: "CmdOrCtrl+O"
},
{
label: "New",
click: newFile,
accelerator: "CmdOrCtrl+N"
}
]
}
]))
}
async function promptFilePathOpen()
{
await dialog.showOpenDialog
({ properties: ["openFile"] }).then(function(res)
{
if(res.canceled) return
filePath = res.filePaths[0]
})
}
async function promptFilePathSave()
{
await dialog.showSaveDialog().then(function(res)
{
if(res.canceled) return
filePath = res.filePath
})
}
async function openFile()
{
await promptFilePathOpen()
//openFiles.push(filePath)
window.webContents.send("crd-openFile", filePath)
}
async function saveFile()
{
if(filePath == null || undefined) await promptFilePathSave()
window.webContents.send("crd-saveFile", filePath)
}
async function newFile()
{
filePath = null
await promptFilePathSave()
window.webContents.send("crd-resetEditor")
window.webContents.send("crd-saveFile", filePath)
}
//-- listeners --\\
app.on("window-all-closed", function()
{
if(process.platform != "darwin") app.quit()
})
ipcMain.on("crd-minimizeWindow", function() //does not get called by the renderer
{
//coming soon
})
ipcMain.on("crd-toggleWindowSize", function() //does not get called by the renderer
{
//coming soon
})
ipcMain.on("crd-closeWindow", function() //does not get called by the renderer
{
console.log("quit")
})
renderer/script.js:
//-- imports --\\
const { ipcRenderer } = require("electron")
const fs = require("fs")
const editorElem = document.querySelector("textarea.editor")
//-- functions --\\
function minimizeWindow() // does not get called by the button (index.html)
{
ipcRenderer.send("crd-minimizeWindow")
}
function toggleWindowSize() // does not get called by the button (index.html)
{
ipcRenderer.send("crd-toggleWindowSize")
}
function closeWindow() // does not get called by the button (index.html)
{
ipcRenderer.send("crd-closeWindow")
}
//-- listeners --\\
ipcRenderer.on("crd-openFile", function(e, path)
{
editorElem.value = fs.readFileSync(path, "utf-8")
})
ipcRenderer.on("crd-saveFile", function(e, path)
{
fs.writeFile(path, editorElem.value , function(res, err)
{
if(err) throw err
})
})
ipcRenderer.on("crd-resetEditor", function()
{
editorElem.value = ""
})
The entire code is avalable on my GitHub, because I do not want the whole question consisting of code :)
Two issues here:
You defined functions like closeWindow, but you didn't actually add an event listener for them. You mention onclick but I can't see that in your code. So the first step would be to add document.querySelector('.closeWindow').addEventListener('click', closeWindow) .
You made the whole title bar draggable, including the buttons. That means that the role of the buttons is also a draggable area, so when you click them, you start the drag operation instead of sending a click event. The solution is therefore to make sure the button area does not have the -webkit-app-region: drag style but only the area left to them has. This will probably require you to redesign the HTML layout for the title bar a bit, since this won't work well with the whole thing being a grid.
For more details, see this tutorial.
I am using quill editor and using a image handler for uploading images and it used to work fine but now i am moving to server side rendering and find this error of "File chooser dialog can only be shown with a user activation." while trying to open the file chooser for uploading the file.
imageHandler() {
//
let self=this
let image;
let image_extension;
var input = document.createElement("input");
// Set its type to file
input.type = "file";
// Set accept to the file types you want the user to select.
// Include both the file extension and the mime type
input.accept = "accept";
// set onchange event to call callback when user has selected file
input.addEventListener("change", onchange)
// dispatch a click event to open the file dialog
input.dispatchEvent(new MouseEvent("click")); //getting the error in this line.
input.onchange = async () => {
//
const file = input.files[0];
var ValidImageTypes = ["image/gif", "image/jpeg", "image/png", "image/jpg", "image/GIF", "image/JPEG", "image/PNG", "image/JPG"];
let file_type = file.type
let filename = file.name
let extension = filename.split('.').pop();
// debugger
if(ValidImageTypes.indexOf(file_type) >= 0){
if(file.size<=500000&&file.size>=50000){
// debugger
var fileToLoad = file
// loadImage(fileToLoad, (canvas) => {
// if(canvas){
// this.setState({
// image=canvas.toDataURL()
// image_extension=extension
// });
this.getBase64(file)
.then(result => {
// debugger
file["base64"] = result;
console.log("File Is",file.base64 );
const res = new Promise(function(resolve, reject) {
axios({
method:'post',
url:API_URL+'api/v1/postblogimage',
headers:{
'x-access-handler':loggedinUser.token
},
data:{
image: file.base64,
image_extension:image_extension,
userid:loggedinUser.userid
}
})
//axios.post(API_URL + 'api/v1/postblogimage', formData, config)
.then((response) => {
if (response.data.error == 'false' || response.data.error == false) {
if (response.data.status == 200 && response.data.message == "Image uploaded successfully") {
//
const range = self.quill.getSelection(true);
// Insert temporary loading placeholder image
// this.quill.insertEmbed(range.index, 'image', `${window.location.origin}/images/loaders/placeholder.gif`);
// Move cursor to right side of image (easier to continue typing)
self.quill.setSelection(range.index + 1);
// Remove placeholder image
self.quill.deleteText(range.index, 1);
// Insert uploaded image
let url=response.data.data[0].imageURL;
self.quill.insertEmbed(range.index, 'image', url);
self.quill.pasteHTML(range.index, <img src={url} class="blog-image-content" alt="Responsive image"/>);
}
}
// else if(response.data.error == 'true' || response.data.status == '500')
// componentProps.error('Sorry, Inappropriate image')
// }
}).catch((error) => {
// reject(Error("It broke"));
});
});
// }
// }, {orientation: true});
// }
})
}
else{
// componentProps.error(" Sorry, File size should be of size between 50 kb to 500kb")
}
}
else{
// this.setState({
// image_warning:'Invalid image type',
// image:'',
// image_extension:''
//})
// this.fileInput.value=''
}
};
}
//render function
<ReactQuill
ref={(el) => this.quillRef = el
}
onChange={this.handleChange}
placeholder={"You can insert images between your blog as well. Max image size to not exceed 500kb.Once you have uploaded an image, just wait, image will show up, if it is approved. Use #hashtags to highlight keywords/impact-terms in your blog, your blog might show up in trending keywords. Example: #gain"}
modules={{
toolbar: {
container: [
[{ header: '1' }, { header: [2,3, 4, 5, 6] }, { font: [] }],
[{ size: [ 'small', false, 'large', 'huge' ] }],
['bold', 'italic', 'underline', 'strike', 'blockquote'],
[{ list: 'ordered' }, { list: 'bullet' }],
['link', 'image', 'video'],
['clean'],
['code-block'],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'align': [] }],
],
handlers: {
image: this.imageHandler
}
}
}}
/>
Before you click you must add the input to the document body
document.body.appendChild(input);
i try to use scanner.js but the same error keeps on showing
i have a problem with websocket connection when i try using scanner.js from Asprise.
i installed scanner.js using npm i scanner.js and imported it in my react code. i even added the following script script in my html page and it does notwork.
import React from "react";
import scanner from 'scanner-js';
let scanRequest = {
"use_asprise_dialog": true, // Whether to use Asprise Scanning Dialog
"show_scanner_ui": true, // Whether scanner UI should be shown
"twain_cap_setting" : {
"ICAP_PIXELTYPE" : "TWPT_RGB", // Color
"ICAP_XRESOLUTION" : "100", // DPI: 100
"ICAP_YRESOLUTION" : "100",
"ICAP_SUPPORTEDSIZES" : "TWSS_USLETTER" // Paper size: TWSS_USLETTER, TWSS_A4, ...
},
"output_settings": [{
"type": "return-base64",
"format": "pdf",
"thumbnail_height": 200,
}]
};
/** Triggers the scan */
const scan = () => {
scanner.scan(displayImagesOnPage, scanRequest);
}
/** Processes the scan result */
const displayImagesOnPage = (successful, mesg, response) => {
if (!successful) { // On error
console.error('Failed: ' + mesg);
return;
}
if (successful && mesg != null && mesg.toLowerCase().indexOf('user cancel') >= 0) { // User cancelled.
console.info('User cancelled');
return;
}
let scannedImages = scanner.getScannedImages(response, true, false); // returns an array of ScannedImage
for (let i = 0;
(scannedImages instanceof Array) && i < scannedImages.length; i++) {
let scannedImage = scannedImages[i];
let elementImg = scanner.createDomElementFromModel({
'name': 'img',
'attributes': {
'class': 'scanned',
'src': scannedImage.src
}
});
(document.getElementById('images') ? document.getElementById('images') : document.body).appendChild(elementImg);
}
}
export const Scanner = () => {
return (
<div>
<h2>Scanner.js TEST</h2>
<button type="button" onClick={()=>scan()}>
Scan
</button>
<div id="images"></div>
</div>
);
};
export default Scanner;
I want to create a PWA which acts as a bar- and QR-code scanner. For detecting QR-codes I use jsQR (see: https://github.com/cozmo/jsQR), for barcodes, I want to use QuaggaJS (see: https://serratus.github.io/quaggaJS/). To select the type of code that should be detected, I have some radio buttons on my site, which call the function "triggerScannerInitialisation()" (see below). Scanning QR-codes is working already, but scanning barcodes causes some problems. The camera image is not loaded properly. If I run the same code on testing site that only uses QuaggaJS, scanning barcodes works as it should do. I assume that opening two camera streams from the same camera may cause a problem. Can anyone give me a hint on how to use both with the same camera stream?
// variables for stopping scanner types on next run
let stopJsQrOnNextRun = true;
function triggerScannerInitialisation() {
// get the selected code type
let codeTypeSelector = document.querySelector('input[name="code_type_selector"]:checked').value;
switch (codeTypeSelector) {
case 'barcode':
stopJsQrOnNextRun = true;
startQuaggaJs();
break;
case 'qr':
stopQuaggaJs();
stopJsQrOnNextRun = false;
startJsQr();
break;
default:
return false;
}
}
function startQuaggaJs() {
document.getElementById("barcode_camera_div").hidden = false;
Quagga.init({
inputStream: {
name: "Live",
type: "LiveStream",
target: document.querySelector('#barcode_camera_div'),
constraints: {
width: 480,
height: 320,
facingMode: "environment"
},
},
decoder: {
readers: [
"code_128_reader",
"ean_reader",
"ean_8_reader",
"code_39_reader",
"code_39_vin_reader",
"codabar_reader",
"upc_reader",
"upc_e_reader",
"i2of5_reader"
],
debug: {
showCanvas: true,
showPatches: true,
showFoundPatches: true,
showSkeleton: true,
showLabels: true,
showPatchLabels: true,
showRemainingPatchLabels: true,
boxFromPatches: {
showTransformed: true,
showTransformedBox: true,
showBB: true
}
}
},
}, function (err) {
if (err) {
console.log(err);
return
}
console.log("Initialization finished. Ready to start");
Quagga.start();
});
Quagga.onProcessed(function (result) {
var drawingCtx = Quagga.canvas.ctx.overlay,
drawingCanvas = Quagga.canvas.dom.overlay;
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
result.boxes.filter(function (box) {
return box !== result.box;
}).forEach(function (box) {
Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 });
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 });
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 });
}
}
});
Quagga.onDetected(function (result) {
console.log("Barcode detected and processed : [" + result.codeResult.code + "]", result);
});
}
function stopQuaggaJs() {
// stop quagga JS
Quagga.stop();
document.getElementById("barcode_camera_div").hidden = true;
}
function startJsQr() {
let video = document.createElement("video");
let canvasElement = document.getElementById("canvas");
let canvas = canvasElement.getContext("2d");
let loadingMessage = document.getElementById("loadingMessage");
function drawLine(begin, end, color) {
canvas.beginPath();
canvas.moveTo(begin.x, begin.y);
canvas.lineTo(end.x, end.y);
canvas.lineWidth = 4;
canvas.strokeStyle = color;
canvas.stroke();
}
// Use facingMode: environment to attemt to get the front camera on phones
navigator.mediaDevices.getUserMedia({video: {facingMode: "environment"}}).then(function (stream) {
video.srcObject = stream;
video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
video.play();
console.log("JSQR triggered");
requestAnimationFrame(tickQRcode);
});
function tickQRcode() {
loadingMessage.innerText = "⌛ Video laden...";
if (video.readyState === video.HAVE_ENOUGH_DATA) {
loadingMessage.hidden = true;
canvasElement.hidden = false;
canvasElement.height = video.videoHeight;
canvasElement.width = video.videoWidth;
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
let imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
let code = jsQR(imageData.data, imageData.width, imageData.height, {
inversionAttempts: "dontInvert",
});
if (code) {
drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
codeFound(code.data, 'qr');
}
}
if (!stopJsQrOnNextRun) {
requestAnimationFrame(tickQRcode);
} else {
stopJsQr();
}
}
function stopJsQr() {
// stop the stream
video.srcObject.getTracks().forEach(function (track) {
if (track.readyState === 'live') {
track.stop();
}
});
// remove HTML element properties
let canvasElement = document.getElementById('canvas');
canvasElement.setAttribute('hidden', 1);
canvasElement.removeAttribute('height');
canvasElement.removeAttribute('width');
}
}
Thank you for your help!
Actually this code is from ionic, and I am processing an image that I get through the photo capture. everything works fine, I get the blob, but for some reason my image is not shown in the template, I think the angular binding is not updating. What can I do to force it?
myblob:any=null;
takePhoto() {
const options: CameraOptions = {
quality: 60,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
allowEdit: true,
};
this.camera.getPicture(options).then(
(imageData) => {
this.file
.resolveLocalFilesystemUrl(imageData)
.then((entry: FileEntry) => {
entry.file((file) => {
this.readFile(file);
});
});
},
(err) => {
// Handle error
}
);
}
readFile(file: any) {
const reader = new FileReader();
reader.onloadend = () => {
const imgBlob = new Blob([reader.result], {
type: file.type,
});
//my ngModel (updating) ****------------->
this.myblob = URL.createObjectURL(imgBlob);
console.log(this.documento_reverso);
};
reader.readAsArrayBuffer(file);
}
In my template:
<button (click)="takePhoto()">Take photo</button>
<img *ngIf="myblob" [src]="myblob"> --> is not show at first time button click
how can do it?
When I click the button and get the photo, the image is not displayed, but the second time I click the button it is immediately displayed.
You can wrap the code in NgZone.run to make sure that it runs in the Angular zone and that the change is picked up by change detection:
import { NgZone } from '#angular/core';
constructor(private ngZone: NgZone) { }
readFile(file: any) {
...
this.ngZone.run(() => {
this.myblob = URL.createObjectURL(imgBlob);
});
...
}