Mon, 23 Dec 2024 20:39:36 -0600
Add Purple.ProtocolConversation.refresh
This virtual function asks the protocol to update an existing conversation.
This could be to bring it back online, update the topic, whatever.
Testing Done:
Ran the unit tests under valgrind and called in the turtles for good measure.
Bugs closed: PIDGIN-17989
Reviewed at https://reviews.imfreedom.org/r/3699/
--- a/libpurple/purpleprotocolconversation.c Fri Dec 06 15:18:29 2024 -0600 +++ b/libpurple/purpleprotocolconversation.c Mon Dec 23 20:39:36 2024 -0600 @@ -499,3 +499,36 @@ G_OBJECT_TYPE_NAME(protocol)); } } + +gboolean +purple_protocol_conversation_implements_refresh(PurpleProtocolConversation *protocol) +{ + PurpleProtocolConversationInterface *iface = NULL; + + g_return_val_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol), FALSE); + + iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol); + if(iface->refresh != NULL) { + return TRUE; + } + + return FALSE; +} + +void +purple_protocol_conversation_refresh(PurpleProtocolConversation *protocol, + PurpleConversation *conversation) +{ + PurpleProtocolConversationInterface *iface = NULL; + + g_return_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol)); + g_return_if_fail(PURPLE_IS_CONVERSATION(conversation)); + + iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol); + if(iface->refresh != NULL) { + iface->refresh(protocol, conversation); + } else { + g_warning("%s does not implement refresh", + G_OBJECT_TYPE_NAME(protocol)); + } +}
--- a/libpurple/purpleprotocolconversation.h Fri Dec 06 15:18:29 2024 -0600 +++ b/libpurple/purpleprotocolconversation.h Mon Dec 23 20:39:36 2024 -0600 @@ -95,6 +95,8 @@ void (*send_typing)(PurpleProtocolConversation *protocol, PurpleConversation *conversation, PurpleTypingState state); + void (*refresh)(PurpleProtocolConversation *protocol, PurpleConversation *conversation); + /*< private >*/ gpointer reserved[8]; }; @@ -446,6 +448,36 @@ PURPLE_AVAILABLE_IN_3_0 void purple_protocol_conversation_send_typing(PurpleProtocolConversation *protocol, PurpleConversation *conversation, PurpleTypingState state); +/** + * purple_protocol_conversation_implements_refresh: + * + * Checks if @protocol implements [vfunc@ProtocolConversation.refresh]. + * + * Returns: true if everything is implemented; false otherwise. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +gboolean purple_protocol_conversation_implements_refresh(PurpleProtocolConversation *protocol); + +/** + * purple_protocol_conversation_refresh: + * @conversation: the conversation + * + * Asks the protocol to refresh a conversation. + * + * A conversation could need to be refreshed for any number of reasons, but the + * primary case is to help restore conversations when user interfaces restart. + * + * This allows the user interface to recreate a conversation and then have the + * protocol do whatever is necessary to bring the conversation back up to date + * and online. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +void purple_protocol_conversation_refresh(PurpleProtocolConversation *protocol, PurpleConversation *conversation); + G_END_DECLS #endif /* PURPLE_PROTOCOL_CONVERSATION_H */
--- a/libpurple/tests/test_protocol_conversation.c Fri Dec 06 15:18:29 2024 -0600 +++ b/libpurple/tests/test_protocol_conversation.c Mon Dec 23 20:39:36 2024 -0600 @@ -458,6 +458,45 @@ g_test_trap_assert_stderr("*Purple-WARNING*TestPurpleProtocolConversationEmpty*send_typing*"); } +static void +test_purple_protocol_conversation_empty_implements_refresh(void) { + PurpleProtocolConversation *protocol = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(), + NULL); + + g_assert_false(purple_protocol_conversation_implements_refresh(protocol)); + + g_assert_finalize_object(protocol); +} + +static void +test_purple_protocol_conversation_empty_refresh(void) { + if(g_test_subprocess()) { + PurpleAccount *account = NULL; + PurpleConversation *conversation = NULL; + PurpleProtocolConversation *protocol = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(), + NULL); + account = purple_account_new("test", "test"); + conversation = g_object_new( + PURPLE_TYPE_CONVERSATION, + "account", account, + "type", PURPLE_CONVERSATION_TYPE_DM, + NULL); + + purple_protocol_conversation_refresh(protocol, conversation); + + g_clear_object(&account); + g_clear_object(&conversation); + g_clear_object(&protocol); + } + + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_stderr("*Purple-WARNING*TestPurpleProtocolConversationEmpty*refresh*"); +} + /****************************************************************************** * TestProtocolConversation Implementation *****************************************************************************/ @@ -491,6 +530,7 @@ guint set_avatar_finish; guint send_typing; + guint refresh; }; static PurpleCreateConversationDetails * @@ -796,6 +836,18 @@ } static void +test_purple_protocol_conversation_refresh(PurpleProtocolConversation *protocol, + PurpleConversation *conversation) +{ + TestPurpleProtocolConversation *test_protocol = NULL; + + test_protocol = TEST_PURPLE_PROTOCOL_CONVERSATION(protocol); + test_protocol->refresh += 1; + + g_assert_true(PURPLE_IS_CONVERSATION(conversation)); +} + +static void test_purple_protocol_conversation_iface_init(PurpleProtocolConversationInterface *iface) { iface->get_create_conversation_details = test_purple_protocol_conversation_get_create_conversation_details; iface->create_conversation_async = test_purple_protocol_conversation_create_conversation_async; @@ -818,6 +870,7 @@ iface->set_avatar_finish = test_purple_protocol_conversation_set_avatar_finish; iface->send_typing = test_purple_protocol_conversation_send_typing; + iface->refresh = test_purple_protocol_conversation_refresh; } G_DEFINE_FINAL_TYPE_WITH_CODE(TestPurpleProtocolConversation, @@ -850,6 +903,7 @@ protocol->set_avatar_finish = 0; protocol->send_typing = 0; + protocol->refresh = 0; } static void @@ -1094,7 +1148,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "this is required at the moment", "type", PURPLE_CONVERSATION_TYPE_DM, NULL); @@ -1158,7 +1211,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "this is required at the moment", "type", PURPLE_CONVERSATION_TYPE_DM, NULL); @@ -1302,7 +1354,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "this is required at the moment", "type", PURPLE_CONVERSATION_TYPE_DM, NULL); @@ -1352,7 +1403,6 @@ conversation = g_object_new( PURPLE_TYPE_CONVERSATION, "account", account, - "name", "this is required at the moment", "type", PURPLE_CONVERSATION_TYPE_DM, NULL); @@ -1367,6 +1417,49 @@ } /****************************************************************************** + * TestProtocolConversation Refresh Tests + ****************************************************************************/ +static void +test_purple_protocol_conversation_implements_refresh(void) { + PurpleProtocolConversation *protocol = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_get_type(), + NULL); + + g_assert_true(purple_protocol_conversation_implements_refresh(protocol)); + + g_assert_finalize_object(protocol); +} + +static void +test_purple_protocol_conversation_refresh_normal(void) { + TestPurpleProtocolConversation *test_protocol = NULL; + PurpleAccount *account = NULL; + PurpleConversation *conversation = NULL; + PurpleProtocolConversation *protocol = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_get_type(), + NULL); + test_protocol = TEST_PURPLE_PROTOCOL_CONVERSATION(protocol); + + account = purple_account_new("test", "test"); + + conversation = g_object_new( + PURPLE_TYPE_CONVERSATION, + "account", account, + "type", PURPLE_CONVERSATION_TYPE_DM, + NULL); + + test_purple_protocol_conversation_refresh(protocol, conversation); + + g_assert_cmpuint(test_protocol->refresh, ==, 1); + + g_clear_object(&conversation); + g_clear_object(&account); + g_clear_object(&protocol); +} + +/****************************************************************************** * Main *****************************************************************************/ gint @@ -1412,6 +1505,12 @@ g_test_add_func("/protocol-conversation/empty/send-typing", test_purple_protocol_conversation_empty_send_typing); + /* Empty refresh tests. */ + g_test_add_func("/protocol-conversation/empty/implements-refresh", + test_purple_protocol_conversation_empty_implements_refresh); + g_test_add_func("/protocol-conversation/empty/refresh", + test_purple_protocol_conversation_empty_refresh); + /* Normal create conversation tests. */ g_test_add_func("/protocol-conversation/normal/implements-create-conversation", test_purple_protocol_conversation_implements_create_conversation); @@ -1476,5 +1575,11 @@ g_test_add_func("/protocol-conversation/normal/send-typing", test_purple_protocol_conversation_send_typing_normal); + /* Normal refresh tests. */ + g_test_add_func("/protocol-conversation/normal/implements-refresh", + test_purple_protocol_conversation_implements_refresh); + g_test_add_func("/protocol-conversation/normal/refresh", + test_purple_protocol_conversation_refresh_normal); + return g_test_run(); }