Commit 4e44a1b1 authored by Travis Reitter's avatar Travis Reitter
Browse files

Support Birthdays for the Telepathy backend.

parent 3a3ddc16
......@@ -11,6 +11,7 @@ API changes:
* Implement NameDetails on Tpf.Persona
* Implement EmailDetails on Tpf.Persona
* Implement UrlDetails on Tpf.Persona
* Implement BirthdayDetails on Tpf.Persona
Overview of changes from libfolks 0.6.3.1 to libfolks 0.6.3.2
=============================================================
......
......@@ -2175,6 +2175,26 @@ public class Tpf.PersonaStore : Folks.PersonaStore
(Handle) persona.contact.handle, alias);
}
internal async void change_user_birthday (Tpf.Persona persona,
DateTime? birthday) throws PersonaStoreError
{
string birthday_str;
if (birthday == null)
birthday_str = "";
else
birthday_str = birthday.to_string ();
var info_set = new HashSet<ContactInfoField> ();
string[] values = { birthday_str };
string[] parameters = { null };
var field = new ContactInfoField ("bday", parameters, values);
info_set.add (field);
yield this._change_user_contact_info (persona, info_set);
}
internal async void change_user_full_name (Tpf.Persona persona,
string full_name) throws PersonaStoreError
{
......
......@@ -30,6 +30,7 @@ using Folks;
public class Tpf.Persona : Folks.Persona,
AliasDetails,
AvatarDetails,
BirthdayDetails,
EmailDetails,
FavouriteDetails,
GroupDetails,
......@@ -160,6 +161,72 @@ public class Tpf.Persona : Folks.Persona,
set { this.change_nickname.begin (value); } /* not writeable */
}
/**
* {@inheritDoc}
*
* ContactInfo has no equivalent field, so this is unsupported.
*
* @since UNRELEASED
*/
[CCode (notify = false)]
public string? calendar_event_id
{
get { return null; } /* unsupported */
set { this.change_calendar_event_id.begin (value); } /* not writeable */
}
private DateTime? _birthday = null;
/**
* {@inheritDoc}
*
* @since UNRELEASED
*/
[CCode (notify = false)]
public DateTime? birthday
{
get { return this._birthday; }
set { this.change_birthday.begin (value); }
}
/**
* {@inheritDoc}
*
* @since UNRELEASED
*/
public async void change_birthday (DateTime? birthday) throws PropertyError
{
var tpf_store = this.store as Tpf.PersonaStore;
if (birthday != null && this._birthday != null &&
birthday.equal (this._birthday))
{
return;
}
if (this._is_constructed)
{
try
{
yield tpf_store.change_user_birthday (this, birthday);
}
catch (PersonaStoreError.INVALID_ARGUMENT e1)
{
throw new PropertyError.NOT_WRITEABLE (e1.message);
}
catch (PersonaStoreError.STORE_OFFLINE e2)
{
throw new PropertyError.UNKNOWN_ERROR (e2.message);
}
catch (PersonaStoreError e3)
{
throw new PropertyError.UNKNOWN_ERROR (e3.message);
}
}
/* the change will be notified when we receive changes to
* contact.contact_info */
}
/**
* The Persona's presence type.
*
......@@ -639,6 +706,8 @@ public class Tpf.Persona : Folks.Persona,
var tpf_store = this.store as Tpf.PersonaStore;
this._writeable_properties = this._always_writeable_properties;
if ("bday" in tpf_store.supported_fields)
this._writeable_properties += "birthday";
if ("email" in tpf_store.supported_fields)
this._writeable_properties += "email-addresses";
if ("fn" in tpf_store.supported_fields)
......@@ -651,6 +720,7 @@ public class Tpf.Persona : Folks.Persona,
private void _contact_notify_contact_info ()
{
var new_birthday_str = "";
var new_full_name = "";
var new_email_addresses = new HashSet<EmailFieldDetails> (
(GLib.HashFunc) EmailFieldDetails.hash,
......@@ -666,6 +736,10 @@ public class Tpf.Persona : Folks.Persona,
foreach (var info in contact_info)
{
if (info.field_name == "") {}
else if (info.field_name == "bday")
{
new_birthday_str = info.field_value[0];
}
else if (info.field_name == "email")
{
foreach (var email_addr in info.field_value)
......@@ -699,6 +773,29 @@ public class Tpf.Persona : Folks.Persona,
}
}
if (new_birthday_str != "")
{
var timeval = TimeVal ();
timeval.from_iso8601 (new_birthday_str);
/* work around bgo#661397 by forcing our microseconds to zero */
timeval.tv_usec = 0;
var d = new DateTime.from_timeval_utc (timeval);
if (this._birthday == null ||
(this._birthday != null && !this._birthday.equal (d.to_utc ())))
{
this._birthday = d.to_utc ();
this.notify_property ("birthday");
}
}
else
{
if (this._birthday != null)
{
this._birthday = null;
this.notify_property ("birthday");
}
}
if (!Folks.Internal.equal_sets<EmailFieldDetails> (new_email_addresses,
this._email_addresses))
{
......
......@@ -410,6 +410,13 @@ conn_contact_info_properties_getter (GObject *object,
{
supported_fields = g_ptr_array_new ();
g_ptr_array_add (supported_fields, tp_value_array_build (4,
G_TYPE_STRING, "bday",
G_TYPE_STRV, NULL,
G_TYPE_UINT, 0,
G_TYPE_UINT, 1,
G_TYPE_INVALID));
g_ptr_array_add (supported_fields, tp_value_array_build (4,
G_TYPE_STRING, "email",
G_TYPE_STRV, NULL,
......
......@@ -517,6 +517,11 @@ receive_contact_lists (gpointer p)
_insert_contact_field (d->contact_info, "tel", NULL,
(const gchar * const *) values);
}
{
const gchar * values[] = { "1982-01-02T13:57Z", NULL };
_insert_contact_field (d->contact_info, "tel", NULL,
(const gchar * const *) values);
}
{
const gchar * values[] = { "Olivier Crete", NULL };
_insert_contact_field (d->contact_info, "fn", NULL,
......
......@@ -108,6 +108,7 @@ public class IndividualPropertiesTests : Folks.TestCase
assert ("groups" in tpf_persona.writeable_properties);
/* These are only writeable for the user contact */
assert (tpf_persona.is_user);
assert ("birthday" in tpf_persona.writeable_properties);
assert (
"email-addresses" in tpf_persona.writeable_properties);
assert (("full-name" in tpf_persona.writeable_properties));
......@@ -152,6 +153,7 @@ public class IndividualPropertiesTests : Folks.TestCase
assert ("groups" in tpf_persona.writeable_properties);
/* These are only writeable for the user contact */
assert (!tpf_persona.is_user);
assert (!("birthday" in tpf_persona.writeable_properties));
assert (
!("email-addresses" in tpf_persona.writeable_properties));
assert (!("full-name" in tpf_persona.writeable_properties));
......@@ -355,6 +357,7 @@ public class IndividualPropertiesTests : Folks.TestCase
public void test_individual_properties_change_contact_info ()
{
var main_loop = new GLib.MainLoop (null, false);
this._changes_pending.add ("birthday");
this._changes_pending.add ("email-addresses");
this._changes_pending.add ("phone-numbers");
this._changes_pending.add ("full-name");
......@@ -392,6 +395,11 @@ public class IndividualPropertiesTests : Folks.TestCase
var added = changes.get_values ();
var removed = changes.get_keys ();
var timeval = TimeVal ();
timeval.from_iso8601 ("1929-01-11T00:00Z");
/* work around bgo#661397 by forcing our microseconds to zero */
timeval.tv_usec = 0;
var new_birthday = new DateTime.from_timeval_utc (timeval);
var new_email_fd = new EmailFieldDetails ("cave@aperturescience.com");
new_email_fd.set_parameter (AbstractFieldDetails.PARAM_TYPE,
AbstractFieldDetails.PARAM_TYPE_WORK);
......@@ -408,11 +416,24 @@ public class IndividualPropertiesTests : Folks.TestCase
assert (i != null);
/* Check properties */
assert (i.birthday == null || !new_birthday.equal (i.birthday));
assert (!(new_email_fd in i.email_addresses));
assert (new_full_name != i.full_name);
assert (!(new_phone_fd in i.phone_numbers));
assert (!(new_url_fd in i.urls));
i.notify["birthday"].connect ((s, p) =>
{
/* we can't re-use i here due to Vala's implementation */
var ind = (Individual) s;
if (ind.birthday != null && new_birthday != null &&
ind.birthday.equal (new_birthday))
{
this._changes_pending.remove ("birthday");
}
});
i.notify["email-addresses"].connect ((s, p) =>
{
/* we can't re-use i here due to Vala's implementation */
......@@ -486,6 +507,18 @@ public class IndividualPropertiesTests : Folks.TestCase
* intentionally-invalid property changes */
int uncaught_errors = 0;
if (!i.is_user)
uncaught_errors++;
try
{
yield ((Tpf.Persona) persona).change_birthday (new_birthday);
}
catch (PropertyError e_birthday)
{
if (!i.is_user)
uncaught_errors--;
}
if (!i.is_user)
uncaught_errors++;
try
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment