http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/765c8158/common-items/Plugins/Compass.cs ---------------------------------------------------------------------- diff --git a/common-items/Plugins/Compass.cs b/common-items/Plugins/Compass.cs new file mode 100644 index 0000000..c9e1c4d --- /dev/null +++ b/common-items/Plugins/Compass.cs @@ -0,0 +1,362 @@ +/* + Licensed 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 System; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Ink; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; +using DeviceCompass = Microsoft.Devices.Sensors.Compass; +using System.Windows.Threading; +using System.Runtime.Serialization; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Threading; +using Microsoft.Devices.Sensors; + +namespace WPCordovaClassLib.Cordova.Commands +{ + + public class Compass : BaseCommand + { + #region Static members + + /// <summary> + /// Status of listener + /// </summary> + private static int currentStatus; + + /// <summary> + /// Id for get getCompass method + /// </summary> + private static string getCompassId = "getCompassId"; + + /// <summary> + /// Compass + /// </summary> + private static DeviceCompass compass = new DeviceCompass(); + + /// <summary> + /// Listeners for callbacks + /// </summary> + private static Dictionary<string, Compass> watchers = new Dictionary<string, Compass>(); + + #endregion + + #region Status codes + + public const int Stopped = 0; + public const int Starting = 1; + public const int Running = 2; + public const int ErrorFailedToStart = 4; + public const int Not_Supported = 20; + + /* + * // Capture error codes + CompassError.COMPASS_INTERNAL_ERR = 0; + CompassError.COMPASS_NOT_SUPPORTED = 20; + * */ + + #endregion + + #region CompassOptions class + /// <summary> + /// Represents Accelerometer options. + /// </summary> + [DataContract] + public class CompassOptions + { + /// <summary> + /// How often to retrieve the Acceleration in milliseconds + /// </summary> + [DataMember(IsRequired = false, Name = "frequency")] + public int Frequency { get; set; } + + /// <summary> + /// The change in degrees required to initiate a watchHeadingFilter success callback. + /// </summary> + [DataMember(IsRequired = false, Name = "filter")] + public int Filter { get; set; } + + /// <summary> + /// Watcher id + /// </summary> + [DataMember(IsRequired = false, Name = "id")] + public string Id { get; set; } + + } + #endregion + + + /// <summary> + /// Time the value was last changed + /// </summary> + //private DateTime lastValueChangedTime; + + /// <summary> + /// Accelerometer options + /// </summary> + private CompassOptions compassOptions; + + //bool isDataValid; + + //bool calibrating = false; + + public Compass() + { + + } + + /// <summary> + /// Formats current coordinates into JSON format + /// </summary> + /// <returns>Coordinates in JSON format</returns> + private string GetHeadingFormatted(CompassReading reading) + { + // NOTE: timestamp is generated on the JS side, to avoid issues with format conversions + string result = String.Format("\"magneticHeading\":{0},\"headingAccuracy\":{1},\"trueHeading\":{2}", + reading.MagneticHeading.ToString("0.0", CultureInfo.InvariantCulture), + reading.HeadingAccuracy.ToString("0.0", CultureInfo.InvariantCulture), + reading.TrueHeading.ToString("0.0", CultureInfo.InvariantCulture)); + return "{" + result + "}"; + } + + public void getHeading(string options) + { + if (!DeviceCompass.IsSupported) + { + DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "{code:" + Not_Supported + "}")); + } + else + { + //if (compass == null) + //{ + // // Instantiate the compass. + // compass = new DeviceCompass(); + // compass.TimeBetweenUpdates = TimeSpan.FromMilliseconds(40); + // compass.CurrentValueChanged += new EventHandler<Microsoft.Devices.Sensors.SensorReadingEventArgs<Microsoft.Devices.Sensors.CompassReading>>(compass_CurrentValueChanged); + // compass.Calibrate += new EventHandler<Microsoft.Devices.Sensors.CalibrationEventArgs>(compass_Calibrate); + //} + + + //compass.Start(); + + } + + try + { + if (currentStatus != Running) + { + lock (compass) + { + compass.CurrentValueChanged += compass_SingleHeadingValueChanged; + compass.Start(); + this.SetStatus(Starting); + } + + long timeout = 2000; + while ((currentStatus == Starting) && (timeout > 0)) + { + timeout = timeout - 100; + Thread.Sleep(100); + } + + if (currentStatus != Running) + { + DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart)); + return; + } + } + lock (compass) + { + compass.CurrentValueChanged -= compass_SingleHeadingValueChanged; + if (watchers.Count < 1) + { + compass.Stop(); + this.SetStatus(Stopped); + } + } + } + catch (UnauthorizedAccessException) + { + DispatchCommandResult(new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION, ErrorFailedToStart)); + } + catch (Exception) + { + DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ErrorFailedToStart)); + } + } + + void compass_SingleHeadingValueChanged(object sender, Microsoft.Devices.Sensors.SensorReadingEventArgs<CompassReading> e) + { + this.SetStatus(Running); + if (compass.IsDataValid) + { + // trueHeading :: The heading in degrees from 0 - 359.99 at a single moment in time. + // magneticHeading:: The heading relative to the geographic North Pole in degrees 0 - 359.99 at a single moment in time. + // A negative value indicates that the true heading could not be determined. + // headingAccuracy :: The deviation in degrees between the reported heading and the true heading. + //rawMagnetometerReading = e.SensorReading.MagnetometerReading; + + //Debug.WriteLine("Compass Result :: " + GetHeadingFormatted(e.SensorReading)); + + PluginResult result = new PluginResult(PluginResult.Status.OK, GetHeadingFormatted(e.SensorReading)); + + DispatchCommandResult(result); + } + } + + /// <summary> + /// Starts listening for compass sensor + /// </summary> + /// <returns>status of listener</returns> + private int start() + { + if ((currentStatus == Running) || (currentStatus == Starting)) + { + return currentStatus; + } + try + { + lock (compass) + { + watchers.Add(getCompassId, this); + compass.CurrentValueChanged += watchers[getCompassId].compass_CurrentValueChanged; + compass.Start(); + this.SetStatus(Starting); + } + } + catch (Exception) + { + this.SetStatus(ErrorFailedToStart); + } + return currentStatus; + } + + public void startWatch(string options) + { + if (!DeviceCompass.IsSupported) + { + DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, Not_Supported)); + } + + try + { + compassOptions = JSON.JsonHelper.Deserialize<CompassOptions>(options); + } + catch (Exception ex) + { + this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message)); + return; + } + + if (string.IsNullOrEmpty(compassOptions.Id)) + { + this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION)); + return; + } + + try + { + lock (compass) + { + watchers.Add(compassOptions.Id, this); + compass.CurrentValueChanged += watchers[compassOptions.Id].compass_CurrentValueChanged; + compass.Start(); + this.SetStatus(Starting); + } + } + catch (Exception) + { + this.DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ErrorFailedToStart)); + return; + } + } + + public void stopWatch(string options) + { + try + { + compassOptions = JSON.JsonHelper.Deserialize<CompassOptions>(options); + } + catch (Exception ex) + { + this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message)); + return; + } + + if (string.IsNullOrEmpty(compassOptions.Id)) + { + this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION)); + return; + } + + if (currentStatus != Stopped) + { + lock (compass) + { + Compass watcher = watchers[compassOptions.Id]; + compass.CurrentValueChanged -= watcher.compass_CurrentValueChanged; + watchers.Remove(compassOptions.Id); + watcher.Dispose(); + } + } + this.SetStatus(Stopped); + + this.DispatchCommandResult(); + } + + void compass_Calibrate(object sender, Microsoft.Devices.Sensors.CalibrationEventArgs e) + { + //throw new NotImplementedException(); + // TODO: pass calibration error to JS + } + + void compass_CurrentValueChanged(object sender, Microsoft.Devices.Sensors.SensorReadingEventArgs<CompassReading> e) + { + this.SetStatus(Running); + if (compass.IsDataValid) + { + // trueHeading :: The heading in degrees from 0 - 359.99 at a single moment in time. + // magneticHeading:: The heading relative to the geographic North Pole in degrees 0 - 359.99 at a single moment in time. + // A negative value indicates that the true heading could not be determined. + // headingAccuracy :: The deviation in degrees between the reported heading and the true heading. + //rawMagnetometerReading = e.SensorReading.MagnetometerReading; + + //Debug.WriteLine("Compass Result :: " + GetHeadingFormatted(e.SensorReading)); + + PluginResult result = new PluginResult(PluginResult.Status.OK, GetHeadingFormatted(e.SensorReading)); + result.KeepCallback = true; + + DispatchCommandResult(result); + } + } + + /// <summary> + /// Sets current status + /// </summary> + /// <param name="status">current status</param> + private void SetStatus(int status) + { + currentStatus = status; + } + + } +}
http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/765c8158/common-items/Plugins/Contacts.cs ---------------------------------------------------------------------- diff --git a/common-items/Plugins/Contacts.cs b/common-items/Plugins/Contacts.cs new file mode 100644 index 0000000..af78942 --- /dev/null +++ b/common-items/Plugins/Contacts.cs @@ -0,0 +1,664 @@ +/* + Licensed 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; +using System.Collections.Generic; +using System.Diagnostics; +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; } + } + + [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; + + public Contacts() + { + + } + + // 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 string[] { "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 += new EventHandler<SaveContactResult>(ContactSaveTaskCompleted); + contactTask.Show(); + } + + void ContactSaveTaskCompleted(object sender, SaveContactResult e) + { + SaveContactTask task = sender as SaveContactTask; + + if (e.TaskResult == TaskResult.OK) + { + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + DeviceContacts deviceContacts = new DeviceContacts(); + deviceContacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(postAdd_SearchCompleted); + + 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.")); + } + } + + void postAdd_SearchCompleted(object sender, ContactsSearchEventArgs e) + { + if (e.Results.Count() > 0) + { + List<Contact> foundContacts = 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, FormatJSONContact(newContact, 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 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; + } + + DeviceContacts deviceContacts = new DeviceContacts(); + deviceContacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(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) + { + ContactSearchParams searchParams = (ContactSearchParams)e.State; + + List<Contact> foundContacts = null; + + // if we have multiple search fields + if (searchParams.options.filter.Length > 0 && 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 a.EmailAddress.Contains(searchParams.options.filter) + select con); + } + if (searchParams.fields.Contains("displayName")) + { + foundContacts.AddRange(from Contact con in e.Results + where con.DisplayName.Contains(searchParams.options.filter) + select con); + } + if (searchParams.fields.Contains("name")) + { + foundContacts.AddRange(from Contact con in e.Results + where con.CompleteName != null && con.CompleteName.ToString().Contains(searchParams.options.filter) + select con); + } + if (searchParams.fields.Contains("phoneNumbers")) + { + foundContacts.AddRange(from Contact con in e.Results + from ContactPhoneNumber a in con.PhoneNumbers + where a.PhoneNumber.Contains(searchParams.options.filter) + select con); + } + if (searchParams.fields.Contains("urls")) + { + foundContacts.AddRange(from Contact con in e.Results + from string a in con.Websites + where a.Contains(searchParams.options.filter) + select con); + } + } + else + { + foundContacts = new List<Contact>(e.Results); + } + + //List<string> contactList = new List<string>(); + + string strResult = ""; + + IEnumerable<Contact> distinctContacts = foundContacts.Distinct(); + + foreach (Contact contact in distinctContacts) + { + strResult += FormatJSONContact(contact, null) + ","; + //contactList.Add(FormatJSONContact(contact, null)); + if (!searchParams.options.multiple) + { + break; // just return the first item + } + } + PluginResult result = new PluginResult(PluginResult.Status.OK); + result.Message = "[" + strResult.TrimEnd(',') + "]"; + DispatchCommandResult(result); + + } + + private string FormatJSONPhoneNumbers(Contact con) + { + string retVal = ""; + string contactFieldFormat = "\"type\":\"{0}\",\"value\":\"{1}\",\"pref\":\"false\""; + foreach (ContactPhoneNumber number in con.PhoneNumbers) + { + + string contactField = string.Format(contactFieldFormat, + number.Kind.ToString(), + number.PhoneNumber); + + retVal += "{" + contactField + "},"; + } + return retVal.TrimEnd(','); + } + + private string FormatJSONEmails(Contact con) + { + string retVal = ""; + string contactFieldFormat = "\"type\":\"{0}\",\"value\":\"{1}\",\"pref\":\"false\""; + foreach (ContactEmailAddress address in con.EmailAddresses) + { + string contactField = string.Format(contactFieldFormat, + address.Kind.ToString(), + address.EmailAddress); + + retVal += "{" + contactField + "},"; + } + return retVal.TrimEnd(','); + } + + private string getFormattedJSONAddress(ContactAddress address, bool isPrefered) + { + + string addressFormatString = "\"pref\":{0}," + // bool + "\"type\":\"{1}\"," + + "\"formatted\":\"{2}\"," + + "\"streetAddress\":\"{3}\"," + + "\"locality\":\"{4}\"," + + "\"region\":\"{5}\"," + + "\"postalCode\":\"{6}\"," + + "\"country\":\"{7}\""; + + string formattedAddress = address.PhysicalAddress.AddressLine1 + " " + + address.PhysicalAddress.AddressLine2 + " " + + address.PhysicalAddress.City + " " + + address.PhysicalAddress.StateProvince + " " + + address.PhysicalAddress.CountryRegion + " " + + address.PhysicalAddress.PostalCode; + + string jsonAddress = string.Format(addressFormatString, + isPrefered ? "\"true\"" : "\"false\"", + address.Kind.ToString(), + formattedAddress, + address.PhysicalAddress.AddressLine1 + " " + address.PhysicalAddress.AddressLine2, + address.PhysicalAddress.City, + address.PhysicalAddress.StateProvince, + address.PhysicalAddress.PostalCode, + address.PhysicalAddress.CountryRegion); + + //Debug.WriteLine("getFormattedJSONAddress returning :: " + jsonAddress); + + return "{" + jsonAddress + "}"; + } + + private string FormatJSONAddresses(Contact con) + { + string retVal = ""; + foreach (ContactAddress address in con.Addresses) + { + retVal += this.getFormattedJSONAddress(address, false) + ","; + } + + //Debug.WriteLine("FormatJSONAddresses returning :: " + retVal); + return retVal.TrimEnd(','); + } + + private string FormatJSONWebsites(Contact con) + { + string retVal = ""; + foreach (string website in con.Websites) + { + retVal += "\"" + website + "\","; + } + return retVal.TrimEnd(','); + } + + /* + * formatted: The complete name of the contact. (DOMString) + familyName: The contacts family name. (DOMString) + givenName: The contacts given name. (DOMString) + middleName: The contacts middle name. (DOMString) + honorificPrefix: The contacts prefix (example Mr. or Dr.) (DOMString) + honorificSuffix: The contacts suffix (example Esq.). (DOMString) + */ + private string FormatJSONName(Contact con) + { + string retVal = ""; + string formatStr = "\"formatted\":\"{0}\"," + + "\"familyName\":\"{1}\"," + + "\"givenName\":\"{2}\"," + + "\"middleName\":\"{3}\"," + + "\"honorificPrefix\":\"{4}\"," + + "\"honorificSuffix\":\"{5}\""; + + if (con.CompleteName != null) + { + retVal = string.Format(formatStr, + con.CompleteName.FirstName + " " + con.CompleteName.LastName, // TODO: does this need suffix? middlename? + con.CompleteName.LastName, + con.CompleteName.FirstName, + con.CompleteName.MiddleName, + con.CompleteName.Title, + con.CompleteName.Suffix); + } + else + { + retVal = string.Format(formatStr,"","","","","",""); + } + + return "{" + retVal + "}"; + } + + private string FormatJSONContact(Contact con, string[] fields) + { + + string contactFormatStr = "\"id\":\"{0}\"," + + "\"displayName\":\"{1}\"," + + "\"nickname\":\"{2}\"," + + "\"phoneNumbers\":[{3}]," + + "\"emails\":[{4}]," + + "\"addresses\":[{5}]," + + "\"urls\":[{6}]," + + "\"name\":{7}," + + "\"note\":\"{8}\"," + + "\"birthday\":\"{9}\""; + + + string jsonContact = String.Format(contactFormatStr, + con.GetHashCode(), + con.DisplayName, + con.CompleteName != null ? con.CompleteName.Nickname : "", + FormatJSONPhoneNumbers(con), + FormatJSONEmails(con), + FormatJSONAddresses(con), + FormatJSONWebsites(con), + FormatJSONName(con), + con.Notes.FirstOrDefault(), + con.Birthdays.FirstOrDefault()); + + //Debug.WriteLine("jsonContact = " + jsonContact); + // JSON requires new line characters be escaped + return "{" + jsonContact.Replace("\n", "\\n") + "}"; + } + } +} http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/765c8158/common-items/Plugins/DebugConsole.cs ---------------------------------------------------------------------- diff --git a/common-items/Plugins/DebugConsole.cs b/common-items/Plugins/DebugConsole.cs new file mode 100644 index 0000000..fa9863a --- /dev/null +++ b/common-items/Plugins/DebugConsole.cs @@ -0,0 +1,49 @@ +/* + Licensed 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 System; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Ink; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; +using System.Diagnostics; + +namespace WPCordovaClassLib.Cordova.Commands +{ + + public class DebugConsole : BaseCommand + { + // warn, error + public void log(string msg) + { + Debug.WriteLine("Log:" + msg); + } + + public void error(string msg) + { + Debug.WriteLine("Error:" + msg); + } + + public void warn(string msg) + { + Debug.WriteLine("Warn:" + msg); + } + + } +} http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/765c8158/common-items/Plugins/Device.cs ---------------------------------------------------------------------- diff --git a/common-items/Plugins/Device.cs b/common-items/Plugins/Device.cs new file mode 100644 index 0000000..8abb4ff --- /dev/null +++ b/common-items/Plugins/Device.cs @@ -0,0 +1,135 @@ +/* + Licensed 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 System; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Ink; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; +using Microsoft.Phone.Info; +using System.IO.IsolatedStorage; +using System.Windows.Resources; +using System.IO; +using System.Diagnostics; + +namespace WPCordovaClassLib.Cordova.Commands +{ + public class Device : BaseCommand + { + public void getDeviceInfo(string notused) + { + + string res = String.Format("\"name\":\"{0}\",\"cordova\":\"{1}\",\"platform\":\"{2}\",\"uuid\":\"{3}\",\"version\":\"{4}\",\"model\":\"{5}\"", + this.name, + this.cordova, + this.platform, + this.uuid, + this.version, + this.model); + + + + res = "{" + res + "}"; + //Debug.WriteLine("Result::" + res); + DispatchCommandResult(new PluginResult(PluginResult.Status.OK, res)); + } + + public string model + { + get + { + return DeviceStatus.DeviceName; + //return String.Format("{0},{1},{2}", DeviceStatus.DeviceManufacturer, DeviceStatus.DeviceHardwareVersion, DeviceStatus.DeviceFirmwareVersion); + } + } + + public string name + { + get + { + return DeviceStatus.DeviceName; + + } + } + + public string cordova + { + get + { + // TODO: should be able to dynamically read the Cordova version from somewhere... + return "0.0.0"; + } + } + + public string platform + { + get + { + return Environment.OSVersion.Platform.ToString(); + } + } + + public string uuid + { + get + { + string returnVal = ""; + object id; + UserExtendedProperties.TryGetValue("ANID", out id); + + if (id != null) + { + returnVal = id.ToString().Substring(2, 32); + } + else + { + returnVal = "???unknown???"; + + using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication()) + { + try + { + IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream("DeviceID.txt", FileMode.Open, FileAccess.Read, appStorage); + + using (StreamReader reader = new StreamReader(fileStream)) + { + returnVal = reader.ReadLine(); + } + } + catch (Exception /*ex*/) + { + + } + } + } + + return returnVal; + } + } + + public string version + { + get + { + return Environment.OSVersion.Version.ToString(); + } + } + + } +}
