Flutter_contacts update contacts function - flutter

I'm quite new to flutter/dart and working in Flutterflow, where trying to create a custom function that takes as input data about the contact in the app (name, surname, cell number, email, photo) and then updates/creates this contact in the user's phone using the next logic:
if a user has a contact with the same name (displayName), then it updates this contact
if a user has a contact with the same phone number, then it updates this contact
if there is no match based on two parameters before, then new contact is created
So far, I have only managed to create a function that checks displayName match, updates contact if there is a match, and if there is no match, it creates a new contact. But I don't know how to do the cell number match/update part (it doesn't work in my code).
The way I'm doing the search for the right contact to update is through the search of contact ID using lists of contacts' names and contacts' IDs to index the right ID when I found the necessary name. It's probably a very ugly and inefficient way to do it, but I don't know the other way.
Will be super happy if someone could give advice on the contact search/update part and overall code optimization (cause I think my approach is long and inefficient). Thank you!
My code is below:
import 'package:flutter_contacts/flutter_contacts.dart';
import 'dart:typed_data';
import 'package:flutter/services.dart';
Future updateContactOnPhone(
String name,
String surname,
String cellnumber,
String email,
String photo,
) async {
String searchingParameterName = name + " " + surname;
String searchingParameterCellphone = cellnumber;
List<String> phoneContactsIDs = [];
List<String> phoneContactsNames = [];
List<String> phoneContactsNumbers = [];
Uint8List bytes = (await NetworkAssetBundle(Uri.parse(photo)).load(photo))
.buffer
.asUint8List();
if (await FlutterContacts.requestPermission()) {
List<dynamic> contacts = await FlutterContacts.getContacts();
contacts.forEach((contact) {phoneContactsIDs.add(contact.id);});
contacts.forEach((contact) {phoneContactsNames.add(contact.displayName);});
contacts.forEach((contact) {if (contact.phones != null) {
phoneContactsNumbers.add(contact.phones.first);}
{phoneContactsNumbers.add("");}});
if (phoneContactsNames.contains(searchingParameterName)) {
int index = phoneContactsNames.indexOf(searchingParameterName);
String contactID = phoneContactsIDs.elementAt(index);
dynamic contact = await FlutterContacts.getContact(contactID);
contact.name.first = name;
contact.name.last = surname;
contact.phones = [Phone(cellnumber)];
contact.emails = [Email(email)];
await contact.update();
} else if (phoneContactsNumbers.contains(searchingParameterCellphone)) {
int index = phoneContactsNumbers.indexOf(searchingParameterCellphone);
String contactID = phoneContactsIDs.elementAt(index);
dynamic contact = await FlutterContacts.getContact(contactID);
contact.name.first = name;
contact.name.last = surname;
contact.phones = [Phone(cellnumber)];
contact.emails = [Email(email)];
await contact.update();
} else {
final newContact = Contact()
..name.first = name
..name.last = surname
..phones = [Phone(cellnumber)]
..emails = [Email(email)]
..photo = bytes;
await newContact.insert();
}}}
I tried various combinations of the code and searched for similar examples on forums, but nothing helped.

This is the code I wrote that worked for me. Hope it'll help someone.
import 'package:flutter_contacts/flutter_contacts.dart';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:collection/collection.dart';
Future updateCreateContact(
String name,
String surname,
String cellnumber,
String email,
String photo,
) async {
String searchingName = name + " " + surname;
Uint8List bytes = (await NetworkAssetBundle(Uri.parse(photo)).load(photo))
.buffer
.asUint8List();
if (await FlutterContacts.requestPermission()) {
List<Contact> contacts = await FlutterContacts.getContacts(
withProperties: true, withPhoto: true);
Contact? contact = contacts.firstWhereOrNull((c) =>
c.displayName == searchingName ||
c.phones.toString().replaceAll(RegExp(r"\D"), "") == cellnumber);
if (contact != null) {
contact.name.first = name;
contact.name.last = surname;
contact.phones = [Phone(cellnumber)];
contact.emails = [Email(email)];
contact.photo = bytes;
await contact.update();
} else {
final newContact = Contact()
..name.first = name
..name.last = surname
..phones = [Phone(cellnumber)]
..emails = [Email(email)]
..photo = bytes;
await newContact.insert();
}
}
}

Related

How to use locationFromAddress in flutter

String _address = ""; // create this variable
void _getPlace() async {
List<Placemark> newPlace = await _geolocator.placemarkFromCoordinates(_position.latitude, _position.longitude);
// this is all you need
Placemark placeMark = newPlace[0];
String name = placeMark.name;
String subLocality = placeMark.subLocality;
String locality = placeMark.locality;
String administrativeArea = placeMark.administrativeArea;
String postalCode = placeMark.postalCode;
String country = placeMark.country;
String address = "${name}, ${subLocality}, ${locality}, ${administrativeArea} ${postalCode}, ${country}";
print(address);
setState(() {
_address = address; // update _address
});
how to replace placemarkFromCoordinates() to locationFromAddress() because convert the address from user input field then change to get the long and lat. Please help me thenks!
You can do both from address to coordinates and vice versa.(with older flutter version & without null safety you can use this)
1st way using geocoding
Future<void> getGeoCoderData() async {
List<Location> locations =
await locationFromAddress("Gronausestraat 710, Enschede");
debugPrint("Address to Lat long ${locations.first.latitude} : ${locations.first.longitude}");
List<Placemark> placemarks =
await placemarkFromCoordinates(52.216653, 6.9462204);
debugPrint("Lat Long to Address: ${placemarks.first.street} : ${placemarks.first.locality}");
}
Output:
2nd way using geocoder
import 'package:geocoder/geocoder.dart';
// From a query / address
final query = "1600 Amphiteatre Parkway, Mountain View";
var addresses = await Geocoder.local.findAddressesFromQuery(query);
var first = addresses.first;
print("${first.featureName} : ${first.coordinates}");
// From coordinates to address
final coordinates = new Coordinates(1.10, 45.50);
addresses = await Geocoder.local.findAddressesFromCoordinates(coordinates);
first = addresses.first;
print("${first.featureName} : ${first.addressLine}");

in return only show Instance of 'User' User is a class

I want this code to convert a csv file to a list, and then convert it to json, for the firebase database, instead of list this code return array it shows an instance of class, like this :
[Instance of 'User', Instance of 'User', Instance of 'User']
void main() {
var users= "username, email, phone \n ctavia,octavia#gmail.com, 099-83-44 \n lark, clark#gmail.com, 054-83-23 \n aven, raven#gmail.com, 784-44-98";
var data = csvToUsersList(users);
print(data);
}
class User {
String username;
String email;
String phone;
User(this.username, this.email, this.phone);
}
List<User> csvToUsersList(String data) {
List<User> users = [];
List<String> userin= data.split("\n");
for (int i = 1; i < userin.length; i++) {
List<String> user = userin[i].split(",");
users.add(User(user[0], user[1], user[2]));
}
return users;
}
That seems correct. If you print something like data.first.username, you should get the name of the first User.
Instance of User just means, that this is an Object of Type User.

Dart is replacing "&" with "\u0026" in a URL

I am using flutter to process a link and download it to the device using dio package.
But the problem is dart is replacing all '&' with '\u0026' and making the link unusable. is there a way to avoid this problem? Thanks in advance.
Here's the code:
const uuid = Uuid();
final Dio dio = Dio();
// * create random id for naming downloaded file
final String randid = uuid.v4();
// * create a local instance of state all media
List<MediaModel> allMedia = state.allMedia;
// * create an instance of IGDownloader utility class from ~/lib/utilities
final IGDownloader igd = IGDownloader();
// * make a download link from provided link from the GetNewMedia event
final link = await igd.getPost(event.link);
link.replaceAll('\u0026', '&');
print(await link);
Output:
// expected : "http://www.example.com/example&examples/"
// result: "http://www.example.com/example\u0026example"
Pass your url to cleanContent function and don't forget to add imports
import 'package:html/parser.dart';
import 'package:html_unescape/html_unescape.dart';
static String cleanContent(String content, {bool decodeComponent = false}) {
if (content.contains("<p>")) {
content = content.replaceAll("<p>", "").trim();
}
if (content.contains("</p>")) {
content = content.replaceAll("</p>", "").trim();
}
var unescape = HtmlUnescape();
content = unescape.convert(content).toString();
if (content.contains("\\<.*?\\>")) {
content = content.replaceAll("\\<.*?\\>", "").trim();
}
content = parseHtmlString(content,decodeComponent: decodeComponent);
return content;
}
static String parseHtmlString(String htmlString,{bool decodeComponent = false}) {
final document = parse(htmlString);
String parsedString = parse(document.body!.text).documentElement!.text;
if(parsedString.contains("%3A")){
parsedString = parsedString.replaceAll("%3A", ":");
}
if(parsedString.contains("%2F")){
parsedString = parsedString.replaceAll("%2F", "/");
}
if(decodeComponent){
parsedString = Uri.decodeComponent(parsedString);
}
return parsedString;
}
replaceAll returns the modified string, but leaves original String untouched.
Try:
print(await link.replaceAll('\u0026', '&'));
or
newLink = link.replaceAll('\u0026', '&');
print(await newLink);

Regarding Trigger email

I have a trigger code:
Trigger AutoEmailsending on Order (after update)
{
Map<Id,Order> Orderdetail = new Map<Id,Order>();
Set<Id> Accountid = new Set<Id>();
for(order or1 : Trigger.new)
{
if(or1.Status == 'Submitted' && (or1.Subtype__c =='Offer' || or1.Subtype__c =='ASP'))
{
Orderdetail.put(or1.id,or1);
Accountid.add (or1.accountid);
}
}
List<Attachment> Attachmentlst = [Select Id,
ParentId,
Name,
BodyLength,
Body,
Description
From Attachment
where ParentId=:Orderdetail.keyset()];
Map<String, Blob> resources = new Map<String, Blob>();
for(StaticResource resource:[SELECT Name, Body FROM StaticResource where Name IN ('TC_for_France','TC_for_Italy')])
{
resources.put(resource.Name, resource.Body);
}
User currentUser = [Select Id,Phone,name from User where Id =:System.UserInfo.getUserId()];
for (attachment attachmentlst1 : attachmentlst )
{
List<String> Toaddress = new List<String>();
List<String> CCaddress = new List<String>();
String Orderid = attachmentlst1.ParentId;
String ResourceName;
String TCname;
string strHtmlBody;
String Emailaddress = UserInfo.getUserEmail();
String CustomerServiceEmail = Order_Configuration__c.getInstance().Customer_Service_Email__c;
string SellingOfficePhone = Order_Configuration__c.getInstance().Selling_Office_Phone__c;
String OrderNumber = Orderdetail.get(attachmentlst1.ParentId).OrderNumber;
List<Messaging.Emailfileattachment> fileAttachments = new List <Messaging.Emailfileattachment>();
if(Accountmap.get(Orderdetail.get(attachmentlst1.ParentId).accountid).Email_Address__c != null)
{
Toaddress.add(Accountmap.get(Orderdetail.get(attachmentlst1.ParentId).accountid).Email_Address__c);
}
String Market = Accountmap.get(Orderdetail.get(attachmentlst1.ParentId).accountid).Market__c;
CCaddress.add(emailaddress);
if(CustomerServiceEmail !=null)
CCaddress.add(CustomerServiceEmail);
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(Toaddress);
mail.setCcAddresses(CCaddress);
if(Orderdetail.get(attachmentlst1.ParentId).Subtype__c =='Offer' || Market=='FR')
{
mail.setSenderDisplayName('Trade Order-FR');
ResourceName = 'TC_for_France';
TCname = 'CONDITIONS_GENERALES_DEVENTE.pdf';
}
}
The trigger should send mail for the created user of the particular order,it should not send mail for last modified user of Particular order How to over come this Scenario,Dont need about the logic what i have to add lines in the trigger code

ConfirmEmailAsync() method is not working

I am having issue in confirming new user email. the Confirm email link works for first 20 minutes , but after 50 minutes the link expires. I have set the token expiration time to 24 hours. Please help me in resolving this issue. I am stuck on it for last 2 days:(.My code is as follows:
I am setting the token lifetime in Create() method in ApplicationUserManager as following:
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"))
{
TokenLifespan = _settings.ConfirmationAndResetTokenExpirationTimeSpan
};
}
And then In AccountsController, the Create method for new user is geiven below. The SendEmailAsync method consist of email subject, email body, generated password and the callback uri.
[Authorize(Roles = Roles.Bam.Name.Admin)]
[HttpPost]
[Route(Routes.Accounts.Template.Create, Name = Routes.Accounts.Name.Create)]
public async Task<IHttpActionResult> Create(CreateUserBindingModel createUserBindingModel)
{
IHttpActionResult result;
var memberNameExists = UserManager.Users.Any(x => x.MemberName.ToLower() == createUserBindingModel.MemberName.ToLower());
if (!memberNameExists)
{
var applicationUser = new ApplicationUser
{
UserName = createUserBindingModel.Email,
Email = createUserBindingModel.Email,
FirstName = createUserBindingModel.FirstName,
LastName = createUserBindingModel.LastName,
Company = createUserBindingModel.Company,
Location = createUserBindingModel.Location,
PhoneNumber = createUserBindingModel.PhoneNumber,
MemberName = createUserBindingModel.MemberName,
LastLoginDate = SqlDateTime.MinValue.Value,
CreateDate = DateTime.Now,
CreatedBy = User.Identity.GetUserId(),
UpdateDate = DateTime.Now,
UpdatedBy = User.Identity.GetUserId(),
TwoFactorEnabled = createUserBindingModel.TwoFactorEnabled,
SecurityResetRequired = true,
PasswordExpirationDate = DateTime.Now.AddDays(Convert.ToDouble(ConfigurationManager.AppSettings["PasswordExpirationDays"]))
};
if (!string.IsNullOrEmpty(createUserBindingModel.AvatarBase64))
{
var avatarBytes = Convert.FromBase64String(createUserBindingModel.AvatarBase64);
var resizedAvatarBytes = ImageResizer.ResizeImage(avatarBytes, _avatarWidth, _avatarHeight);
applicationUser.UserAvatar = new ApplicationUserAvatar
{
Avatar = resizedAvatarBytes
};
}
var generatedPassword = PasswordGenerator.GenerateStrongPassword(10, 10);
var identityResult = await UserManager.CreateAsync(applicationUser, generatedPassword);
if (identityResult.Succeeded)
{
await UserManager.AddToRolesAsync(applicationUser.Id, createUserBindingModel.Roles.ToArray());
var token = await UserManager.GenerateEmailConfirmationTokenAsync(applicationUser.Id);
var callbackUri = string.Format("{0}?userId={1}&token={2}", createUserBindingModel.EmailConfirmationCallbackUri, applicationUser.Id, HttpUtility.UrlEncode(token));
await UserManager.SendEmailAsync(applicationUser.Id, Email.Confirmation.Subject, string.Format(Email.Confirmation.Body, string.Format("{0} {1}", applicationUser.FirstName, applicationUser.LastName), callbackUri, generatedPassword, _settings.AccessTokenExpirationTimeSpan.TotalHours));
var userUrl = new Uri(Url.Link(Routes.Accounts.Name.Get, new { id = applicationUser.Id }));
var roles = await UserManager.GetRolesAsync(applicationUser.Id);
var contract = _accountsMapper.ToContract(applicationUser, roles);
result = Created(userUrl, contract);
}
else
{
result = GetErrorResult(identityResult);
}
}
else
{
ModelState.AddModelError(string.Empty, "Member Name already exists!");
result = BadRequest(ModelState);
}
return result;
}
Once the email is generated the UI has following JS angular code which gets executed and the provide the userid and token to service.
Angular JS code:
angular.module('confirmEmailModule').factory('confirmEmailFactory', function ($http) {
var factory = {};
factory.confirmEmail = function(userId, token) {
var encodedToken = encodeURIComponent(token);
var uri = '/identity/api/accounts/confirmemail?userId=' + userId + '&token=' + token;
return $http.post(uri);
}
return factory;
});
and the Service is :
[AllowAnonymous]
[HttpPost]
[Route(Routes.Accounts.Template.ConfirmEmail, Name = Routes.Accounts.Name.ConfirmEmail)]
public async Task<IHttpActionResult> ConfirmEmail([FromUri] string userId, [FromUri] string token)
{
//var decodedToken = HttpUtility.UrlDecode(token);
var identityResult = await UserManager.ConfirmEmailAsync(userId, token);
var result = identityResult.Succeeded ? StatusCode(HttpStatusCode.NoContent) : GetErrorResult(identityResult);
return result;
}
Please advice.
I found the solution to this issue. I am posting it if somebody faced the same issue. In my case the services and web API were on different servers. Different machine keys caused this issue. So I generated the machine key for my Web application and posted the same machine key in web.config file of Identity service. After that it worked. For more information on generating machine key, following link is helpful.
http://gunaatita.com/Blog/How-to-Generate-Machine-Key-using-IIS/1058
This is what worked for me. Hope it helps out;
public async Task<IActionResult> ConfirmEmail(string userId, string token)
{
if (userId == null || token == null)
{
return RedirectToAction("employees", "home");
}
var user = await userManager.FindByIdAsync(userId);
if (user == null)
{
ViewBag.ErrorMessage = $"The User ID {userId} is invalid";
return View("NotFound");
}
var result = await userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(token));
if (result != null)
{
user.EmailConfirmed = true;
await userManager.UpdateAsync(user);
return View();
}
}