Mon 21 Jul 22:43:21 CEST 2025
This commit is contained in:
parent
dfca45d97a
commit
5a63537374
592
js/ui/cordova/plugins/cordova-plugin-contacts/src/wp/Contacts.cs
Normal file
592
js/ui/cordova/plugins/cordova-plugin-contacts/src/wp/Contacts.cs
Normal file
|
@ -0,0 +1,592 @@
|
|||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
using Microsoft.Phone.Tasks;
|
||||
using Microsoft.Phone.UserData;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
using DeviceContacts = Microsoft.Phone.UserData.Contacts;
|
||||
|
||||
|
||||
namespace WPCordovaClassLib.Cordova.Commands
|
||||
{
|
||||
[DataContract]
|
||||
public class SearchOptions
|
||||
{
|
||||
[DataMember]
|
||||
public string filter { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public bool multiple { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string[] desiredFields { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class ContactSearchParams
|
||||
{
|
||||
[DataMember]
|
||||
public string[] fields { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public SearchOptions options { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class JSONContactAddress
|
||||
{
|
||||
[DataMember]
|
||||
public string formatted { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string type { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string streetAddress { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string locality { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string region { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string postalCode { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string country { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public bool pref { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class JSONContactName
|
||||
{
|
||||
[DataMember]
|
||||
public string formatted { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string familyName { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string givenName { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string middleName { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string honorificPrefix { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string honorificSuffix { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class JSONContactField
|
||||
{
|
||||
[DataMember]
|
||||
public string type { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string value { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public bool pref { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class JSONContactOrganization
|
||||
{
|
||||
[DataMember]
|
||||
public string type { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string name { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public bool pref { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string department { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string title { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class JSONContact
|
||||
{
|
||||
[DataMember]
|
||||
public string id { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string rawId { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string displayName { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string nickname { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string note { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public JSONContactName name { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public JSONContactField[] emails { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public JSONContactField[] phoneNumbers { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public JSONContactField[] ims { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public JSONContactField[] photos { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public JSONContactField[] categories { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public JSONContactField[] urls { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public JSONContactOrganization[] organizations { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public JSONContactAddress[] addresses { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class Contacts : BaseCommand
|
||||
{
|
||||
public const int UNKNOWN_ERROR = 0;
|
||||
public const int INVALID_ARGUMENT_ERROR = 1;
|
||||
public const int TIMEOUT_ERROR = 2;
|
||||
public const int PENDING_OPERATION_ERROR = 3;
|
||||
public const int IO_ERROR = 4;
|
||||
public const int NOT_SUPPORTED_ERROR = 5;
|
||||
public const int PERMISSION_DENIED_ERROR = 20;
|
||||
public const int SYNTAX_ERR = 8;
|
||||
|
||||
// refer here for contact properties we can access: http://msdn.microsoft.com/en-us/library/microsoft.phone.tasks.savecontacttask_members%28v=VS.92%29.aspx
|
||||
public void save(string jsonContact)
|
||||
{
|
||||
// jsonContact is actually an array of 1 {contact}
|
||||
string[] args = JSON.JsonHelper.Deserialize<string[]>(jsonContact);
|
||||
|
||||
|
||||
JSONContact contact = JSON.JsonHelper.Deserialize<JSONContact>(args[0]);
|
||||
|
||||
SaveContactTask contactTask = new SaveContactTask();
|
||||
|
||||
if (contact.nickname != null)
|
||||
{
|
||||
contactTask.Nickname = contact.nickname;
|
||||
}
|
||||
if (contact.urls != null && contact.urls.Length > 0)
|
||||
{
|
||||
contactTask.Website = contact.urls[0].value;
|
||||
}
|
||||
if (contact.note != null)
|
||||
{
|
||||
contactTask.Notes = contact.note;
|
||||
}
|
||||
|
||||
#region contact.name
|
||||
|
||||
if (contact.name != null)
|
||||
{
|
||||
if (contact.name.givenName != null)
|
||||
contactTask.FirstName = contact.name.givenName;
|
||||
if (contact.name.familyName != null)
|
||||
contactTask.LastName = contact.name.familyName;
|
||||
if (contact.name.middleName != null)
|
||||
contactTask.MiddleName = contact.name.middleName;
|
||||
if (contact.name.honorificSuffix != null)
|
||||
contactTask.Suffix = contact.name.honorificSuffix;
|
||||
if (contact.name.honorificPrefix != null)
|
||||
contactTask.Title = contact.name.honorificPrefix;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region contact.org
|
||||
|
||||
if (contact.organizations != null && contact.organizations.Count() > 0)
|
||||
{
|
||||
contactTask.Company = contact.organizations[0].name;
|
||||
contactTask.JobTitle = contact.organizations[0].title;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region contact.phoneNumbers
|
||||
|
||||
if (contact.phoneNumbers != null && contact.phoneNumbers.Length > 0)
|
||||
{
|
||||
foreach (JSONContactField field in contact.phoneNumbers)
|
||||
{
|
||||
string fieldType = field.type.ToLower();
|
||||
if (fieldType == "work")
|
||||
{
|
||||
contactTask.WorkPhone = field.value;
|
||||
}
|
||||
else if (fieldType == "home")
|
||||
{
|
||||
contactTask.HomePhone = field.value;
|
||||
}
|
||||
else if (fieldType == "mobile")
|
||||
{
|
||||
contactTask.MobilePhone = field.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region contact.emails
|
||||
|
||||
if (contact.emails != null && contact.emails.Length > 0)
|
||||
{
|
||||
// set up different email types if they are not explicitly defined
|
||||
foreach (string type in new[] {"personal", "work", "other"})
|
||||
{
|
||||
foreach (JSONContactField field in contact.emails)
|
||||
{
|
||||
if (field != null && String.IsNullOrEmpty(field.type))
|
||||
{
|
||||
field.type = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (JSONContactField field in contact.emails)
|
||||
{
|
||||
if (field != null)
|
||||
{
|
||||
if (field.type != null && field.type != "other")
|
||||
{
|
||||
string fieldType = field.type.ToLower();
|
||||
if (fieldType == "work")
|
||||
{
|
||||
contactTask.WorkEmail = field.value;
|
||||
}
|
||||
else if (fieldType == "home" || fieldType == "personal")
|
||||
{
|
||||
contactTask.PersonalEmail = field.value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
contactTask.OtherEmail = field.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
if (contact.note != null && contact.note.Length > 0)
|
||||
{
|
||||
contactTask.Notes = contact.note;
|
||||
}
|
||||
|
||||
#region contact.addresses
|
||||
|
||||
if (contact.addresses != null && contact.addresses.Length > 0)
|
||||
{
|
||||
foreach (JSONContactAddress address in contact.addresses)
|
||||
{
|
||||
if (address.type == null)
|
||||
{
|
||||
address.type = "home"; // set a default
|
||||
}
|
||||
string fieldType = address.type.ToLower();
|
||||
if (fieldType == "work")
|
||||
{
|
||||
contactTask.WorkAddressCity = address.locality;
|
||||
contactTask.WorkAddressCountry = address.country;
|
||||
contactTask.WorkAddressState = address.region;
|
||||
contactTask.WorkAddressStreet = address.streetAddress;
|
||||
contactTask.WorkAddressZipCode = address.postalCode;
|
||||
}
|
||||
else if (fieldType == "home" || fieldType == "personal")
|
||||
{
|
||||
contactTask.HomeAddressCity = address.locality;
|
||||
contactTask.HomeAddressCountry = address.country;
|
||||
contactTask.HomeAddressState = address.region;
|
||||
contactTask.HomeAddressStreet = address.streetAddress;
|
||||
contactTask.HomeAddressZipCode = address.postalCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no other address fields available ...
|
||||
Debug.WriteLine("Creating contact with unsupported address type :: " + address.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
contactTask.Completed += ContactSaveTaskCompleted;
|
||||
contactTask.Show();
|
||||
}
|
||||
|
||||
private void ContactSaveTaskCompleted(object sender, SaveContactResult e)
|
||||
{
|
||||
SaveContactTask task = sender as SaveContactTask;
|
||||
|
||||
if (e.TaskResult == TaskResult.OK)
|
||||
{
|
||||
Deployment.Current.Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
var deviceContacts = new DeviceContacts();
|
||||
deviceContacts.SearchCompleted +=
|
||||
postAdd_SearchCompleted;
|
||||
|
||||
if (task != null)
|
||||
{
|
||||
string displayName = String.Format("{0}{2}{1}", task.FirstName, task.LastName,
|
||||
String.IsNullOrEmpty(task.FirstName) ? "" : " ");
|
||||
|
||||
deviceContacts.SearchAsync(displayName, FilterKind.DisplayName, task);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (e.TaskResult == TaskResult.Cancel)
|
||||
{
|
||||
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Operation cancelled."));
|
||||
}
|
||||
}
|
||||
|
||||
private void postAdd_SearchCompleted(object sender, ContactsSearchEventArgs e)
|
||||
{
|
||||
if (e.Results.Any())
|
||||
{
|
||||
new List<Contact>();
|
||||
|
||||
int n = (from Contact contact in e.Results select contact.GetHashCode()).Max();
|
||||
Contact newContact = (from Contact contact in e.Results
|
||||
where contact.GetHashCode() == n
|
||||
select contact).First();
|
||||
|
||||
DispatchCommandResult(new PluginResult(PluginResult.Status.OK, newContact.ToJson(null)));
|
||||
}
|
||||
else
|
||||
{
|
||||
DispatchCommandResult(new PluginResult(PluginResult.Status.NO_RESULT));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void remove(string id)
|
||||
{
|
||||
// note id is wrapped in [] and always has exactly one string ...
|
||||
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "{\"code\":" + NOT_SUPPORTED_ERROR + "}"));
|
||||
}
|
||||
|
||||
public void pickContact(string arguments)
|
||||
{
|
||||
string[] args = JSON.JsonHelper.Deserialize<string[]>(arguments);
|
||||
|
||||
// Use custom contact picker because WP8 api doesn't provide its' own
|
||||
// contact picker, only PhoneNumberChooser or EmailAddressChooserTask
|
||||
var task = new ContactPickerTask();
|
||||
var desiredFields = JSON.JsonHelper.Deserialize<string[]>(args[0]);
|
||||
|
||||
task.Completed += delegate(Object sender, ContactPickerTask.PickResult e)
|
||||
{
|
||||
if (e.TaskResult == TaskResult.OK)
|
||||
{
|
||||
string strResult = e.Contact.ToJson(desiredFields);
|
||||
var result = new PluginResult(PluginResult.Status.OK)
|
||||
{
|
||||
Message = strResult
|
||||
};
|
||||
DispatchCommandResult(result);
|
||||
}
|
||||
if (e.TaskResult == TaskResult.Cancel)
|
||||
{
|
||||
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Operation cancelled."));
|
||||
}
|
||||
};
|
||||
|
||||
task.Show();
|
||||
}
|
||||
|
||||
public void search(string searchCriteria)
|
||||
{
|
||||
string[] args = JSON.JsonHelper.Deserialize<string[]>(searchCriteria);
|
||||
|
||||
ContactSearchParams searchParams = new ContactSearchParams();
|
||||
try
|
||||
{
|
||||
searchParams.fields = JSON.JsonHelper.Deserialize<string[]>(args[0]);
|
||||
searchParams.options = JSON.JsonHelper.Deserialize<SearchOptions>(args[1]);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_ARGUMENT_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (searchParams.options == null)
|
||||
{
|
||||
searchParams.options = new SearchOptions();
|
||||
searchParams.options.filter = "";
|
||||
searchParams.options.multiple = true;
|
||||
}
|
||||
else if (searchParams.options.filter == null)
|
||||
{
|
||||
searchParams.options.filter = "";
|
||||
}
|
||||
|
||||
DeviceContacts deviceContacts = new DeviceContacts();
|
||||
deviceContacts.SearchCompleted += contacts_SearchCompleted;
|
||||
|
||||
// default is to search all fields
|
||||
FilterKind filterKind = FilterKind.None;
|
||||
// if only one field is specified, we will try the 3 available DeviceContact search filters
|
||||
if (searchParams.fields.Count() == 1)
|
||||
{
|
||||
if (searchParams.fields.Contains("name"))
|
||||
{
|
||||
filterKind = FilterKind.DisplayName;
|
||||
}
|
||||
else if (searchParams.fields.Contains("emails"))
|
||||
{
|
||||
filterKind = FilterKind.EmailAddress;
|
||||
}
|
||||
else if (searchParams.fields.Contains("phoneNumbers"))
|
||||
{
|
||||
filterKind = FilterKind.PhoneNumber;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
deviceContacts.SearchAsync(searchParams.options.filter, filterKind, searchParams);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("search contacts exception :: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
|
||||
{
|
||||
var searchParams = (ContactSearchParams) e.State;
|
||||
|
||||
List<Contact> foundContacts = null;
|
||||
// used for comparing strings, "" instantiates with InvariantCulture
|
||||
CultureInfo culture = new CultureInfo("");
|
||||
// make the search comparisons case insensitive.
|
||||
CompareOptions compare_option = CompareOptions.IgnoreCase;
|
||||
|
||||
// if we have multiple search fields
|
||||
|
||||
if (!String.IsNullOrEmpty(searchParams.options.filter) && searchParams.fields.Count() > 1)
|
||||
{
|
||||
foundContacts = new List<Contact>();
|
||||
if (searchParams.fields.Contains("emails"))
|
||||
{
|
||||
foundContacts.AddRange(from Contact con in e.Results
|
||||
from ContactEmailAddress a in con.EmailAddresses
|
||||
where
|
||||
culture.CompareInfo.IndexOf(a.EmailAddress, searchParams.options.filter,
|
||||
compare_option) >= 0
|
||||
select con);
|
||||
}
|
||||
if (searchParams.fields.Contains("displayName"))
|
||||
{
|
||||
foundContacts.AddRange(from Contact con in e.Results
|
||||
where
|
||||
culture.CompareInfo.IndexOf(con.DisplayName, searchParams.options.filter,
|
||||
compare_option) >= 0
|
||||
select con);
|
||||
}
|
||||
if (searchParams.fields.Contains("name"))
|
||||
{
|
||||
foundContacts.AddRange(
|
||||
from Contact con in e.Results
|
||||
where con.CompleteName != null && (
|
||||
(con.CompleteName.FirstName != null && culture.CompareInfo.IndexOf(con.CompleteName.FirstName, searchParams.options.filter, compare_option) >= 0) ||
|
||||
(con.CompleteName.LastName != null && culture.CompareInfo.IndexOf(con.CompleteName.LastName, searchParams.options.filter, compare_option) >= 0) ||
|
||||
(con.CompleteName.MiddleName != null && culture.CompareInfo.IndexOf(con.CompleteName.MiddleName, searchParams.options.filter, compare_option) >= 0) ||
|
||||
(con.CompleteName.Nickname != null && culture.CompareInfo.IndexOf(con.CompleteName.Nickname, searchParams.options.filter, compare_option) >= 0) ||
|
||||
(con.CompleteName.Suffix != null && culture.CompareInfo.IndexOf(con.CompleteName.Suffix, searchParams.options.filter, compare_option) >= 0) ||
|
||||
(con.CompleteName.Title != null && culture.CompareInfo.IndexOf(con.CompleteName.Title, searchParams.options.filter, compare_option) >= 0) ||
|
||||
(con.CompleteName.YomiFirstName != null && culture.CompareInfo.IndexOf(con.CompleteName.YomiFirstName, searchParams.options.filter, compare_option) >= 0) ||
|
||||
(con.CompleteName.YomiLastName != null && culture.CompareInfo.IndexOf(con.CompleteName.YomiLastName, searchParams.options.filter, compare_option) >= 0))
|
||||
select con);
|
||||
}
|
||||
if (searchParams.fields.Contains("phoneNumbers"))
|
||||
{
|
||||
foundContacts.AddRange(from Contact con in e.Results
|
||||
from ContactPhoneNumber a in con.PhoneNumbers
|
||||
where
|
||||
culture.CompareInfo.IndexOf(a.PhoneNumber, searchParams.options.filter,
|
||||
compare_option) >= 0
|
||||
select con);
|
||||
}
|
||||
if (searchParams.fields.Contains("urls"))
|
||||
{
|
||||
foundContacts.AddRange(from Contact con in e.Results
|
||||
from string a in con.Websites
|
||||
where
|
||||
culture.CompareInfo.IndexOf(a, searchParams.options.filter,
|
||||
compare_option) >= 0
|
||||
select con);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foundContacts = new List<Contact>(e.Results);
|
||||
}
|
||||
|
||||
string strResult = "";
|
||||
|
||||
IEnumerable<Contact> distinctContacts = foundContacts.Distinct();
|
||||
|
||||
foreach (Contact contact in distinctContacts)
|
||||
{
|
||||
strResult += contact.ToJson(searchParams.options.desiredFields) + ",";
|
||||
|
||||
if (!searchParams.options.multiple)
|
||||
{
|
||||
break; // just return the first item
|
||||
}
|
||||
}
|
||||
PluginResult result = new PluginResult(PluginResult.Status.OK);
|
||||
result.Message = "[" + strResult.TrimEnd(',') + "]";
|
||||
DispatchCommandResult(result);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user