Ionic refresher get's fired automatically on page load? - firebase

Ionic refresher seems to be refreshing the page without being manually calling the doRefresh. I would like the refresher to only execute when the "pull down" action is done.
Seems like doRefresh is executed on "ionviewdidload" function automatically.
<ion-refresher (ionRefresh)="doRefresh($event);">
<ion-refresher-content
pullingText="Pull to refresh" pullingIcon="arrow-dropdown"
refreshingSpinner="circles"
refreshingText="..fetching">
</ion-refresher-content>
</ion-refresher>
home.ts
doRefresh(refresher) {
console.log('the current tab that is set = ' + this.tabSelId);
console.log('testing');
this.user = JSON.parse(window.localStorage.getItem('user'));
let self_ = this;
let devicePos = null;
let devicelat = null;
let devicelong = null;
Geolocation.getCurrentPosition().then((position) => {
// self_.loadingData(devicePos);
devicelat = position.coords.latitude;
devicelong = position.coords.longitude;
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
refresher.complete();
}, (err) => {
console.log('failed to get lat and long :' + err);
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
// self_.filter_posts_by_type(self_.tabSelId);
// loading.dismiss();
// refresher.complete();
});
}
on my ionviewdidload function (home.ts):
ionViewDidLoad(){
this.user = JSON.parse(window.localStorage.getItem('user'));
let self_ = this;
let devicePos = null;
console.log('the current tab that is set = '+this.tabSelId);
let devicelat = null;
let devicelong = null;
Geolocation.getCurrentPosition().then((position) => {
devicelat = position.coords.latitude;
devicelong = position.coords.longitude;
console.log('%c executing when position is got successfully ', 'background: #222; color: #bada55');
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
console.log('executing when position is got successfully');
}, (err) => {
console.log('failed to get lat and long :' + err);
devicelat = 28.318237;
devicelong = 111.168137;
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
});
is it the default behaviour when using
"ion-refresher"
I would like the refresher to only fire when "pull down" action is done.
Don't know why the doRefresh() function is being executed when the app is loaded (the first time only)

In your Html use like..
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-refresher-content pullingIcon="arrow-dropdown" pullingText="Pull to refresh" refreshingSpinner="circles"
refreshingText="Refreshing...">
</ion-refresher-content>
</ion-refresher>
In .ts use like...
doRefresh(event) {
this.userPost();
setTimeout(() => {
event.target.complete();
}, 2000);
}

Related

Can't able to fetch the user location in meteor

I developed a meteor app in which while registering I am fetching the user location at the client side, to do so I have added the packages listed below:
meteor add mdg:geolocation
meteor add jeremy:geocomplete
meteor aldeed:geocoder
meteor add jaymc:google-reverse-geocode
The code written at client side is as follows:
if (Meteor.isClient) {
Meteor.startup(() => {
GoogleMaps.load({
v: '3.26',
key: '',
libraries: 'geometry,places'
});
console.log("is GoogleMaps.loaded",GooglMaps.loaded());
});
Template.Registration.onRendered(function () {
Tracker.autorun(() => {
if (GoogleMaps.loaded()) {
$('#txt_address').geocomplete({country: "AU", type:
['()']});
}
});
var date = new Date();
$('#div_dob').datetimepicker({
format: 'DD/MM/YYYY',
maxDate : date,
ignoreReadonly: true
});
date=null;
});
Template.Registration.helpers({
location:function(){
$('input[name="txt_address"]').val(Session.get('location'));
}
});
Template.Registration.events({
'click #btn_findlocation':function(event){
alert('Find Location')
event.preventDefault();
function success(position) {
var crd = position.coords;
console.log(`Latitude0 : ${crd.latitude}`);
console.log(`Longitude0: ${crd.longitude}`);
var lat = crd.latitude;
var long = crd.longitude;
reverseGeocode.getLocation(lat, long, function(location)
{
console.log("Address",JSON.stringify(reverseGeocode.getAddrStr()));
Session.set('location', reverseGeocode.getAddrStr());
});
};// end of function success(position)
function error(err) {
console.warn('ERROR(' + err.code + '): ' + err.message);
};//end of function error(err)
// geolocation options
var options = {
enableHighAccuracy: true,
maximumAge: 0
};// end of var options
navigator.geolocation.getCurrentPosition(success, error,
options);
},
})
}
But I am getting false value for GoogleMaps.loaded() function and the following below error when I click a button to fetch the location.
Can't able to read formatted address of undefined.
Results are inconsistent as sometimes I was able to fetch the location other times not.
Please give any suggestions...

How to return an Observable of type any from firebase query

I am using firebase realtime database for chat feature in my application, I just need to return an Obserable of type any or type Message from firebase query,
Here is my code:
getMessageHistory(farmerId) {
let chatMessages = [];
var chats;
firebase.database().ref('/' + this.chatUrl + '/' + farmerId + '/').once('value', function (snapshot) {
chats = snapshot.val();
if (chats != null) {
Object.keys(chats).forEach(element => {
let chat = chats[element.toString()];
var Message = {
fromId: chat.from,
toId: chat.to,
message: chat.message
}
let mockedHistory: Array<Message>;
mockedHistory.push(Message)
});
}
else {
}
});
}`
How do I return Observable from above method. I have tried angularfire2 but throwing an error while compiling (Angular Version 4)
Got the solution but I don't know is it recommended or not!
let mockedHistory: Array<Message> = [];
let totalRecords = this.db.list('/' + this.chatUrl + '/' + userId + '/');
return totalRecords.valueChanges<any>().map((chat)=>{
var newChat = chat.map((message) => {
let msg = new Message();
msg.fromId = message.from;
msg.toId= message.to,
msg.message= message.message
return msg;
});
return newChat;
}
)

Adding or deleting data in a file with Cloud Functions

my idea is to be able to edit files in storage.
This edition consists of adding or deleting file data according to the firebase trigger.
I created a trigger in firebase after obtaining the file with the bucket.file function ("file.txt"). CreateReadStream ()
and I edited the data in the base in the change in the firebase after this I updated the file with the function
bucket.file ("file.txt"). createWriteStream ().
This solution is good when there is 1 trigger, but when there are more than 2 triggers, the data does not keep correctly why the file is overwritten with the data it had before.
Example
this is the content of file.txt
This text is an example
and executed 2 triggers
the 2 activators get the file at the same time and the first trigger adds data and overwrites the file with this message
this text is an example
and this file was edited with the first trigger
and the second activator erases data and overwrites the file with this message
this text
When the triggers are finished, the file has "this text"
but this file must have
this text
and this file was edited with the first trigger
Someone help me.
exports.createData = functions.database.ref('data/{id}/summary/status').onCreate((data, context) => {
let status = data._data;
return Promise.all([ admin.database().ref('data/' + context.params.id + '/summary/entityUrl').once('value', (snapshot) => {
let entityUrl = snapshot.val();
if (isDataValid(status))
return addDataFile(entityUrl) ;
return;
}) ]);
})
function addDataFile(entityUrl){
return Promise.all([ returnFile("txt",() => {
dataFile.splice(dataFile.length - 1, 0, `new data ${entityUrl}`)
updateFileStorage("txt", dataFile.join('\n'));
}) ]);
}
function returnFile(extension, callback) {
let respData = "";
if (dataFile == null ){
return bucket.file(FileUrl + extension).createReadStream()
.on('data', (chunk) => {
respData += chunk;
})
.on('end', () => {
dataFile = respData.split('\n');
callback();
})
.on('error', (error) => {
console.log("Error en lectura")
return returnFile(extension, callback);
})
}
else callback();
return;
}
function updateFileStorage(extension,data, trys ){
trys = typeof trys !== 'undefined' ? trys : 0;
if(trys>6)
return;
var s = new Readable();
s._read = function noop() { };
s.push(data);
s.push(null);
return s.pipe(bucket.file(FileUrl + extension).createWriteStream())
.on('finish', function () {
//console.log("File updated");
return;
})
.on('error', function (err) {
console.log("Error de Escritura");
return setTimeout(() => {
return updateFileStorage(extension, data, trys + 1)
}, 250);
})
}

How to access image src nativescript

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()]);
});
});
}

How to avoid blockin while uploading file using Meteor method

I've created a Meteor method to upload a file, it's working well but until the file is fully uploaded, I cannot move around, all subscriptions seem to wait that the upload finishes... is there a way to avoid that ?
Here is the code on the server :
Meteor.publish('product-photo', function (productId) {
return Meteor.photos.find({productId: productId}, {limit: 1});
});
Meteor.methods({
/**
* Creates an photo
* #param obj
* #return {*}
*/
createPhoto: function (obj) {
check(obj, Object);
// Filter attributes
obj = filter(obj, [
'name',
'productId',
'size',
'type',
'url'
]);
// Check user
if (!this.userId) {
throw new Meteor.Error('not-connected');
}
// Check file name
if (typeof obj.name !== 'string' || obj.name.length > 255) {
throw new Meteor.Error('invalid-file-name');
}
// Check file type
if (typeof obj.type !== 'string' || [
'image/gif',
'image/jpg',
'image/jpeg',
'image/png'
].indexOf(obj.type) === -1) {
throw new Meteor.Error('invalid-file-type');
}
// Check file url
if (typeof obj.url !== 'string' || obj.url.length < 1) {
throw new Meteor.Error('invalid-file-url');
}
// Check file size
if (typeof obj.size !== 'number' || obj.size <= 0) {
throw new Meteor.Error('invalid-file-size');
}
// Check file max size
if (obj.size > 1024 * 1024) {
throw new Meteor.Error('file-too-large');
}
// Check if product exists
if (!obj.productId || Meteor.products.find({_id: obj.productId}).count() !== 1) {
throw new Meteor.Error('product-not-found');
}
// Limit the number of photos per user
if (Meteor.photos.find({productId: obj.productId}).count() >= 3) {
throw new Meteor.Error('max-photos-reached');
}
// Resize the photo if the data is in base64
if (typeof obj.url === 'string' && obj.url.indexOf('data:') === 0) {
obj.url = resizeImage(obj.url, 400, 400);
obj.size = obj.url.length;
obj.type = 'image/png';
}
// Add info
obj.createdAt = new Date();
obj.userId = this.userId;
return Meteor.photos.insert(obj);
}
});
And the code on the client :
Template.product.events({
'change [name=photo]': function (ev) {
var self = this;
readFilesAsDataURL(ev, function (event, file) {
var photo = {
name: file.name,
productId: self._id,
size: file.size,
type: file.type,
url: event.target.result
};
Session.set('uploadingPhoto', true);
// Save the file
Meteor.call('createPhoto', photo, function (err, photoId) {
Session.set('uploadingPhoto', false);
if (err) {
displayError(err);
} else {
notify(i18n("Transfert terminé pour {{name}}", photo));
}
});
});
}
});
I finally found the solution myself.
Explication : the code I used was blocking the subscriptions because it was using only one method call to transfer all the file from the first byte to the last one, that leads to block the thread (I think, the one reserved to each users on the server) until the transfer is complete.
Solution : I splitted the file into chunks of about 8KB, and send chunk by chunk, this way the thread or whatever was blocking the subscriptions is free after each chunk transfer.
The final working solution is on that post : How to write a file from an ArrayBuffer in JS
Client Code
// data comes from file.readAsArrayBuffer();
var total = data.byteLength;
var offset = 0;
var upload = function() {
var length = 4096; // chunk size
// adjust the last chunk size
if (offset + length > total) {
length = total - offset;
}
// I am using Uint8Array to create the chunk
// because it can be passed to the Meteor.method natively
var chunk = new Uint8Array(data, offset, length);
if (offset < total) {
// Send the chunk to the server and tell it what file to append to
Meteor.call('uploadFileData', fileId, chunk, function (err, length) {
if (!err) {
offset += length;
upload();
}
}
}
};
upload();
Server code
var fs = Npm.require('fs');
var Future = Npm.require('fibers/future');
Meteor.methods({
uploadFileData: function(fileId, chunk) {
var fut = new Future();
var path = '/uploads/' + fileId;
// I tried that with no success
chunk = String.fromCharCode.apply(null, chunk);
// how to write the chunk that is an Uint8Array to the disk ?
fs.appendFile(path, new Buffer(chunk), function (err) {
if (err) {
fut.throw(err);
} else {
fut.return(chunk.length);
}
});
return fut.wait();
}
});
Improving #Karl's code:
Client
This function breaks the file into chunks and sends them to the server one by one.
function uploadFile(file) {
const reader = new FileReader();
let _offset = 0;
let _total = file.size;
return new Promise((resolve, reject) => {
function readChunk() {
var length = 10 * 1024; // chunk size
// adjust the last chunk size
if (_offset + length > _total) {
length = _total - _offset;
}
if (_offset < _total) {
const slice = file.slice(_offset, _offset + length);
reader.readAsArrayBuffer(slice);
} else {
// EOF
setProgress(100);
resolve(true);
}
}
reader.onload = function readerOnload() {
let buffer = new Uint8Array(reader.result) // convert to binary
Meteor.call('fileUpload', file.name, buffer, _offset,
(error, length) => {
if (error) {
console.log('Oops, unable to import!');
return false;
} else {
_offset += length;
readChunk();
}
}
);
};
reader.onloadend = function readerOnloadend() {
setProgress(100 * _offset / _total);
};
readChunk();
});
}
Server
The server then writes to a file when offset is zero, or appends to its end otherwise, returning a promise, as I used an asynchronous function to write/append in order to avoid blocking the client.
if (Meteor.isServer) {
var fs = require('fs');
var Future = require('fibers/future');
}
Meteor.methods({
// Upload file from client to server
fileUpload(
fileName: string,
fileData: Uint8Array,
offset: number) {
check(fileName, String);
check(fileData, Uint8Array);
check(offset, Number);
console.log(`[x] Received file ${fileName} data length: ${fileData.length}`);
if (Meteor.isServer) {
const fut = new Future();
const filePath = '/tmp/' + fileName;
const buffer = new Buffer(fileData);
const jot = offset === 0 ? fs.writeFile : fs.appendFile;
jot(filePath, buffer, 'binary', (err) => {
if (err) {
fut.throw(err);
} else {
fut.return(buffer.length);
}
});
return fut.wait();
}
}
)};
Usage
uploadFile(file)
.then(() => {
/* do your stuff */
});

Resources