summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Kramlich <grim@reaperworld.com>2023-03-21 02:36:13 -0500
committerGary Kramlich <grim@reaperworld.com>2023-03-21 02:36:13 -0500
commit26eb56e7957480a4d6a506cf9250d092b924f6f6 (patch)
tree161c1c14a6cca5330cec44fe01ab43fa928fe0ce
parent6bd051f03a0450bd1f7db83796381773ae148eff (diff)
downloadpidgin-26eb56e7957480a4d6a506cf9250d092b924f6f6.tar.gz
Add "new-status" properties to PurplePresence with fallbacks were applicable
This adds the new `emoji` and `mobile` properties to `PurplePresence`. It also makes `message` read/write and it fallsback to the active status's message if the internal message is false. Additionally the primitive property was moved `PurpleStatusPrimitive` to `PurplePresencePrimitive`. Testing Done: Ran the updated unit tests and connected a demo account and verified that the expected status messages were displayed. Reviewed at https://reviews.imfreedom.org/r/2372/
-rw-r--r--libpurple/purplepresence.c164
-rw-r--r--libpurple/purplepresence.h73
-rw-r--r--libpurple/tests/test_presence.c114
3 files changed, 284 insertions, 67 deletions
diff --git a/libpurple/purplepresence.c b/libpurple/purplepresence.c
index e31b8a6412..0182e54760 100644
--- a/libpurple/purplepresence.c
+++ b/libpurple/purplepresence.c
@@ -36,6 +36,11 @@ typedef struct {
GHashTable *status_table;
PurpleStatus *active_status;
+
+ PurplePresencePrimitive primitive;
+ char *message;
+ char *emoji;
+ gboolean mobile;
} PurplePresencePrivate;
enum {
@@ -46,6 +51,8 @@ enum {
PROP_ACTIVE_STATUS,
PROP_PRIMITIVE,
PROP_MESSAGE,
+ PROP_EMOJI,
+ PROP_MOBILE,
N_PROPERTIES
};
static GParamSpec *properties[N_PROPERTIES];
@@ -98,6 +105,18 @@ purple_presence_set_property(GObject *obj, guint param_id, const GValue *value,
purple_presence_set_active_status(presence,
g_value_get_object(value));
break;
+ case PROP_PRIMITIVE:
+ purple_presence_set_primitive(presence, g_value_get_enum(value));
+ break;
+ case PROP_MESSAGE:
+ purple_presence_set_message(presence, g_value_get_string(value));
+ break;
+ case PROP_EMOJI:
+ purple_presence_set_emoji(presence, g_value_get_string(value));
+ break;
+ case PROP_MOBILE:
+ purple_presence_set_mobile(presence, g_value_get_boolean(value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
break;
@@ -129,6 +148,12 @@ purple_presence_get_property(GObject *obj, guint param_id, GValue *value,
case PROP_MESSAGE:
g_value_set_string(value, purple_presence_get_message(presence));
break;
+ case PROP_EMOJI:
+ g_value_set_string(value, purple_presence_get_emoji(presence));
+ break;
+ case PROP_MOBILE:
+ g_value_set_boolean(value, purple_presence_get_mobile(presence));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
break;
@@ -157,6 +182,9 @@ purple_presence_finalize(GObject *obj) {
g_clear_pointer(&priv->idle_time, g_date_time_unref);
g_clear_pointer(&priv->login_time, g_date_time_unref);
+ g_clear_pointer(&priv->message, g_free);
+ g_clear_pointer(&priv->emoji, g_free);
+
G_OBJECT_CLASS(purple_presence_parent_class)->finalize(obj);
}
@@ -219,9 +247,9 @@ purple_presence_class_init(PurplePresenceClass *klass) {
properties[PROP_PRIMITIVE] = g_param_spec_enum(
"primitive", "primitive",
"The primitive for the presence",
- PURPLE_TYPE_STATUS_PRIMITIVE,
- PURPLE_STATUS_UNSET,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ PURPLE_TYPE_PRESENCE_PRIMITIVE,
+ PURPLE_PRESENCE_PRIMITIVE_OFFLINE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* PurplePresence:message:
@@ -234,7 +262,33 @@ purple_presence_class_init(PurplePresenceClass *klass) {
"message", "message",
"The status message",
NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurplePresence:emoji:
+ *
+ * The emoji or mood of the presence.
+ *
+ * Since: 3.0.0
+ */
+ properties[PROP_EMOJI] = g_param_spec_string(
+ "emoji", "emoji",
+ "The emoji for the presence.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurplePresence:mobile:
+ *
+ * Whether or not the presence is on a mobile device.
+ *
+ * Since: 3.0.0
+ */
+ properties[PROP_MOBILE] = g_param_spec_boolean(
+ "mobile", "mobile",
+ "Whether or not the presence is on a mobile device.",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
}
@@ -557,21 +611,34 @@ purple_presence_compare(PurplePresence *presence1, PurplePresence *presence2) {
return 0;
}
-PurpleStatusPrimitive
+PurplePresencePrimitive
purple_presence_get_primitive(PurplePresence *presence) {
PurplePresencePrivate *priv = NULL;
- PurpleStatusType *type = NULL;
- g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), PURPLE_STATUS_UNSET);
+ g_return_val_if_fail(PURPLE_IS_PRESENCE(presence),
+ PURPLE_PRESENCE_PRIMITIVE_OFFLINE);
priv = purple_presence_get_instance_private(presence);
- type = purple_status_get_status_type(priv->active_status);
- if(type != NULL) {
- return purple_status_type_get_primitive(type);
- }
+ return priv->primitive;
+}
+
+void
+purple_presence_set_primitive(PurplePresence *presence,
+ PurplePresencePrimitive primitive)
+{
+ PurplePresencePrivate *priv = NULL;
+
+ g_return_if_fail(PURPLE_IS_PRESENCE(presence));
- return PURPLE_STATUS_UNSET;
+ priv = purple_presence_get_instance_private(presence);
+
+ if(priv->primitive != primitive) {
+ priv->primitive = primitive;
+
+ g_object_notify_by_pspec(G_OBJECT(presence),
+ properties[PROP_PRIMITIVE]);
+ }
}
const char *
@@ -582,9 +649,82 @@ purple_presence_get_message(PurplePresence *presence) {
priv = purple_presence_get_instance_private(presence);
+ if(priv->message != NULL) {
+ return priv->message;
+ }
+
return purple_status_get_attr_string(priv->active_status, "message");
}
+void
+purple_presence_set_message(PurplePresence *presence, const char *message) {
+ PurplePresencePrivate *priv = NULL;
+
+ g_return_if_fail(PURPLE_IS_PRESENCE(presence));
+
+ priv = purple_presence_get_instance_private(presence);
+
+ if(!purple_strequal(priv->message, message)) {
+ g_free(priv->message);
+ priv->message = g_strdup(message);
+
+ g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_MESSAGE]);
+ }
+}
+
+const char *
+purple_presence_get_emoji(PurplePresence *presence) {
+ PurplePresencePrivate *priv = NULL;
+
+ g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL);
+
+ priv = purple_presence_get_instance_private(presence);
+
+ return priv->emoji;
+}
+
+void
+purple_presence_set_emoji(PurplePresence *presence, const char *emoji) {
+ PurplePresencePrivate *priv = NULL;
+
+ g_return_if_fail(PURPLE_IS_PRESENCE(presence));
+
+ priv = purple_presence_get_instance_private(presence);
+
+ if(!purple_strequal(priv->emoji, emoji)) {
+ g_free(priv->emoji);
+ priv->emoji = g_strdup(emoji);
+
+ g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_EMOJI]);
+ }
+}
+
+gboolean
+purple_presence_get_mobile(PurplePresence *presence) {
+ PurplePresencePrivate *priv = NULL;
+
+ g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
+
+ priv = purple_presence_get_instance_private(presence);
+
+ return priv->mobile;
+}
+
+void
+purple_presence_set_mobile(PurplePresence *presence, gboolean mobile) {
+ PurplePresencePrivate *priv = NULL;
+
+ g_return_if_fail(PURPLE_IS_PRESENCE(presence));
+
+ priv = purple_presence_get_instance_private(presence);
+
+ if(priv->mobile != mobile) {
+ priv->mobile = mobile;
+
+ g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_MOBILE]);
+ }
+}
+
const char *
purple_presence_primitive_to_string(PurplePresencePrimitive primitive) {
switch(primitive) {
diff --git a/libpurple/purplepresence.h b/libpurple/purplepresence.h
index 8e012fed16..09512343d5 100644
--- a/libpurple/purplepresence.h
+++ b/libpurple/purplepresence.h
@@ -298,13 +298,24 @@ gint purple_presence_compare(PurplePresence *presence1, PurplePresence *presence
* purple_presence_get_primitive:
* @presence: The instance.
*
- * Gets the [enum@Purple.StatusPrimitive] for @presence.
+ * Gets the [enum@Purple.PresencePrimitive] for @presence.
*
* Returns: The current primitive.
*
* Since: 3.0.0
*/
-PurpleStatusPrimitive purple_presence_get_primitive(PurplePresence *presence);
+PurplePresencePrimitive purple_presence_get_primitive(PurplePresence *presence);
+
+/**
+ * purple_presence_set_primitive:
+ * @presence: The instance.
+ * @primitive: The new primitive.
+ *
+ * Sets the [enum@Purple.StatusPrimitive] for @presence to @primitive.
+ *
+ * Since: 3.0.0
+ */
+void purple_presence_set_primitive(PurplePresence *presence, PurplePresencePrimitive primitive);
/**
* purple_presence_get_message:
@@ -319,6 +330,64 @@ PurpleStatusPrimitive purple_presence_get_primitive(PurplePresence *presence);
const char *purple_presence_get_message(PurplePresence *presence);
/**
+ * purple_presence_set_message:
+ * @presence: The instance.
+ * @message: (nullable): The new message.
+ *
+ * Sets the status message of @presence to @message.
+ *
+ * Since: 3.0.0
+ */
+void purple_presence_set_message(PurplePresence *presence, const char *message);
+
+/**
+ * purple_presence_get_emoji:
+ * @presence: The instance.
+ *
+ * Gets the current emoji, sometimes referred to as a mood, of @presence.
+ *
+ * Returns: The current emoji or %NULL if none is set.
+ *
+ * Since: 3.0.0
+ */
+const char *purple_presence_get_emoji(PurplePresence *presence);
+
+/**
+ * purple_presence_set_emoji:
+ * @presence: The instance.
+ * @emoji: (nullable): The new emoji to set.
+ *
+ * Sets the current emoji, sometimes referred to as a mood, of @presence to
+ * @emoji.
+ *
+ * Since: 3.0.0
+ */
+void purple_presence_set_emoji(PurplePresence *presence, const char *emoji);
+
+/**
+ * purple_presence_get_mobile:
+ * @presence: The instance.
+ *
+ * Gets whether or not @presence is on a mobile device.
+ *
+ * Returns: %TRUE if @presence is on a mobile device, otherwise %FALSE.
+ *
+ * Since: 3.0.0
+ */
+gboolean purple_presence_get_mobile(PurplePresence *presence);
+
+/**
+ * purple_presence_set_mobile:
+ * @presence: The instance.
+ * @mobile: The new mobile status.
+ *
+ * Sets whether or not @presence is on a mobile device.
+ *
+ * Since: 3.0.0
+ */
+void purple_presence_set_mobile(PurplePresence *presence, gboolean mobile);
+
+/**
* purple_presence_primitive_to_string:
* @primitive: The [enum@Purple.PresencePrimitive] value.
*
diff --git a/libpurple/tests/test_presence.c b/libpurple/tests/test_presence.c
index b1e237efc6..d376f919d4 100644
--- a/libpurple/tests/test_presence.c
+++ b/libpurple/tests/test_presence.c
@@ -24,65 +24,79 @@
* Main
*****************************************************************************/
static void
-test_purple_presence_migrate_online_without_message(void) {
+test_purple_presence_new(void) {
PurplePresence *presence = NULL;
- PurpleStatus *status = NULL;
- PurpleStatusType *type = NULL;
- type = purple_status_type_new(PURPLE_STATUS_AVAILABLE,
- "online", "online", TRUE);
presence = purple_presence_new();
- status = purple_status_new(type, presence);
-
- purple_status_set_active(status, TRUE);
-
- /* Now verify that the presence returns the correct values for the
- * properties.
- */
- g_assert_cmpint(purple_presence_get_primitive(presence), ==,
- PURPLE_STATUS_AVAILABLE);
- g_assert_null(purple_presence_get_message(presence));
+ g_assert_true(PURPLE_IS_PRESENCE(presence));
/* Cleanup. */
g_clear_object(&presence);
- g_clear_object(&status);
- g_clear_pointer(&type, purple_status_type_destroy);
}
static void
-test_purple_presence_migrate_online_with_message(void) {
+test_purple_presence_properties(void) {
PurplePresence *presence = NULL;
- PurpleStatus *status = NULL;
- PurpleStatusType *type = NULL;
- GHashTable *attrs = NULL;
-
- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
- "online", "online",
- FALSE, TRUE, TRUE,
- "message", "message",
- purple_value_new(G_TYPE_STRING),
- NULL);
- presence = purple_presence_new();
-
- status = purple_status_new(type, presence);
-
- attrs = g_hash_table_new(g_str_hash, g_str_equal);
- g_hash_table_insert(attrs, "message", "Greetings Programs!");
- purple_status_set_active_with_attributes(status, TRUE, attrs);
- g_hash_table_destroy(attrs);
-
- /* Now verify that the presence returns the correct values for the
- * properties.
+ PurplePresencePrimitive primitive = PURPLE_PRESENCE_PRIMITIVE_OFFLINE;
+ GDateTime *now = NULL;
+ GDateTime *login = NULL;
+ GDateTime *login1 = NULL;
+ GDateTime *idle = NULL;
+ GDateTime *idle1 = NULL;
+ char *message = NULL;
+ char *emoji = NULL;
+ gboolean mobile = FALSE;
+
+ /* Create the login and idle times. */
+ now = g_date_time_new_now_utc();
+ login = g_date_time_add_hours(now, -1);
+ idle = g_date_time_add_minutes(now, -10);
+ g_clear_pointer(&now, g_date_time_unref);
+
+ /* Create the presence using g_object_new to make sure set_property is
+ * wired up correctly.
*/
- g_assert_cmpint(purple_presence_get_primitive(presence), ==,
- PURPLE_STATUS_AVAILABLE);
- g_assert_cmpstr(purple_presence_get_message(presence), ==,
- "Greetings Programs!");
+ presence = g_object_new(
+ PURPLE_TYPE_PRESENCE,
+ "primitive", PURPLE_PRESENCE_PRIMITIVE_AVAILABLE,
+ "message", "I'll be back!",
+ "emoji", "🤖",
+ "login-time", login,
+ "idle-time", idle,
+ "mobile", TRUE,
+ NULL);
+
+ /* Grab the values via g_object_get to make sure get_property is wired up
+ * correctly.
+ */
+ g_object_get(
+ presence,
+ "primitive", &primitive,
+ "message", &message,
+ "emoji", &emoji,
+ "login-time", &login1,
+ "idle-time", &idle1,
+ "mobile", &mobile,
+ NULL);
+
+ /* Validate! */
+ g_assert_cmpint(primitive, ==, PURPLE_PRESENCE_PRIMITIVE_AVAILABLE);
+ g_assert_cmpstr(message, ==, "I'll be back!");
+ g_assert_cmpstr(emoji, ==, "🤖");
+ g_assert_nonnull(login1);
+ g_assert_true(g_date_time_equal(login, login1));
+ g_assert_nonnull(idle1);
+ g_assert_true(g_date_time_equal(idle, idle1));
+ g_assert_true(mobile);
/* Cleanup. */
+ g_clear_pointer(&message, g_free);
+ g_clear_pointer(&emoji, g_free);
+ g_clear_pointer(&login, g_date_time_unref);
+ g_clear_pointer(&login1, g_date_time_unref);
+ g_clear_pointer(&idle, g_date_time_unref);
+ g_clear_pointer(&idle1, g_date_time_unref);
g_clear_object(&presence);
- g_clear_object(&status);
- g_clear_pointer(&type, purple_status_type_destroy);
}
/******************************************************************************
@@ -92,14 +106,8 @@ gint
main(gint argc, gchar *argv[]) {
g_test_init(&argc, &argv, NULL);
- /* This tests verify that PurplePresence is properly notifying of property
- * changes with the 2.x.y and earlier status back end. When PurplePresence
- * has replaced that back end, these tests should be removed as well.
- */
- g_test_add_func("/presence/migrate/online-without-message",
- test_purple_presence_migrate_online_without_message);
- g_test_add_func("/presence/migrate/online-with-message",
- test_purple_presence_migrate_online_with_message);
+ g_test_add_func("/presence/new", test_purple_presence_new);
+ g_test_add_func("/presence/properties", test_purple_presence_properties);
return g_test_run();
}