Wed, 08 May 2024 03:37:46 -0500
Automatically generate titles for DMs and GroupDMs
This is one of the steps in removing PurpleConversation:name. This required a
but of tinkering with property flags and freezing the property notification,
but I think it's all good.
Testing Done:
Ran the turtles, ran the tests under valgrind, and opened conversations with the demo protocol plugin and sent some messages.
Reviewed at https://reviews.imfreedom.org/r/3158/
--- a/ChangeLog.API Tue May 07 23:06:04 2024 -0500 +++ b/ChangeLog.API Wed May 08 03:37:46 2024 -0500 @@ -503,6 +503,7 @@ * PurpleConversationType * purple_conversation::conversation-switched signal * purple_conversation_add_smiley + * purple_conversation_autoset_title * purple_conversation_clear_message_history * purple_conversation_close_logs * purple_conversation_do_command
--- a/libpurple/purpleconversation.c Tue May 07 23:06:04 2024 -0500 +++ b/libpurple/purpleconversation.c Wed May 08 03:37:46 2024 -0500 @@ -47,6 +47,7 @@ PurpleAvatar *avatar; char *name; char *title; + gboolean title_generated; PurpleConnectionFlags features; @@ -75,6 +76,7 @@ PROP_AVATAR, PROP_NAME, PROP_TITLE, + PROP_TITLE_GENERATED, PROP_FEATURES, PROP_AGE_RESTRICTED, PROP_DESCRIPTION, @@ -112,6 +114,41 @@ * Helpers **************************************************************************/ static void +purple_conversation_set_title_generated(PurpleConversation *conversation, + gboolean title_generated) +{ + g_return_if_fail(PURPLE_IS_CONVERSATION(conversation)); + + /* If conversation isn't a dm or group dm, and title_generated is being set + * to %TRUE exit immediately because generating the title is only allowed + * on DMs and GroupDMs. + */ + if(conversation->type != PURPLE_CONVERSATION_TYPE_DM && + conversation->type != PURPLE_CONVERSATION_TYPE_GROUP_DM && + title_generated) + { + return; + } + + if(conversation->title_generated != title_generated) { + GObject *obj = G_OBJECT(conversation); + + conversation->title_generated = title_generated; + + g_object_freeze_notify(obj); + + if(conversation->title_generated) { + purple_conversation_generate_title(conversation); + } + + g_object_notify_by_pspec(G_OBJECT(conversation), + properties[PROP_TITLE_GENERATED]); + + g_object_thaw_notify(obj); + } +} + +static void purple_conversation_set_id(PurpleConversation *conversation, const char *id) { g_return_if_fail(PURPLE_IS_CONVERSATION(conversation)); @@ -157,6 +194,20 @@ } static void +purple_conversation_set_conversation_type(PurpleConversation *conversation, + PurpleConversationType type) +{ + g_return_if_fail(PURPLE_IS_CONVERSATION(conversation)); + + if(type != conversation->type) { + conversation->type = type; + + g_object_notify_by_pspec(G_OBJECT(conversation), + properties[PROP_TYPE]); + } +} + +static void purple_conversation_set_federated(PurpleConversation *conversation, gboolean federated) { @@ -353,6 +404,18 @@ * Callbacks **************************************************************************/ static void +purple_conversation_member_name_changed_cb(G_GNUC_UNUSED GObject *source, + G_GNUC_UNUSED GParamSpec *pspec, + gpointer data) +{ + PurpleConversation *conversation = data; + + if(purple_conversation_get_title_generated(conversation)) { + purple_conversation_generate_title(conversation); + } +} + +static void purple_conversation_account_connected_cb(GObject *obj, G_GNUC_UNUSED GParamSpec *pspec, gpointer data) @@ -485,6 +548,10 @@ case PROP_TITLE: g_value_set_string(value, purple_conversation_get_title(conversation)); break; + case PROP_TITLE_GENERATED: + g_value_set_boolean(value, + purple_conversation_get_title_generated(conversation)); + break; case PROP_FEATURES: g_value_set_flags(value, purple_conversation_get_features(conversation)); @@ -564,6 +631,17 @@ G_OBJECT_CLASS(purple_conversation_parent_class)->constructed(object); + if(purple_strempty(conversation->title)) { + if(conversation->type == PURPLE_CONVERSATION_TYPE_DM || + conversation->type == PURPLE_CONVERSATION_TYPE_GROUP_DM) + { + /* There's no way to add members during construction, so just call + * set_title_generated. + */ + purple_conversation_set_title_generated(conversation, TRUE); + } + } + g_object_get(object, "account", &account, NULL); gc = purple_account_get_connection(account); @@ -575,9 +653,6 @@ purple_connection_get_flags(gc)); } - /* Auto-set the title. */ - purple_conversation_autoset_title(conversation); - g_object_unref(account); } @@ -648,7 +723,7 @@ "The type of the conversation.", PURPLE_TYPE_CONVERSATION_TYPE, PURPLE_CONVERSATION_TYPE_UNSET, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** * PurpleConversation:account: @@ -690,7 +765,7 @@ "name", "Name", "The name of the conversation.", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * PurpleConversation:title: @@ -703,7 +778,27 @@ "title", "Title", "The title of the conversation.", NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + /** + * PurpleConversation:title-generated: + * + * Whether or not the title of the conversation was generated by + * [method@Conversation.generate_title]. + * + * Note: This only works on DMs and GroupDMs. + * + * If this is %TRUE, [method@Conversation.generate_title] will + * automatically be called whenever a member is added or removed, or when + * their display name changes. + * + * Since: 3.0 + */ + properties[PROP_TITLE_GENERATED] = g_param_spec_boolean( + "title-generated", "title-generated", + "Whether or not the current title was generated.", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * PurpleConversation:features: @@ -1088,20 +1183,6 @@ return conversation->type; } -void -purple_conversation_set_conversation_type(PurpleConversation *conversation, - PurpleConversationType type) -{ - g_return_if_fail(PURPLE_IS_CONVERSATION(conversation)); - - if(type != conversation->type) { - conversation->type = type; - - g_object_notify_by_pspec(G_OBJECT(conversation), - properties[PROP_TYPE]); - } -} - PurpleAccount * purple_conversation_get_account(PurpleConversation *conversation) { g_return_val_if_fail(PURPLE_IS_CONVERSATION(conversation), NULL); @@ -1129,14 +1210,24 @@ const char *title) { g_return_if_fail(PURPLE_IS_CONVERSATION(conversation)); - g_return_if_fail(title != NULL); if(!purple_strequal(conversation->title, title)) { + GObject *obj = G_OBJECT(conversation); + g_free(conversation->title); conversation->title = g_strdup(title); - g_object_notify_by_pspec(G_OBJECT(conversation), - properties[PROP_TITLE]); + /* We have to g_object_freeze_notify here because we're modifying more + * than one property. However, purple_conversation_generate_title will + * also have called g_object_freeze_notify before calling us because it + * needs to set the title-generated property to TRUE even though we set + * it to FALSE here. We do this, because we didn't want to write + * additional API that skips that part. + */ + g_object_freeze_notify(obj); + g_object_notify_by_pspec(obj, properties[PROP_TITLE]); + purple_conversation_set_title_generated(conversation, FALSE); + g_object_thaw_notify(obj); } } @@ -1148,14 +1239,80 @@ } void -purple_conversation_autoset_title(PurpleConversation *conversation) { - const char *name = NULL; +purple_conversation_generate_title(PurpleConversation *conversation) { + PurpleAccount *account = NULL; + PurpleContactInfo *account_info = NULL; + GString *str = NULL; + guint n_members = 0; + gboolean first = TRUE; g_return_if_fail(PURPLE_IS_CONVERSATION(conversation)); - name = purple_conversation_get_name(conversation); + if(conversation->type != PURPLE_CONVERSATION_TYPE_DM && + conversation->type != PURPLE_CONVERSATION_TYPE_GROUP_DM) + { + g_warning("purple_conversation_generate_title called for non DM/Group " + "DM conversation"); + + return; + } + + account = purple_conversation_get_account(conversation); + account_info = PURPLE_CONTACT_INFO(account); + + str = g_string_new(""); + + n_members = g_list_model_get_n_items(G_LIST_MODEL(conversation->members)); + for(guint i = 0; i < n_members; i++) { + PurpleContactInfo *info = NULL; + PurpleConversationMember *member = NULL; + const char *name = NULL; + + member = g_list_model_get_item(G_LIST_MODEL(conversation->members), i); + info = purple_conversation_member_get_contact_info(member); + if(purple_contact_info_compare(info, account_info) == 0) { + g_clear_object(&member); + + continue; + } + + name = purple_contact_info_get_name_for_display(info); + if(purple_strempty(name)) { + g_warning("contact %p has no displayable name", info); - purple_conversation_set_title(conversation, name); + g_clear_object(&member); + + continue; + } + + if(!first) { + g_string_append_printf(str, ", %s", name); + } else { + g_string_append(str, name); + first = FALSE; + } + + g_clear_object(&member); + } + + /* If we found at least 1 user to add, then we set the title. */ + if(!first) { + GObject *obj = G_OBJECT(conversation); + + g_object_freeze_notify(obj); + purple_conversation_set_title(conversation, str->str); + purple_conversation_set_title_generated(conversation, TRUE); + g_object_thaw_notify(obj); + } + + g_string_free(str, TRUE); +} + +gboolean +purple_conversation_get_title_generated(PurpleConversation *conversation) { + g_return_val_if_fail(PURPLE_IS_CONVERSATION(conversation), FALSE); + + return conversation->title_generated; } void @@ -1639,6 +1796,16 @@ member = purple_conversation_member_new(info); g_list_store_append(conversation->members, member); + /* Add a callback for notify::name-for-display on info. */ + g_signal_connect_object(info, "notify::name-for-display", + G_CALLBACK(purple_conversation_member_name_changed_cb), + conversation, G_CONNECT_DEFAULT); + + /* Update the title if necessary. */ + if(purple_conversation_get_title_generated(conversation)) { + purple_conversation_generate_title(conversation); + } + g_signal_emit(conversation, signals[SIG_MEMBER_ADDED], 0, member, announce, message); @@ -1667,6 +1834,16 @@ g_list_store_remove(conversation->members, position); + /* Remove our signal handlers for the member. */ + g_signal_handlers_disconnect_by_func(info, + purple_conversation_member_name_changed_cb, + conversation); + + /* Update our title if necessary. */ + if(purple_conversation_get_title_generated(conversation)) { + purple_conversation_generate_title(conversation); + } + g_signal_emit(conversation, signals[SIG_MEMBER_REMOVED], 0, member, announce, message);
--- a/libpurple/purpleconversation.h Tue May 07 23:06:04 2024 -0500 +++ b/libpurple/purpleconversation.h Wed May 08 03:37:46 2024 -0500 @@ -203,21 +203,6 @@ PurpleConversationType purple_conversation_get_conversation_type(PurpleConversation *conversation); /** - * purple_conversation_set_conversation_type: - * @conversation: The instance. - * @type: The new type. - * - * Sets the type of @conversation to @type. - * - * > Note this only for the internal representation in libpurple and the - * protocol will not be told to change the type. - * - * Since: 3.0 - */ -PURPLE_AVAILABLE_IN_3_0 -void purple_conversation_set_conversation_type(PurpleConversation *conversation, PurpleConversationType type); - -/** * purple_conversation_get_account: * @conversation: The conversation. * @@ -272,18 +257,37 @@ const char *purple_conversation_get_title(PurpleConversation *conversation); /** - * purple_conversation_autoset_title: - * @conversation: The conversation. + * purple_conversation_generate_title: + * @conversation: The instance. + * + * Sets the title for @conversation, which must be a DM or Group DM, to a comma + * separated string of the display names for each [class@ConversationMember]. * - * Automatically sets the specified conversation's title. + * If @conversation is not a DM or Group DM, no changes will be made. + * + * If no members are found, [property@Conversation:title] will not be changed. + * + * If the title is updated, [property@Conversation:title-generated] will be + * updated as well. * - * This function takes OPT_IM_ALIAS_TAB into account, as well as the - * user's alias. + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +void purple_conversation_generate_title(PurpleConversation *conversation); + +/** + * purple_conversation_get_title_generated: + * @conversation: The instance. * - * Since: 2.0 + * Gets whether or not the current title was automatically generated via + * [method@Conversation.generate_title]. + * + * Returns: %TRUE if the title was automatically generated. + * + * Since: 3.0 */ -PURPLE_AVAILABLE_IN_ALL -void purple_conversation_autoset_title(PurpleConversation *conversation); +PURPLE_AVAILABLE_IN_3_0 +gboolean purple_conversation_get_title_generated(PurpleConversation *conversation); /** * purple_conversation_set_name:
--- a/libpurple/tests/test_conversation.c Tue May 07 23:06:04 2024 -0500 +++ b/libpurple/tests/test_conversation.c Wed May 08 03:37:46 2024 -0500 @@ -47,6 +47,7 @@ char *description = NULL; char *id = NULL; char *name = NULL; + char *title = NULL; char *topic = NULL; char *user_nickname = NULL; gboolean age_restricted = FALSE; @@ -62,9 +63,6 @@ /* Use g_object_new so we can test setting properties by name. All of them * call the setter methods, so by doing it this way we exercise more of the * code. - * - * We don't currently test title because purple_conversation_autoset_title - * makes it something we don't expect it to be. */ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, @@ -78,6 +76,7 @@ "features", PURPLE_CONNECTION_FLAG_HTML, "id", "id1", "name", "name1", + "title", "test conversation", "topic", "the topic...", "topic-author", topic_author, "topic-updated", topic_updated, @@ -99,6 +98,7 @@ "members", &members, "name", &name, "tags", &tags, + "title", &title, "topic", &topic, "topic-author", &topic_author1, "topic-updated", &topic_updated1, @@ -141,6 +141,9 @@ g_assert_true(PURPLE_IS_TAGS(tags)); g_clear_object(&tags); + g_assert_cmpstr(title, ==, "test conversation"); + g_clear_pointer(&title, g_free); + g_assert_cmpstr(topic, ==, "the topic..."); g_clear_pointer(&topic, g_free); @@ -178,7 +181,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "this is required for some reason", NULL); g_assert_true(PURPLE_IS_CONVERSATION(conversation)); @@ -215,7 +217,6 @@ PURPLE_TYPE_CONVERSATION, "account", account, "type", PURPLE_CONVERSATION_TYPE_DM, - "name", "this is required for some reason", NULL); g_assert_true(PURPLE_IS_CONVERSATION(conversation)); @@ -239,7 +240,6 @@ PURPLE_TYPE_CONVERSATION, "account", account, "type", PURPLE_CONVERSATION_TYPE_GROUP_DM, - "name", "this is required for some reason", NULL); g_assert_true(PURPLE_IS_CONVERSATION(conversation)); @@ -263,7 +263,6 @@ PURPLE_TYPE_CONVERSATION, "account", account, "type", PURPLE_CONVERSATION_TYPE_CHANNEL, - "name", "this is required for some reason", NULL); g_assert_true(PURPLE_IS_CONVERSATION(conversation)); @@ -287,7 +286,6 @@ PURPLE_TYPE_CONVERSATION, "account", account, "type", PURPLE_CONVERSATION_TYPE_THREAD, - "name", "this is required for some reason", NULL); g_assert_true(PURPLE_IS_CONVERSATION(conversation)); @@ -336,8 +334,10 @@ gint added_called = 0; gint removed_called = 0; - /* Create our instances. */ - info = purple_contact_info_new(NULL); + /* Create our instances. The id is just a uuid 4 to help us avoid a + * g_warning. + */ + info = purple_contact_info_new("745c50ba-1189-48d9-827c-051783026c96"); account = purple_account_new("test", "test"); conversation = g_object_new( PURPLE_TYPE_CONVERSATION, @@ -427,7 +427,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "this is required", NULL); messages = purple_conversation_get_messages(conversation); @@ -488,6 +487,125 @@ } /****************************************************************************** + * generate_title tests + *****************************************************************************/ +static void +test_purple_conversation_generate_title_empty(void) { + PurpleAccount *account = NULL; + PurpleConversation *conversation = NULL; + const char *title = NULL; + + account = purple_account_new("test", "test"); + conversation = g_object_new( + PURPLE_TYPE_CONVERSATION, + "account", account, + "type", PURPLE_CONVERSATION_TYPE_DM, + NULL); + + title = purple_conversation_get_title(conversation); + g_assert_null(title); + + purple_conversation_set_title(conversation, "test"); + title = purple_conversation_get_title(conversation); + + /* There are no members in this conversation, so calling generate_title + * doesn't change the title. + */ + purple_conversation_generate_title(conversation); + title = purple_conversation_get_title(conversation); + g_assert_cmpstr(title, ==, "test"); + + g_assert_finalize_object(conversation); + g_clear_object(&account); +} + +static void +test_purple_conversation_generate_title_dm(void) { + PurpleAccount *account = NULL; + PurpleContact *contact = NULL; + PurpleConversation *conversation = NULL; + const char *title = NULL; + + account = purple_account_new("test", "test"); + conversation = g_object_new( + PURPLE_TYPE_CONVERSATION, + "account", account, + "type", PURPLE_CONVERSATION_TYPE_DM, + NULL); + + title = purple_conversation_get_title(conversation); + g_assert_null(title); + + contact = purple_contact_new(account, NULL); + purple_contact_info_set_username(PURPLE_CONTACT_INFO(contact), "Alice"); + purple_conversation_add_member(conversation, PURPLE_CONTACT_INFO(contact), + FALSE, NULL); + + title = purple_conversation_get_title(conversation); + g_assert_cmpstr(title, ==, "Alice"); + + /* Make sure the title updates when the display name changes. */ + purple_contact_info_set_username(PURPLE_CONTACT_INFO(contact), "alice!"); + title = purple_conversation_get_title(conversation); + g_assert_cmpstr(title, ==, "alice!"); + + g_assert_finalize_object(conversation); + g_assert_finalize_object(contact); + g_clear_object(&account); +} + +static void +test_purple_conversation_generate_title_group_dm(void) { + PurpleAccount *account = NULL; + PurpleContact *contact1 = NULL; + PurpleContact *contact2 = NULL; + PurpleContact *contact3 = NULL; + PurpleConversation *conversation = NULL; + const char *title = NULL; + + account = purple_account_new("test", "test"); + conversation = g_object_new( + PURPLE_TYPE_CONVERSATION, + "account", account, + "type", PURPLE_CONVERSATION_TYPE_GROUP_DM, + NULL); + + title = purple_conversation_get_title(conversation); + g_assert_null(title); + + contact1 = purple_contact_new(account, NULL); + purple_contact_info_set_username(PURPLE_CONTACT_INFO(contact1), "Alice"); + purple_conversation_add_member(conversation, PURPLE_CONTACT_INFO(contact1), + FALSE, NULL); + + contact2 = purple_contact_new(account, NULL); + purple_contact_info_set_username(PURPLE_CONTACT_INFO(contact2), "Bob"); + purple_conversation_add_member(conversation, PURPLE_CONTACT_INFO(contact2), + FALSE, NULL); + + contact3 = purple_contact_new(account, NULL); + purple_contact_info_set_username(PURPLE_CONTACT_INFO(contact3), "Eve"); + purple_conversation_add_member(conversation, PURPLE_CONTACT_INFO(contact3), + FALSE, NULL); + + title = purple_conversation_get_title(conversation); + g_assert_cmpstr(title, ==, "Alice, Bob, Eve"); + + /* Change some names around and verify the title was generated properly. */ + purple_contact_info_set_username(PURPLE_CONTACT_INFO(contact2), "Robert"); + purple_contact_info_set_username(PURPLE_CONTACT_INFO(contact3), "Evelyn"); + + title = purple_conversation_get_title(conversation); + g_assert_cmpstr(title, ==, "Alice, Robert, Evelyn"); + + g_assert_finalize_object(conversation); + g_assert_finalize_object(contact1); + g_assert_finalize_object(contact2); + g_assert_finalize_object(contact3); + g_clear_object(&account); +} + +/****************************************************************************** * Main *****************************************************************************/ gint @@ -520,6 +638,13 @@ g_test_add_func("/conversation/signals/present", test_purple_conversation_signals_present); + g_test_add_func("/conversation/generate-title/empty", + test_purple_conversation_generate_title_empty); + g_test_add_func("/conversation/generate-title/dm", + test_purple_conversation_generate_title_dm); + g_test_add_func("/conversation/generate-title/group-dm", + test_purple_conversation_generate_title_group_dm); + ret = g_test_run(); test_ui_purple_uninit();
--- a/libpurple/tests/test_conversation_manager.c Tue May 07 23:06:04 2024 -0500 +++ b/libpurple/tests/test_conversation_manager.c Wed May 08 03:37:46 2024 -0500 @@ -69,7 +69,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "purple_conversation_autoset_title sucks", NULL); /* Add the conversation to the manager. */ @@ -136,7 +135,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "kool kats", NULL); purple_conversation_manager_register(manager, conversation); @@ -185,7 +183,6 @@ PURPLE_TYPE_CONVERSATION, "account", account, "type", PURPLE_CONVERSATION_TYPE_DM, - "name", "bleh", NULL); ret = purple_conversation_manager_register(manager, conversation); @@ -238,13 +235,13 @@ manager = g_object_new(PURPLE_TYPE_CONVERSATION_MANAGER, NULL); account = purple_account_new("test", "test"); - contact = purple_contact_new(account, NULL); + contact = purple_contact_new(account, + "a9780f2a-eeb5-4d6b-89cb-52e5dad3973f"); conversation1 = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, "type", PURPLE_CONVERSATION_TYPE_DM, - "name", "this is required for some reason", NULL); purple_conversation_manager_register(manager, conversation1); purple_conversation_add_member(conversation1, PURPLE_CONTACT_INFO(contact), @@ -287,7 +284,6 @@ PURPLE_TYPE_CONVERSATION, "account", account1, "type", PURPLE_CONVERSATION_TYPE_CHANNEL, - "name", "this is required for some reason", NULL); purple_conversation_manager_register(manager, conversation1); @@ -298,7 +294,6 @@ PURPLE_TYPE_CONVERSATION, "account", account1, "type", PURPLE_CONVERSATION_TYPE_DM, - "name", "this is required for some reason", NULL); purple_conversation_manager_register(manager, conversation2); @@ -307,7 +302,6 @@ PURPLE_TYPE_CONVERSATION, "account", account2, "type", PURPLE_CONVERSATION_TYPE_CHANNEL, - "name", "this is required for some reason", NULL); purple_conversation_manager_register(manager, conversation2);
--- a/libpurple/tests/test_protocol_conversation.c Tue May 07 23:06:04 2024 -0500 +++ b/libpurple/tests/test_protocol_conversation.c Wed May 08 03:37:46 2024 -0500 @@ -203,7 +203,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "this is required at the moment", "type", PURPLE_CONVERSATION_TYPE_DM, NULL); message = g_object_new(PURPLE_TYPE_MESSAGE, NULL); @@ -262,7 +261,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "this is required at the moment", "type", PURPLE_CONVERSATION_TYPE_DM, NULL); @@ -395,7 +393,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "this is required at the moment", "type", PURPLE_CONVERSATION_TYPE_DM, NULL); @@ -451,7 +448,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "this is required at the moment", "type", PURPLE_CONVERSATION_TYPE_DM, NULL); @@ -545,7 +541,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "test", NULL); g_task_return_pointer(task, conversation, g_object_unref); }