using futures with flutter maps - asynchronous

I have this code which is supposed to loop through images to upload them to firebase, then take their links and put it inside the Product class so the product can have its images link. Then, upload the product too.
The problem is it doesn't wait for the upload to happen to insert its links to the product.
Code
List<String> imgUrls = [];
Future<void> loopThroughMap()async{
_map.forEach((storedImage, inGallery) async {
if (!inGallery && storedImage != null && storedImage.path != null) {
await GallerySaver.saveImage(storedImage.path);
}
String urlString = await FirestoreHelper.uploadImage(storedImage);
imgUrls.add(urlString);
});
}
This function is called in here
`
await loopThroughMap();
print('FINISHED THIS ONE, imgs Urls length ${imgUrls.length}');
for (int i = 0; i < imgUrls.length; i++) {
if (i == 0)
_editedProduct.imageUrl = imgUrls[i];
else if (i == 1)
_editedProduct.imageUrl2 = imgUrls[i];
else if (i == 2)
_editedProduct.imageUrl3 = imgUrls[i];
else if (i == 3) _editedProduct.imageUrl4 = imgUrls[i];
}`
The imgUrls list length is ALWAYS zero.
Could it be a problem with the map.foreach?

Ok, I changed the uploading from the ForEach loop to a for loop, and it works fine!
List<File> _listedImages = [];
Future<void> loopThroughMap(){
_map.forEach((storedImage, inGallery) async {
if (!inGallery && storedImage != null && storedImage.path != null) {
GallerySaver.saveImage(storedImage.path);
}
_listedImages.add(storedImage);
});
}
/////
for(var img in _listedImages){
String url = await FirestoreHelper.uploadImage(img);
imgUrls.add(url);
}
After a lot of iterations, the only variable that was causing the error was the ForEach loop.

Related

How to get specific entries in Contentful

So I want to know how I can get all the entries where my sessionId equals to (for example: 4).
public async Task<IActionResult> Index(int? session)
{
var cardio = await _client.GetEntries<CardioModel>();
// ContentfulCollection<CardioModel> cardioModels = new ContentfulCollection<CardioModel>();
// foreach (var model in cardio)
// {
// if(model.Session == 4){
// cardioModels.add(model)
// }
// }
return View(cardio);
}
I tried this but the .add isn't a thing, I tried various ways but none of them is working and I can't find good docs about what I want. I thought probably something with .getEntriesRaw() but I don't know how to work with that.
public async Task<IActionResult> Index(int? session)
{
var cardio = await _client.GetEntries<CardioModel>();
// ContentfulCollection<CardioModel> cardioModels = new ContentfulCollection<CardioModel>();
// foreach (var model in cardio)
// {
// if(model.Session == 4){
// cardioModels.add(model)
// }
// }
return View(cardio);
}
How about just modifying just a little bit
public async Task<IActionResult> Index(int? session)
{
if (session == null || session != 4) return View(null);
var cardio = await _client.GetEntries<CardioModel>().FirstOrDefault(x => x.Session == 4);
return View(cardio);
}

Hyperlinks are lost when using PDFsharp to concatenate multiple PDFs

When using PDFsharp (v1.5x) to concatenate multiple PDF files, hyperlinks that exist in the source files are lost.
The links need to be manually recreated in the composite file. Run this method each time you add a new PdfPage object to the target document.
private void FixWebLinkAnnotations(PdfPage page, PdfDocument doc, int docPage)
{
for (var i = 0; i < page.Annotations.Count; i++)
{
var annot = page.Annotations[i];
var subType = annot.Elements.GetString(PdfAnnotation.Keys.Subtype);
if (subType == "/Link")
{
var dest = annot.Elements.GetDictionary(PdfAnnotation.Keys.A);
var rect = annot.Elements.GetRectangle(PdfAnnotation.Keys.Rect);
if (dest != null && rect != null && dest.Elements.Count > 0)
{
var uri = dest.Elements.GetString("/URI");
for (var p = 0; p < doc.PageCount; p++)
{
if (p == docPage && uri != null)
{
doc.Pages[docPage].Annotations.Add(PdfLinkAnnotation.CreateWebLink(rect, uri));
}
}
}
}
}
}
This code was adapted from https://forum.pdfsharp.net/viewtopic.php?f=3&t=3382 to work with hyperlinks rather than document references.

how to use loop inside query on firestore?

Is it possible to use loop inside query?
Future<void> addServiceConfig(String uid, List<ServiceConfigModel> model) {
_db.collection('users').document(uid).updateData({
'businessDetails':{
'serviceConfig':FieldValue.arrayUnion([
{
for(int i = 0;i <model.length;i++){
if (model[i].inShop != null) 'inShop': model[i].inShop,
if (model[i].inShopAndClientLocation != null)
'inShopAndClientLocation': model[i].inShopAndClientLocation,
if (model[i].clientLocation != null)
'clientLocation': model[i].clientLocation,
'serviceLocations': model[i].serviceLocations,
'subCategoryId': model[i].subCategoryId
}
}
])
}
});
}
I got this error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Invalid argument: Instance of '_CompactLinkedHashSet>'
You can't use a loop (or many other statements) inside an expression, like the value of a field. One solution is to pull construct the value outside of the update() all and then pass it in:
//var config = new Map()
var result = new List();
for(int i = 0;i < model.length; i++){
var config = new Map();
if (model[i].inShop != null) config['inShop'] = model[i].inShop;
if (model[i].inShopAndClientLocation != null)
config['inShopAndClientLocation'] = model[i].inShopAndClientLocation;
if (model[i].clientLocation != null)
config['clientLocation'] = model[i].clientLocation;
config['serviceLocations'] = model[i].serviceLocations,
config['subCategoryId'] = model[i].subCategoryId;
result.add(config);
}
_db.collection('users').document(uid).updateData({
'businessDetails':{
'serviceConfig': FieldValue.arrayUnion(result)
}
});

Flutter Firebase update will not stop updating node?

I'm searching for an int value in my firebase node and decreasing it. It successfully decreases and prints the correct info to my log once. When I attempt to update the node with the new int it repeats as if it where in a loop. How can I get it to update a single time? Here is my code...
if (vidRank == 1) {
await fb.child('UserVideo/${userid}/Vid1').onValue.listen((Event event){
if (event.snapshot != null){
var vid1id = event.snapshot.value['videoID'].toString();
fb.child('NumberOnes/${vid1id}').onValue.listen((Event onesEvent){
if (onesEvent.snapshot != null){
var onesValue = (onesEvent.snapshot.value['Value'] as int);
final vidValue = onesValue - 1;
print("Inside ${vidValue}");
fb.child('NumberOnes/${vid1id}').update({
'Value': vidValue
});
}
});
}
});
If you only want a single action, use .once()
if (vidRank == 1) {
var event = await fb.child('UserVideo/${userid}/Vid1').once();
if (event.snapshot != null){
var vid1id = event.snapshot.value['videoID'].toString();
var onesEvent = await fb.child('NumberOnes/${vid1id}').once();
if (onesEvent.snapshot != null){
var onesValue = (onesEvent.snapshot.value['Value'] as int);
final vidValue = onesValue - 1;
print("Inside ${vidValue}");
fb.child('NumberOnes/${vid1id}').update({
'Value': vidValue
});
}
}
}
otherwise an update will cause another event for listen(...) and you have a perfect loop.

How to get Session obj value on client side from server js?

Hi as i mensioned above how to get the session variable from server to client js using meteor below placed the code verify and give me a sugession.In the bellow code how to get the ltest on client JS.
validation.Js:
Meteor.methods({
signupUser: function signupUser(rawData){
console.log("rawData :: "+rawData);
Mesosphere.signupForm.validate(rawData, function(errors, exmp){
if(!errors){
console.log("No Errors Found");
var username = '';
var password = '';
console.log(rawData.length + ">>>>>>>");
for(var i = 0;i < rawData.length ; i++)
{
var obj = rawData[i];
if(i == 0)
{
username = rawData[i].value;
console.log(rawData[i].value + ">>>>>>>" + obj.value);
}
else(i == 1)
{
password = rawData[i].value;
}
}
var obj = Meteor.call('ltest', username,password);
console.log("**********************"+obj);
//Session.set('q', obj);
//Do what you want with the validated data.
}else{
_(errors).each( function( value, key ) {
console.log("signupUser >> "+key+": "+value.message);
});
}
});
}
});
First of all, You need to use Future for this to return data from async call in method.
Second, Looks like you are trying to do code re-use with calling another meteor method.
IMO, you should not call the meteor method from another meteor method, which will create the another callback for getting results, which is added overhead and also make code unreadable. You should basically create the common function and try calling it from both Meteor method.
Following is listing, which should work
// define this future at top of file
Future = Npm.require("fibers/future")
Meteor.methods({
signupUser: function signupUser(rawData){
console.log("rawData :: "+rawData);
future = new Future()
Mesosphere.signupForm.validate(rawData, function(errors, exmp){
if(!errors){
console.log("No Errors Found");
var username = '';
var password = '';
console.log(rawData.length + ">>>>>>>");
for(var i = 0;i < rawData.length ; i++)
{
var obj = rawData[i];
if(i == 0)
{
username = rawData[i].value;
console.log(rawData[i].value + ">>>>>>>" + obj.value);
}
else(i == 1)
{
password = rawData[i].value;
}
}
//var obj = Meteor.call('ltest', username,password);
// replace above call to common method as described above
obj = common_ltest(username, password);
console.log("**********************"+obj);
future['return'](obj);
}else{
_(errors).each( function( value, key ) {
console.log("signupUser >> "+key+": "+value.message);
});
// assuming some error here, return null to client
future['return'](null);
}
});
// **note that, this important**
return future.wait()
}
});
Hope this helps

Resources