I'm trying to take a photo with the Camera module of NativeScript, then upload it to Firebase, but it doesn't seem to work. imageTaken and fileLocation come up as false and undefined. Is there something wrong with my code? (Written in TypeScript)
import fs = require('file-system')
import frame = require('ui/frame')
import utils = require('utils/utils')
import observableModule = require('data/observable')
import imageSource = require("image-source")
import camera = require('camera')
import image = require('ui/image')
import {
ImageFormat
} from 'ui/enums'
import view = require("ui/core/view")
import firebase = require('nativescript-plugin-firebase')
var dialog = require('nativescript-dialog')
var pd = new observableModule.Observable()
var imageContainer
var imageTaken = false
var fileLocation
exports.loaded = args => {
var page = args.object
imageContainer = view.getViewById(page, "img")
pd.set('imageTaken', imageTaken)
page.bindingContext = pd
}
exports.takePhoto = args => {
const options = {
width: 300,
height: 300,
keepAspectRatio: true
}
camera.takePicture().then((picture) => {
console.log('Take Picture')
var image = new image.Image()
image.imageSource = picture
imageContainer.imageSource = picture
let savePath = fs.knownFolders.documents().path;
let fileName = 'img_' + new Date().getTime() + '_' + this.currentUserId.getValue() + '.' + ImageFormat.jpeg
let filePath = fs.path.join(savePath, fileName)
console.log(filePath)
picture.saveToFile(filePath, ImageFormat.jpeg)
fileLocation = filePath
imageTaken = true
})
}
exports.sendPhoto = args => {
console.log(imageTaken)
console.log(fileLocation)
imageTaken ? upload(Math.random() + '-' + Date.now()) : dialog.show({
title: "Error",
message: "Please take a photo first.",
okButtonText: "OK"
})
}
const upload = (remoteFileName) => {
firebase.uploadFile({
remoteFullPath: 'uploads/images/' + remoteFileName,
localFile: fs.File.fromPath(fileLocation),
localFullPath: fileLocation,
onProgress: function (status) {
console.log("Uploaded fraction: " + status.fractionCompleted)
console.log("Percentage complete: " + status.percentageCompleted)
}
}).then(
uploadedFile => {
console.log("File uploaded: " + JSON.stringify(uploadedFile))
},
error => {
console.log("File upload error: " + error)
}
)
}
The old camera module is obsolete. Use nativescript-camera instead. Note that for Android API23+ you will need to explicitly request permissions runtime. With nativescript-camera it is done with
import * as camera from "nativescript-camera";
camera.requestPermissions();
More about nativescript-camera plugin here
Related
I have next.js project, on server side I generate Looker-sso url and on client side I use this url for embedded dashboard.
Here is how I generate SSO url at Next.js server side
function getLookerSsoUrl(embeddedUserParams: UserInfo, dashboardId: string) : string {
/** Returns Looker Embedded sso url. */
const url_data : LookerEmbeddedUrlOptions = {
"host": LOOKER_HOST,
"secret": LOOKER_SECRET,
"first_name": embeddedUserParams.firstName,
"last_name": embeddedUserParams.lastName,
"external_user_id": embeddedUserParams.firstName + " " + embeddedUserParams.lastName,
"external_group_id": embeddedUserParams.companyName + " group",
"group_ids": [1],
"access_filters": {},
"models": ['db_analytics'],
"permissions": [
'see_user_dashboards',
'see_lookml_dashboards',
'access_data',
'see_looks'],
"user_attributes": {
"name": embeddedUserParams.firstName + " " + embeddedUserParams.lastName,
"first_name": embeddedUserParams.firstName,
"last_name": embeddedUserParams.lastName,
"email": embeddedUserParams.email,
"company_id": embeddedUserParams.companyId,
"company_name": embeddedUserParams.companyName,
"id": embeddedUserParams.id
},
"session_length": 15 * 60,
"embed_url": `/embed/dashboards/${dashboardId}?embed_domain=http://localhost&company_id=${embeddedUserParams.companyId}`,
"force_logout_login": true
}
return "https://" + getSignedEmbedUrl(url_data)
}
function getSignedEmbedUrl(options : LookerEmbeddedUrlOptions) : string {
/** Build sso url with all Looker options and secret key and returns it. */
// looker options
const secret = options.secret
const host = options.host
// user options
const json_external_user_id = JSON.stringify(options.external_user_id)
const json_first_name = JSON.stringify(options.first_name)
const json_last_name = JSON.stringify(options.last_name)
const json_permissions = JSON.stringify(options.permissions)
const json_models = JSON.stringify(options.models)
const json_group_ids = JSON.stringify(options.group_ids)
const json_external_group_id = JSON.stringify(options.external_group_id || "")
const json_user_attributes = JSON.stringify(options.user_attributes || {})
const json_access_filters = JSON.stringify(options.access_filters)
// url/session specific options
const embed_path = '/login/embed/' + encodeURIComponent(options.embed_url)
const json_session_length = JSON.stringify(options.session_length)
const json_force_logout_login = JSON.stringify(options.force_logout_login)
// computed options
const json_time = JSON.stringify(Math.floor((new Date()).getTime() / 1000))
const json_nonce = JSON.stringify(getNonce(16))
// compute signature
let string_to_sign = ""
string_to_sign += host + "\n"
string_to_sign += embed_path + "\n"
string_to_sign += json_nonce + "\n"
string_to_sign += json_time + "\n"
string_to_sign += json_session_length + "\n"
string_to_sign += json_external_user_id + "\n"
string_to_sign += json_permissions + "\n"
string_to_sign += json_models + "\n"
string_to_sign += json_group_ids + "\n"
string_to_sign += json_external_group_id + "\n"
string_to_sign += json_user_attributes + "\n"
string_to_sign += json_access_filters
const signature = createHmac('sha1', secret).update(ForceUnicodeEncoding(string_to_sign)).digest('base64').trim()
// construct query string
const query_params = {
nonce: json_nonce,
time: json_time,
session_length: json_session_length,
external_user_id: json_external_user_id,
permissions: json_permissions,
models: json_models,
access_filters: json_access_filters,
first_name: json_first_name,
last_name: json_last_name,
group_ids: json_group_ids,
external_group_id: json_external_group_id,
user_attributes: json_user_attributes,
force_logout_login: json_force_logout_login,
signature: signature
}
const query_string = stringify(query_params)
return host + embed_path + '?' + query_string
}
function getNonce(len : number) : string {
/** Returns nonce characters. */
let text = ""
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
for (let i = 0; i < len; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length))
return text
}
function ForceUnicodeEncoding(string : string) : string {
/** Decodes a URI component previously created by encodeURIComponent. */
return decodeURIComponent(encodeURIComponent(string))
}
Here is client side code:
import React, {useCallback} from "react"
import {LookerEmbedSDK} from "#looker/embed-sdk"
import {ENV_VAR} from "env"
type embeddedDashboardType = {
id : number
setError? : ((errorMsg : string) => void)
}
export const EmbeddedDashboard = ({id, setError} : embeddedDashboardType) => {
const canceller = (event : any) => {
return { cancel: !event.modal }
}
document.addEventListener("click", ()=>console.log("r"))
const embedCtrRef = useCallback((el) => {
const authUrl = "/api/looker-sso"
if (el) {
LookerEmbedSDK.init("...", authUrl)
LookerEmbedSDK.createDashboardWithId(id)
.withNext()
.appendTo(el)
.on("drillmenu:click", canceller)
.on("drillmodal:explore", canceller)
.on("dashboard:tile:explore", canceller)
.on("look:ready", ()=> console.log("ready"))
.on("explore:ready", ()=>console.log("ready"))
.on("dashboard:run:start", ()=>console.log("ready"))
.on("dashboard:tile:view", canceller)
.build()
.connect()
.catch((error) => {
console.error("Connection error", error)
if (setError){
setError(error)
}
})
}
}, [])
return <>
<style jsx>{`
:global(.container-dashboard) {
width: 100%;
height: 95vh;
}
:global(.container-dashboard > iframe) {
width: 100%;
height: 100%;
}
`}</style>
<div className="container-dashboard" ref={embedCtrRef} />
</>
}
The dashboard displays correctly, but I cant track events, that happen in Looker Iframe
I except, that I would see clicks, which are made on looker iframe
window.onload = function () {
const user_name =
NAME_ARRAY[Math.round(Math.random() * NAME_ARRAY.length)];
document.getElementById("userName_profile").innerHTML = user_name;
document.getElementById("userName").innerHTML = user_name;
const btn = document.querySelector("#sendMessage");
const textfield = document.querySelector("#messageInput");
const log = document.querySelector("#messageArea");
// +++++++++++++++ For chat messaging system ++++++++++++
NAF.connection.subscribeToDataChannel(
"chat",
(senderId, dataType, data, targetId) => {
console.log("msg", data, "from", senderId, targetId);
messageArea.innerHTML += senderId + ": " + data.txt + "<br>";
}
);
btn.addEventListener("click", (evt) => {
NAF.clientId = user_name;
messageArea.innerHTML +=
NAF.clientId + ": " + textfield.value + "<br>";
NAF.connection.broadcastData("chat", { txt: textfield.value });
document.getElementById("messageInput").value = "";
// NAF.easy = user_name;
});
}
When I've made chat system and working fine. The only, issue is that I want a user name rather than a client id. Please, help with this.
Please i am trying to modify the filename of a selected file posted by a user before uploading to Amazon S3 using the edgee:slinghot package. I can upload the file quite alright but the problem is how do i modify the filename.
I modified it on the client using by saving the modified name into a variable. My problem now is how to access that variable declared and saved on the Client in the Server environment. I just can't seem to wrap my head around it.
'change .js-submitTeamPaper' : function(event , template){
event.preventDefault();
let paper = template.paperDetails.get();
newFilename = paper[0].paper_name + "_"
_.map(paper[0].member , (member)=>{
newFilename += "_" + member.regnum + "_"
});
newFilename += paper[0]._id;
let file = event.target.value;
let fileArray = file.split(".");
let ext = fileArray[fileArray.length - 1];
newFilename += "." + ext;
studentFileUpload(event , template , 'submitTeamTermPaper' , 'divProgress');
}
The code to upload the file.
let _collectfile = (event , template) =>{
let file = event.target.files[0]
return file
}
let _showProgressBar = (div) => {
let _div = document.getElementById(div);
_div.classList.remove("hide");
}
let _closeProgressBar = (div) => {
let _div = document.getElementById(div);
_div.classList.add("hide");
}
let _slingShotUploadConfigure = (event , template , folder ,div) => {
let _upload = new Slingshot.Upload(folder);
let _file = _collectfile(event , template);
_showProgressBar(div);
_upload.send(_file , (error , downloadUrl) => {
template.uploader.set();
if (error){
//throw new Meteor.Error('500' , error.reason);
event.target.value = '';
sAlert.error(error.reason , {effect: 'bouncyflip',
position: 'bottom-right', timeout: 3000, onRouteClose: false, stack: false, offset: '150px'});
_closeProgressBar(div);
}
else{
sAlert.success('File was uploaded successfully' , {effect: 'genie',
position: 'bottom-right', timeout: 3000, onRouteClose: false, stack: false, offset: '150px'});
event.target.value = '';
template.downloadUrl.set(downloadUrl);
_closeProgressBar(div);
//return downloadUrl;
}
});
template.uploader.set(_upload);
}
export default function(event , template , folder ,div , progress){
return _slingShotUploadConfigure(event , template , folder,div , progress)
}
I then imported the module as studentFileUpload from '../../modules/handle-fileuploads';
Below is the meteor-slingshot code to do the upload
Slingshot.createDirective("submitTeamTermPaper", Slingshot.S3Storage, {
bucket: Meteor.settings.BucketName,
AWSAccessKeyId : Meteor.settings.AWSAccessKeyId,
AWSSecretAccessKey : Meteor.settings.AWSSecretAccessKey,
acl: "public-read",
authorize: function () {
// do some validation
// e.g. deny uploads if user is not logged in.
if (this.userId) {
return true;
}
},
key: function (file) {
//file here is the file to be uploaded how do i get the modified file name i defined in the client as newFilename here
let timeStamp = + new Date;
//let newFilename = file.name.replace(/_/g , "-");
return 'Team_Term_Papers/' + timeStamp + '_' + '_' + newFilename;
}
});
From my code newFilename is the variable that holds the modified filename. How do i access it from the server environment. Any help is really appreciated. Thanks
You can pass extra information through to slingshot using metacontext:
metacontext = {newName: "foo"};
let _upload = new Slingshot.Upload(folder,metacontext);
Then you can access that metacontext in your key function:
key: function (file,metacontext) {
let timeStamp = + new Date;
let newFilename = metacontext ? metacontext.newName : file.name;
newFilename = newFilename.replace(/_/g , "-");
return 'Team_Term_Papers/' + timeStamp + '_' + '_' + newFilename;
}
How can I get photo src, from nativescript camera module?
public takePicture() {
cameraModule.takePicture().then(function(picture) {
console.log("Result is an image source instance");
var image = new imageModule.Image();
image.imageSource = picture;
console.dir(picture);
});
}
console.dir output:
=== dump(): dumping members ===
{
"android": {
"constructor": "constructor()function () { [native code] }"
}
}
=== dump(): dumping function and properties names ===
loadFromResource()
fromResource()
loadFromFile()
fromFile()
loadFromData()
fromData()
loadFromBase64()
fromBase64()
setNativeSource()
saveToFile()
height: 480
width: 640
=== dump(): finished ===
How do I get the image src ?
I want to upload it to firebase, so i need the src.
To upload to firebase, you need to upload the image via its path:
let imgsrc = this.imageSource.fromNativeSource(data);
let path = this.utils.documentsPath(randomName);
imgsrc.saveToFile(path, this.enums.ImageFormat.png);
this.firebase.uploadFile(path).then((uploadedFile: any) => {
this.appSettings.setString("fileName", uploadedFile.name);
this.router.navigate(['/soundcloud']);
this.LoadingIndicator.hide();
}, (error: any) => {
alert("File upload error: " + error);
});
}, (err: any) => {
alert(err);
});
Figured it out, this works:
public takePicture() {
cameraModule.takePicture().then((picture) => {
var image = new imageModule.Image();
image.imageSource = picture;
let savePath = fs.knownFolders.documents().path;
let fileName = 'img_' + new Date().getTime() + '_' + this.currentUserId.getValue() + '.' + enumsModule.ImageFormat.jpeg;
let filePath = fs.path.join( savePath, fileName );
picture.saveToFile(filePath, enumsModule.ImageFormat.jpeg);
this.photoService.uploadImage(filePath, fileName).then((data) => {
this._router.navigate(["/upload", fileName, this.currentUserId.getValue()]);
});
});
}
Using the chat example, when I close the browser window, I do not ever see the #Disconnect method called.
Here is my service:-
package org.atmosphere.samples.chat;
import java.io.IOException;
import org.atmosphere.config.service.Disconnect;
import org.atmosphere.config.service.ManagedService;
import org.atmosphere.config.service.Ready;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;
import org.atmosphere.cpr.AtmosphereResourceEventListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#ManagedService(path = "{room: [a-zA-Z][a-zA-Z_0-9]*}")
public class Chat
{
private static final Logger LOGGER = LoggerFactory.getLogger(Chat.class);
#Ready
public void onReady(final AtmosphereResource inAtmosphereResource)
{
LOGGER.info("Browser {} connected.", inAtmosphereResource.uuid());
}
#Disconnect
public void onDisconnect(AtmosphereResourceEvent event)
{
if (event.isCancelled())
{
LOGGER.info("Browser {} unexpectedly disconnected", event.getResource().uuid());
}
else if (event.isClosedByClient())
{
LOGGER.info("Browser {} closed the connection", event.getResource().uuid());
}
else
{
LOGGER.info("close event was called, but I know not why");
}
}
#org.atmosphere.config.service.Message(encoders = { JacksonEncoder.class }, decoders = { JacksonDecoder.class })
public Message onMessage(Message message) throws IOException
{
LOGGER.info("{} just send {}", message.getAuthor(), message.getMessage());
return message;
}
}
Here is my JS:-
$(function () {
"use strict";
var header = $('#header');
var content = $('#content');
var input = $('#input');
var status = $('#status');
console.log(document.location.hash);
var bookingNumber = document.location.hash.substring(1, document.location.hash.length);
console.log(bookingNumber);
var myName = false;
var author = null;
var logged = false;
var socket = $.atmosphere;
var subSocket;
var transport = 'websocket';
// We are now ready to cut the request
var request = { url: document.location.toString().replace(/#.*/, "") + 'chat/' + bookingNumber,
contentType : "application/json",
trackMessageLength : true,
shared : true,
logLevel : "debug",
transport : transport ,
fallbackTransport: 'long-polling'};
request.onOpen = function(response) {
content.html($('>p<', { text: 'Atmosphere connected using ' + response.transport }));
input.removeAttr('disabled').focus();
status.text('Choose name:');
transport = response.transport;
if (response.transport == "local") {
subSocket.pushLocal("Name?");
}
};
request.onTransportFailure = function(errorMsg, request) {
jQuery.atmosphere.info(errorMsg);
if (window.EventSource) {
request.fallbackTransport = "sse";
transport = "see";
}
header.html($('<h3>', { text: 'Atmosphere Chat. Default transport is WebSocket, fallback is ' + request.fallbackTransport }));
};
request.onMessage = function (response) {
// We need to be logged first.
if (!myName) return;
var message = response.responseBody;
try {
var json = jQuery.parseJSON(message);
} catch (e) {
console.log('This doesn\'t look like a valid JSON: ', message.data);
return;
}
if (!logged) {
logged = true;
status.text(myName + ': ').css('color', 'blue');
input.removeAttr('disabled').focus();
subSocket.pushLocal(myName);
} else {
input.removeAttr('disabled');
var me = json.author == author;
var date = typeof(json.time) == 'string' ? parseInt(json.time) : json.time;
addMessage(json.author, json.message, me ? 'blue' : 'black', new Date(date));
}
};
request.onClose = function(response) {
logged = false;
}
subSocket = socket.subscribe(request);
input.keydown(function(e) {
if (e.keyCode === 13) {
var msg = $(this).val();
if (author == null) {
author = msg;
}
subSocket.push(jQuery.stringifyJSON({ author: author, message: msg }));
$(this).val('');
input.attr('disabled', 'disabled');
if (myName === false) {
myName = msg;
}
}
});
function addMessage(author, message, color, datetime) {
content.append('<p><span style="color:' + color + '">' + author + '</span> # ' +
+ (datetime.getHours() < 10 ? '0' + datetime.getHours() : datetime.getHours()) + ':'
+ (datetime.getMinutes() < 10 ? '0' + datetime.getMinutes() : datetime.getMinutes())
+ ': ' + message + '</p>');
}
});
I am running on glassfish 3, with web sockets and comet enabled.
UPDATE I forgot to mention that I am using v 2.1.0RC1
tested with GF 3.1.2.2:
Blockquote
[#|2013-12-02T10:43:24.743-0500|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=25;_ThreadName=http-thread-pool-8080(4);|10:43:24.743 [http-thread-pool-8080(4)] INFO org.atmosphere.samples.chat.Chat - Browser 0f7f5596-bd25-4dda-a488-1357da8487f5 closed the connection
Let's havce the discussion on the Atmosphere ML in case you are still experiencing issue. I've tested with the sample BTW.
-- Jeanfrancois