Create Pidgin.Notification to simplify the custom widgets

Tue, 17 Sep 2024 00:56:55 -0500

author
Gary Kramlich <grim@reaperworld.com>
date
Tue, 17 Sep 2024 00:56:55 -0500
changeset 42940
240eb66a3795
parent 42939
4921f19b1b7b
child 42941
d39faa3581eb

Create Pidgin.Notification to simplify the custom widgets

This should be much easier to maintain as it keeps everything encapsulated.

PidginNotificationAuthorizationRequest was removed as nothing creates these
notifications right now.

PidginNotificationConnectionError was removed as we are currently in the
process of reworking the way connection errors work and this is in the way of
that.

Testing Done:
Created a bunch of test notifications with the demo protocol plugin and called in the turtles.

Bugs closed: PIDGIN-17929, PIDGIN-17942

Reviewed at https://reviews.imfreedom.org/r/3480/

pidgin/meson.build file | annotate | diff | comparison | revisions
pidgin/pidginnotification.c file | annotate | diff | comparison | revisions
pidgin/pidginnotification.h file | annotate | diff | comparison | revisions
pidgin/pidginnotificationaddcontact.c file | annotate | diff | comparison | revisions
pidgin/pidginnotificationaddcontact.h file | annotate | diff | comparison | revisions
pidgin/pidginnotificationauthorizationrequest.c file | annotate | diff | comparison | revisions
pidgin/pidginnotificationauthorizationrequest.h file | annotate | diff | comparison | revisions
pidgin/pidginnotificationconnectionerror.c file | annotate | diff | comparison | revisions
pidgin/pidginnotificationconnectionerror.h file | annotate | diff | comparison | revisions
pidgin/pidginnotificationlist.c file | annotate | diff | comparison | revisions
pidgin/resources/Notifications/addcontact.ui file | annotate | diff | comparison | revisions
pidgin/resources/Notifications/authorizationrequest.ui file | annotate | diff | comparison | revisions
pidgin/resources/Notifications/connectionerror.ui file | annotate | diff | comparison | revisions
pidgin/resources/notification.ui file | annotate | diff | comparison | revisions
pidgin/resources/notificationaddcontact.ui file | annotate | diff | comparison | revisions
pidgin/resources/pidgin.gresource.xml file | annotate | diff | comparison | revisions
--- a/pidgin/meson.build	Tue Sep 17 00:55:06 2024 -0500
+++ b/pidgin/meson.build	Tue Sep 17 00:56:55 2024 -0500
@@ -32,9 +32,8 @@
 	'pidgininfopane.c',
 	'pidginkeypad.c',
 	'pidginnotifiable.c',
+	'pidginnotification.c',
 	'pidginnotificationaddcontact.c',
-	'pidginnotificationauthorizationrequest.c',
-	'pidginnotificationconnectionerror.c',
 	'pidginnotificationlist.c',
 	'pidginpluginsmenu.c',
 	'pidginpresenceicon.c',
@@ -79,9 +78,8 @@
 	'pidgininfopane.h',
 	'pidginkeypad.h',
 	'pidginnotifiable.h',
+	'pidginnotification.h',
 	'pidginnotificationaddcontact.h',
-	'pidginnotificationauthorizationrequest.h',
-	'pidginnotificationconnectionerror.h',
 	'pidginnotificationlist.h',
 	'pidginpluginsmenu.h',
 	'pidginpresenceicon.h',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginnotification.c	Tue Sep 17 00:56:55 2024 -0500
@@ -0,0 +1,262 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n-lib.h>
+
+#include <purple.h>
+
+#include "pidgin/pidginnotification.h"
+
+typedef struct {
+	PurpleNotification *notification;
+
+	GtkWidget *details;
+	GtkWidget *child;
+} PidginNotificationPrivate;
+
+enum {
+	PROP_0,
+	PROP_NOTIFICATION,
+	PROP_CHILD,
+	N_PROPERTIES,
+};
+static GParamSpec *properties[N_PROPERTIES] = {NULL, };
+
+G_DEFINE_TYPE_WITH_PRIVATE(PidginNotification, pidgin_notification,
+                           GTK_TYPE_BOX)
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+pidgin_notification_set_notification(PidginNotification *pidgin_notification,
+                                     PurpleNotification *purple_notification)
+{
+	PidginNotificationPrivate *priv = NULL;
+
+	priv = pidgin_notification_get_instance_private(pidgin_notification);
+
+	if(g_set_object(&priv->notification, purple_notification)) {
+		g_object_notify_by_pspec(G_OBJECT(pidgin_notification),
+		                         properties[PROP_NOTIFICATION]);
+	}
+}
+
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
+static gboolean
+pidgin_notification_show_subtitle(G_GNUC_UNUSED PidginNotification *notification,
+                                  const char *subtitle)
+{
+	return !purple_strempty(subtitle);
+}
+
+/******************************************************************************
+ * Widget Actions
+ *****************************************************************************/
+static void
+pidgin_notification_close(GtkWidget *self,
+                          G_GNUC_UNUSED const char *action_name,
+                          G_GNUC_UNUSED GVariant *parameter)
+{
+	PidginNotification *notification = PIDGIN_NOTIFICATION(self);
+	PidginNotificationPrivate *priv = NULL;
+	PurpleNotificationManager *manager = NULL;
+
+	priv = pidgin_notification_get_instance_private(notification);
+	purple_notification_delete(priv->notification);
+
+	manager = purple_notification_manager_get_default();
+	purple_notification_manager_remove(manager, priv->notification);
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+static void
+pidgin_notification_get_property(GObject *obj, guint param_id, GValue *value,
+                                 GParamSpec *pspec)
+{
+	PidginNotification *notification = PIDGIN_NOTIFICATION(obj);
+
+	switch(param_id) {
+	case PROP_NOTIFICATION:
+		g_value_set_object(value,
+		                   pidgin_notification_get_notification(notification));
+		break;
+	case PROP_CHILD:
+		g_value_set_object(value,
+		                   pidgin_notification_get_child(notification));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+		break;
+	}
+}
+
+static void
+pidgin_notification_set_property(GObject *obj, guint param_id,
+                                 const GValue *value, GParamSpec *pspec)
+{
+	PidginNotification *notification = PIDGIN_NOTIFICATION(obj);
+
+	switch(param_id) {
+	case PROP_NOTIFICATION:
+		pidgin_notification_set_notification(notification,
+		                                     g_value_get_object(value));
+		break;
+	case PROP_CHILD:
+		pidgin_notification_set_child(notification, g_value_get_object(value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+		break;
+	}
+}
+
+static void
+pidgin_notification_dispose(GObject *obj) {
+	PidginNotification *notification = PIDGIN_NOTIFICATION(obj);
+	PidginNotificationPrivate *priv = NULL;
+
+	priv = pidgin_notification_get_instance_private(notification);
+
+	g_clear_object(&priv->notification);
+	g_clear_pointer(&priv->child, gtk_widget_unparent);
+
+	G_OBJECT_CLASS(pidgin_notification_parent_class)->dispose(obj);
+}
+
+static void
+pidgin_notification_init(PidginNotification *notification) {
+	gtk_widget_init_template(GTK_WIDGET(notification));
+}
+
+static void
+pidgin_notification_class_init(PidginNotificationClass *klass) {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+
+	obj_class->get_property = pidgin_notification_get_property;
+	obj_class->set_property = pidgin_notification_set_property;
+	obj_class->dispose = pidgin_notification_dispose;
+
+	/**
+	 * PidginNotification:notification:
+	 *
+	 * The [type@Purple.Notification] that is being displayed.
+	 *
+	 * Since: 3.0
+	 */
+	properties[PROP_NOTIFICATION] = g_param_spec_object(
+		"notification", NULL, NULL,
+		PURPLE_TYPE_NOTIFICATION,
+		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * PidginNotification:child:
+	 *
+	 * Child widgets to show between the details and the close button.
+	 *
+	 * This is typically actions like message, add contact, etc.
+	 *
+	 * Since: 3.0
+	 */
+	properties[PROP_CHILD] = g_param_spec_object(
+		"child", NULL, NULL,
+		GTK_TYPE_WIDGET,
+		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+
+	/* Actions */
+	gtk_widget_class_install_action(widget_class, "notification.close",
+	                                NULL, pidgin_notification_close);
+
+	/* Bindings */
+	gtk_widget_class_set_template_from_resource(widget_class,
+	                                            "/im/pidgin/Pidgin3/notification.ui");
+
+	gtk_widget_class_bind_template_child_private(widget_class,
+	                                             PidginNotification, details);
+	gtk_widget_class_bind_template_callback(widget_class,
+	                                        pidgin_notification_show_subtitle);
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+GtkWidget *
+pidgin_notification_new(PurpleNotification *notification) {
+	return g_object_new(
+		PIDGIN_TYPE_NOTIFICATION,
+		"notification", notification,
+		NULL);
+}
+
+PurpleNotification *
+pidgin_notification_get_notification(PidginNotification *notification)
+{
+	PidginNotificationPrivate *priv = NULL;
+
+	g_return_val_if_fail(PIDGIN_IS_NOTIFICATION(notification), NULL);
+
+	priv = pidgin_notification_get_instance_private(notification);
+
+	return priv->notification;
+}
+
+GtkWidget *
+pidgin_notification_get_child(PidginNotification *notification) {
+	PidginNotificationPrivate *priv = NULL;
+
+	g_return_val_if_fail(PIDGIN_IS_NOTIFICATION(notification), NULL);
+
+	priv = pidgin_notification_get_instance_private(notification);
+
+	return priv->child;
+}
+
+void
+pidgin_notification_set_child(PidginNotification *notification,
+                              GtkWidget *child)
+{
+	PidginNotificationPrivate *priv = NULL;
+
+	g_return_if_fail(PIDGIN_IS_NOTIFICATION(notification));
+
+	priv = pidgin_notification_get_instance_private(notification);
+
+	if(child == priv->child) {
+		return;
+	}
+
+	g_clear_pointer(&priv->child, gtk_widget_unparent);
+	if(GTK_IS_WIDGET(child)) {
+		priv->child = child;
+		gtk_box_insert_child_after(GTK_BOX(notification), child,
+		                           priv->details);
+	}
+
+	g_object_notify_by_pspec(G_OBJECT(notification), properties[PROP_CHILD]);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginnotification.h	Tue Sep 17 00:56:55 2024 -0500
@@ -0,0 +1,125 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined(PIDGIN_GLOBAL_HEADER_INSIDE) && !defined(PIDGIN_COMPILATION)
+# error "only <pidgin.h> may be included directly"
+#endif
+
+#ifndef PIDGIN_NOTIFICATION_H
+#define PIDGIN_NOTIFICATION_H
+
+#include <glib.h>
+
+#include <gtk/gtk.h>
+
+#include <adwaita.h>
+
+#include <purple.h>
+
+#include "pidginversion.h"
+
+G_BEGIN_DECLS
+
+/**
+ * PidginNotification:
+ *
+ * #PidginNotification is a widget that displays [class@Purple.Notification]'s
+ * from [class@Purple.NotificationManager].
+ *
+ * Depending on the [class@Purple.Notification] that this is created for,
+ * different actions will be displayed.
+ *
+ * Since: 3.0
+ */
+
+#define PIDGIN_TYPE_NOTIFICATION (pidgin_notification_get_type())
+
+PIDGIN_AVAILABLE_IN_3_0
+G_DECLARE_DERIVABLE_TYPE(PidginNotification, pidgin_notification, PIDGIN,
+                         NOTIFICATION, GtkBox)
+
+struct _PidginNotificationClass {
+    /*< private >*/
+    GtkBoxClass parent;
+
+    /*< private >*/
+    gpointer reserved[4];
+};
+
+/**
+ * pidgin_notification_new:
+ * @notification: A [class@Purple.Notification] to display.
+ *
+ * Creates a new widget that will display @notification.
+ *
+ * Returns: (transfer full): The new instance.
+ *
+ * Since: 3.0
+ */
+PIDGIN_AVAILABLE_IN_3_0
+GtkWidget *pidgin_notification_new(PurpleNotification *notification);
+
+/**
+ * pidgin_notification_get_notification:
+ * @notification: The instance.
+ *
+ * Gets the [class@Purple.Notification] that @notification is displaying.
+ *
+ * Returns: (transfer none): The notification.
+ *
+ * Since: 3.0
+ */
+PIDGIN_AVAILABLE_IN_3_0
+PurpleNotification *pidgin_notification_get_notification(PidginNotification *notification);
+
+/**
+ * pidgin_notification_get_child:
+ * @notification: The instance.
+ *
+ * Gets the child widget from @notification.
+ *
+ * This child is meant to hold actions that can be performed for this
+ * notification.
+ *
+ * Returns: (transfer none) (nullable): The child widget if set, otherwise
+ *          %NULL.
+ *
+ * Since: 3.0
+ */
+PIDGIN_AVAILABLE_IN_3_0
+GtkWidget *pidgin_notification_get_child(PidginNotification *notification);
+
+/**
+ * pidgin_notification_set_child:
+ * @notification: The instance.
+ * @child: (nullable): The new child widget.
+ *
+ * Sets the child of @notification to @child.
+ *
+ * Since: 3.0
+ */
+PIDGIN_AVAILABLE_IN_3_0
+void pidgin_notification_set_child(PidginNotification *notification, GtkWidget *child);
+
+G_END_DECLS
+
+#endif /* PIDGIN_NOTIFICATION_H */
--- a/pidgin/pidginnotificationaddcontact.c	Tue Sep 17 00:55:06 2024 -0500
+++ b/pidgin/pidginnotificationaddcontact.c	Tue Sep 17 00:56:55 2024 -0500
@@ -27,264 +27,101 @@
 #include "pidgin/pidginnotificationaddcontact.h"
 
 struct _PidginNotificationAddContact {
-	AdwActionRow parent;
-
-	PurpleNotification *notification;
-
-	GtkWidget *icon;
-	GtkWidget *add;
-	GtkWidget *message;
+	PidginNotification parent;
 };
 
-enum {
-	PROP_0,
-	PROP_NOTIFICATION,
-	N_PROPERTIES,
-};
-static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-
 G_DEFINE_FINAL_TYPE(PidginNotificationAddContact,
-                    pidgin_notification_add_contact, ADW_TYPE_ACTION_ROW)
-
-/******************************************************************************
- * Helpers
- *****************************************************************************/
-static void
-pidgin_notification_add_contact_update(PidginNotificationAddContact *add_contact)
-{
-	PurpleAccount *account = NULL;
-	PurpleAddContactRequest *request = NULL;
-	const gchar *title = NULL;
-	const gchar *icon_name = NULL, *message = NULL;
-
-	g_return_if_fail(PIDGIN_IS_NOTIFICATION_ADD_CONTACT(add_contact));
-
-	if(!PURPLE_IS_NOTIFICATION(add_contact->notification)) {
-		adw_preferences_row_set_title(ADW_PREFERENCES_ROW(add_contact),
-		                              _("Notification missing"));
-
-		gtk_image_set_from_icon_name(GTK_IMAGE(add_contact->icon), NULL);
-		adw_action_row_set_subtitle(ADW_ACTION_ROW(add_contact), NULL);
-
-		gtk_widget_set_visible(add_contact->add, FALSE);
-		gtk_widget_set_visible(add_contact->message, FALSE);
-
-		return;
-	}
-
-	account = purple_notification_get_account(add_contact->notification);
-	if(!PURPLE_IS_ACCOUNT(account)) {
-		adw_preferences_row_set_title(ADW_PREFERENCES_ROW(add_contact),
-		                              _("Notification is missing an account"));
-
-		gtk_image_set_from_icon_name(GTK_IMAGE(add_contact->icon), NULL);
-		adw_action_row_set_subtitle(ADW_ACTION_ROW(add_contact), NULL);
-
-		gtk_widget_set_visible(add_contact->add, FALSE);
-		gtk_widget_set_visible(add_contact->message, FALSE);
-
-		return;
-	}
-
-	request = purple_notification_get_data(add_contact->notification);
-
-	/* Set the icon name if one was specified. */
-	icon_name = purple_notification_get_icon_name(add_contact->notification);
-	if(icon_name == NULL) {
-		PurpleProtocol *protocol = NULL;
-
-		protocol = purple_account_get_protocol(account);
-		icon_name = purple_protocol_get_icon_name(protocol);
-
-		if(icon_name == NULL) {
-			icon_name = "dialog-question";
-		}
-	}
-	gtk_image_set_from_icon_name(GTK_IMAGE(add_contact->icon), icon_name);
-
-	title = purple_notification_get_title(add_contact->notification);
-	adw_preferences_row_set_title(ADW_PREFERENCES_ROW(add_contact), title);
-
-	message = purple_add_contact_request_get_message(request);
-	adw_action_row_set_subtitle(ADW_ACTION_ROW(add_contact), message);
-
-	gtk_widget_set_visible(add_contact->add, TRUE);
-	gtk_widget_set_visible(add_contact->message, TRUE);
-}
-
-static void
-pidgin_notification_add_contact_set_notification(PidginNotificationAddContact *add_contact,
-                                                 PurpleNotification *notification)
-{
-	if(g_set_object(&add_contact->notification, notification)) {
-		pidgin_notification_add_contact_update(add_contact);
-
-		g_object_notify_by_pspec(G_OBJECT(add_contact),
-		                         properties[PROP_NOTIFICATION]);
-	}
-}
-
-static void
-pidgin_notification_add_contact_close(PidginNotificationAddContact *add_contact)
-{
-	PurpleNotificationManager *manager = NULL;
-
-	purple_notification_delete(add_contact->notification);
-
-	manager = purple_notification_manager_get_default();
-	purple_notification_manager_remove(manager, add_contact->notification);
-}
+                    pidgin_notification_add_contact, PIDGIN_TYPE_NOTIFICATION)
 
 /******************************************************************************
  * Callbacks
  *****************************************************************************/
 static void
-pidgin_notification_add_contact_add_cb(G_GNUC_UNUSED GtkButton *button,
-                                       gpointer data)
+pidgin_notification_add_contact_create_dm_cb(GObject *self,
+                                             GAsyncResult *result,
+                                             G_GNUC_UNUSED gpointer data)
 {
-	PidginNotificationAddContact *pidgin_request = data;
-	PurpleAddContactRequest *request = NULL;
+	PurpleContact *contact = PURPLE_CONTACT(self);
+	PurpleConversation *conversation = NULL;
+	GError *error = NULL;
 
-	request = purple_notification_get_data(pidgin_request->notification);
+	conversation = purple_contact_create_dm_finish(contact, result, &error);
+	if(error != NULL) {
+		g_warning("failed to create dm for %s: %s",
+		          purple_contact_info_get_name_for_display(PURPLE_CONTACT_INFO(contact)),
+		          error->message);
+
+		g_clear_error(&error);
+		g_clear_object(&conversation);
 
-	purple_add_contact_request_add(request);
+		return;
+	}
 
-	pidgin_notification_add_contact_close(pidgin_request);
+	if(PURPLE_IS_CONVERSATION(conversation)) {
+		purple_conversation_present(conversation);
+	}
+
+	g_clear_object(&conversation);
 }
 
+/******************************************************************************
+ * Actions
+ *****************************************************************************/
 static void
-pidgin_notification_add_contact_message_cb(G_GNUC_UNUSED GtkButton *button,
-                                           gpointer data)
+pidgin_notification_add_contact_message(GtkWidget *self,
+                                        G_GNUC_UNUSED const char *action_name,
+                                        G_GNUC_UNUSED GVariant *parameter)
 {
-	PidginNotificationAddContact *pidgin_request = data;
+	PidginNotification *pidgin_notification = PIDGIN_NOTIFICATION(self);
+	PurpleNotification *purple_notification = NULL;
 	PurpleAddContactRequest *request = NULL;
 	PurpleContact *contact = NULL;
 	PurpleConversation *conversation = NULL;
 
-	request = purple_notification_get_data(pidgin_request->notification);
+	purple_notification = pidgin_notification_get_notification(pidgin_notification);
+	request = purple_notification_add_contact_get_request(PURPLE_NOTIFICATION_ADD_CONTACT(purple_notification));
 	contact = purple_add_contact_request_get_contact(request);
 
 	conversation = purple_contact_find_dm(contact);
 	if(PURPLE_IS_CONVERSATION(conversation)) {
 		purple_conversation_present(conversation);
 	} else {
-		purple_contact_create_dm_async(contact, NULL, NULL, NULL);
+		purple_contact_create_dm_async(contact, NULL,
+		                               pidgin_notification_add_contact_create_dm_cb,
+		                               NULL);
 	}
 }
 
-static void
-pidgin_notification_add_contact_remove_cb(G_GNUC_UNUSED GtkButton *button,
-                                          gpointer data)
-{
-	PidginNotificationAddContact *request = data;
-
-	pidgin_notification_add_contact_close(request);
-}
-
 /******************************************************************************
  * GObject Implementation
  *****************************************************************************/
 static void
-pidgin_notification_add_contact_get_property(GObject *obj, guint param_id,
-                                             GValue *value, GParamSpec *pspec)
-{
-	PidginNotificationAddContact *request = NULL;
-
-	request = PIDGIN_NOTIFICATION_ADD_CONTACT(obj);
-
-	switch(param_id) {
-		case PROP_NOTIFICATION:
-			g_value_set_object(value,
-			                   pidgin_notification_add_contact_get_notification(request));
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-			break;
-	}
-}
-
-static void
-pidgin_notification_add_contact_set_property(GObject *obj, guint param_id,
-                                             const GValue *value,
-                                             GParamSpec *pspec)
+pidgin_notification_add_contact_init(PidginNotificationAddContact *notification)
 {
-	PidginNotificationAddContact *request = NULL;
-
-	request = PIDGIN_NOTIFICATION_ADD_CONTACT(obj);
-
-	switch(param_id) {
-		case PROP_NOTIFICATION:
-			pidgin_notification_add_contact_set_notification(request,
-			                                                 g_value_get_object(value));
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-			break;
-	}
-}
-
-static void
-pidgin_notification_add_contact_dispose(GObject *obj) {
-	PidginNotificationAddContact *request = NULL;
-
-	request = PIDGIN_NOTIFICATION_ADD_CONTACT(obj);
-
-	g_clear_object(&request->notification);
-
-	G_OBJECT_CLASS(pidgin_notification_add_contact_parent_class)->dispose(obj);
-}
-
-static void
-pidgin_notification_add_contact_init(PidginNotificationAddContact *list) {
-	gtk_widget_init_template(GTK_WIDGET(list));
+	gtk_widget_init_template(GTK_WIDGET(notification));
 }
 
 static void
 pidgin_notification_add_contact_class_init(PidginNotificationAddContactClass *klass)
 {
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
 
-	obj_class->get_property = pidgin_notification_add_contact_get_property;
-	obj_class->set_property = pidgin_notification_add_contact_set_property;
-	obj_class->dispose = pidgin_notification_add_contact_dispose;
-
-	/**
-	 * PidginNotificationAddContact:notification:
-	 *
-	 * The [type@Purple.Notification] that is being displayed.
-	 *
-	 * Since: 3.0
-	 */
-	properties[PROP_NOTIFICATION] = g_param_spec_object(
-		"notification", "notification",
-		"The notification to display",
-		PURPLE_TYPE_NOTIFICATION,
-		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
-
 	gtk_widget_class_set_template_from_resource(
 	    widget_class,
-	    "/im/pidgin/Pidgin3/Notifications/addcontact.ui"
+	    "/im/pidgin/Pidgin3/notificationaddcontact.ui"
 	);
 
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationAddContact,
-	                                     icon);
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationAddContact,
-	                                     add);
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationAddContact,
-	                                     message);
-
-	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_notification_add_contact_add_cb);
-	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_notification_add_contact_message_cb);
-	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_notification_add_contact_remove_cb);
+#if 0
+	/* This is disabled because it uses the request API and we really need to
+	 * create a real dialog for this instead.
+	 */
+	gtk_widget_class_install_action(widget_class, "notification.add-contact",
+	                                NULL,
+	                                pidgin_notification_add_contact_add_contact);
+#endif
+	gtk_widget_class_install_action(widget_class, "notification.message",
+	                                NULL,
+	                                pidgin_notification_add_contact_message);
 }
 
 /******************************************************************************
@@ -292,16 +129,11 @@
  *****************************************************************************/
 GtkWidget *
 pidgin_notification_add_contact_new(PurpleNotification *notification) {
+	g_return_val_if_fail(PURPLE_IS_NOTIFICATION_ADD_CONTACT(notification),
+	                     NULL);
+
 	return g_object_new(
 		PIDGIN_TYPE_NOTIFICATION_ADD_CONTACT,
 		"notification", notification,
 		NULL);
 }
-
-PurpleNotification *
-pidgin_notification_add_contact_get_notification(PidginNotificationAddContact *add_contact)
-{
-	g_return_val_if_fail(PIDGIN_IS_NOTIFICATION_ADD_CONTACT(add_contact), NULL);
-
-	return add_contact->notification;
-}
--- a/pidgin/pidginnotificationaddcontact.h	Tue Sep 17 00:55:06 2024 -0500
+++ b/pidgin/pidginnotificationaddcontact.h	Tue Sep 17 00:56:55 2024 -0500
@@ -35,6 +35,7 @@
 
 #include <purple.h>
 
+#include "pidginnotification.h"
 #include "pidginversion.h"
 
 G_BEGIN_DECLS
@@ -53,7 +54,7 @@
 
 PIDGIN_AVAILABLE_IN_3_0
 G_DECLARE_FINAL_TYPE(PidginNotificationAddContact, pidgin_notification_add_contact,
-                     PIDGIN, NOTIFICATION_ADD_CONTACT, AdwActionRow)
+                     PIDGIN, NOTIFICATION_ADD_CONTACT, PidginNotification)
 
 /**
  * pidgin_notification_add_contact_new:
@@ -70,19 +71,6 @@
 PIDGIN_AVAILABLE_IN_3_0
 GtkWidget *pidgin_notification_add_contact_new(PurpleNotification *notification);
 
-/**
- * pidgin_notification_add_contact_get_notification:
- * @request: The instance.
- *
- * Gets the [class@Purple.Notification] that @request is displaying.
- *
- * Returns: (transfer none): The notification.
- *
- * Since: 3.0
- */
-PIDGIN_AVAILABLE_IN_3_0
-PurpleNotification *pidgin_notification_add_contact_get_notification(PidginNotificationAddContact *request);
-
 G_END_DECLS
 
 #endif /* PIDGIN_NOTIFICATION_ADD_CONTACT_H */
--- a/pidgin/pidginnotificationauthorizationrequest.c	Tue Sep 17 00:55:06 2024 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +0,0 @@
-/*
- * Pidgin - Internet Messenger
- * Copyright (C) Pidgin Developers <devel@pidgin.im>
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <https://www.gnu.org/licenses/>.
- */
-
-#include <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "pidgin/pidginnotificationauthorizationrequest.h"
-
-struct _PidginNotificationAuthorizationRequest {
-	AdwActionRow parent;
-
-	PurpleNotification *notification;
-
-	GtkWidget *icon;
-	GtkWidget *accept;
-	GtkWidget *deny;
-	GtkWidget *message;
-};
-
-enum {
-	PROP_0,
-	PROP_NOTIFICATION,
-	N_PROPERTIES,
-};
-static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-
-G_DEFINE_FINAL_TYPE(PidginNotificationAuthorizationRequest,
-                    pidgin_notification_authorization_request,
-                    ADW_TYPE_ACTION_ROW)
-
-/******************************************************************************
- * Helpers
- *****************************************************************************/
-static void
-pidgin_notification_authorization_request_update(PidginNotificationAuthorizationRequest *request) {
-	PurpleAccount *account = NULL;
-	PurpleAuthorizationRequest *purple_request = NULL;
-	const gchar *title = NULL;
-	const gchar *icon_name = NULL, *message = NULL;
-
-	g_return_if_fail(PIDGIN_IS_NOTIFICATION_AUTHORIZATION_REQUEST(request));
-
-	if(!PURPLE_IS_NOTIFICATION(request->notification)) {
-		adw_preferences_row_set_title(ADW_PREFERENCES_ROW(request),
-		                              _("Notification missing"));
-
-		gtk_image_set_from_icon_name(GTK_IMAGE(request->icon), NULL);
-		adw_action_row_set_subtitle(ADW_ACTION_ROW(request), NULL);
-
-		gtk_widget_set_visible(request->accept, FALSE);
-		gtk_widget_set_visible(request->deny, FALSE);
-		gtk_widget_set_visible(request->message, FALSE);
-
-		return;
-	}
-
-	account = purple_notification_get_account(request->notification);
-	if(!PURPLE_IS_ACCOUNT(account)) {
-		adw_preferences_row_set_title(ADW_PREFERENCES_ROW(request),
-		                              _("Notification is missing an account"));
-
-		gtk_image_set_from_icon_name(GTK_IMAGE(request->icon), NULL);
-		adw_action_row_set_subtitle(ADW_ACTION_ROW(request), NULL);
-
-		gtk_widget_set_visible(request->accept, FALSE);
-		gtk_widget_set_visible(request->deny, FALSE);
-		gtk_widget_set_visible(request->message, FALSE);
-
-		return;
-	}
-
-	purple_request = purple_notification_get_data(request->notification);
-
-	/* Set the icon name if one was specified. */
-	icon_name = purple_notification_get_icon_name(request->notification);
-	if(icon_name == NULL) {
-		PurpleProtocol *protocol = NULL;
-
-		protocol = purple_account_get_protocol(account);
-		icon_name = purple_protocol_get_icon_name(protocol);
-
-		if(icon_name == NULL) {
-			icon_name = "dialog-question";
-		}
-	}
-	gtk_image_set_from_icon_name(GTK_IMAGE(request->icon), icon_name);
-
-	title = purple_notification_get_title(request->notification);
-	adw_preferences_row_set_title(ADW_PREFERENCES_ROW(request), title);
-
-	message = purple_authorization_request_get_message(purple_request);
-	adw_action_row_set_subtitle(ADW_ACTION_ROW(request), message);
-
-	gtk_widget_set_visible(request->accept, TRUE);
-	gtk_widget_set_visible(request->deny, TRUE);
-	gtk_widget_set_visible(request->message, TRUE);
-}
-
-static void
-pidgin_notification_authorization_request_set_notification(PidginNotificationAuthorizationRequest *request,
-                                                           PurpleNotification *notification)
-{
-	if(g_set_object(&request->notification, notification)) {
-		pidgin_notification_authorization_request_update(request);
-
-		g_object_notify_by_pspec(G_OBJECT(request), properties[PROP_NOTIFICATION]);
-	}
-}
-
-static void
-pidgin_notification_authorization_request_close(PidginNotificationAuthorizationRequest *request)
-{
-	PurpleNotificationManager *manager = NULL;
-
-	purple_notification_delete(request->notification);
-
-	manager = purple_notification_manager_get_default();
-	purple_notification_manager_remove(manager, request->notification);
-}
-
-/******************************************************************************
- * Callbacks
- *****************************************************************************/
-static void
-pidgin_notification_authorization_request_accept_cb(G_GNUC_UNUSED GtkButton *button,
-                                                    gpointer data)
-{
-	PidginNotificationAuthorizationRequest *pidgin_request = data;
-	PurpleAuthorizationRequest *request = NULL;
-
-	request = purple_notification_get_data(pidgin_request->notification);
-
-	purple_authorization_request_accept(request);
-
-#if 0
-	if(purple_authorization_request_get_add(request)) {
-		PurpleAccount *account = NULL;
-		const gchar *username = NULL, *alias = NULL;
-
-		account = purple_authorization_request_get_account(request);
-		username = purple_authorization_request_get_username(request);
-		alias = purple_authorization_request_get_alias(request);
-	}
-#endif
-
-	pidgin_notification_authorization_request_close(pidgin_request);
-}
-
-static void
-pidgin_notification_authorization_request_deny_cb(G_GNUC_UNUSED GtkButton *button,
-                                                  gpointer data)
-{
-	PidginNotificationAuthorizationRequest *pidgin_request = data;
-	PurpleAuthorizationRequest *request = NULL;
-
-	request = purple_notification_get_data(pidgin_request->notification);
-
-	purple_authorization_request_deny(request, NULL);
-
-	pidgin_notification_authorization_request_close(pidgin_request);
-}
-
-static void
-pidgin_notification_authorization_request_message_cb(G_GNUC_UNUSED GtkButton *button,
-                                                     gpointer data)
-{
-	PidginNotificationAuthorizationRequest *pidgin_request = data;
-	PurpleAuthorizationRequest *request = NULL;
-	PurpleAccount *account = NULL;
-	PurpleContact *contact = NULL;
-	PurpleContactManager *manager = NULL;
-	PurpleConversation *conversation = NULL;
-	const char *username = NULL;
-
-	request = purple_notification_get_data(pidgin_request->notification);
-
-	account = purple_authorization_request_get_account(request);
-	username = purple_authorization_request_get_username(request);
-
-	manager = purple_contact_manager_get_default();
-	contact = purple_contact_manager_find_with_username(manager, account,
-	                                                    username);
-
-	if(!PURPLE_IS_CONTACT(contact)) {
-		g_warning("failed to find a user named '%s' on account %s",
-		          username,
-		          purple_account_get_username(account));
-
-		return;
-	}
-
-	conversation = purple_contact_find_dm(contact);
-	if(PURPLE_IS_CONVERSATION(conversation)) {
-		purple_conversation_present(conversation);
-	} else {
-		purple_contact_create_dm_async(contact, NULL, NULL, NULL);
-	}
-}
-
-static void
-pidgin_notification_authorization_request_remove_cb(G_GNUC_UNUSED GtkButton *button,
-                                                    gpointer data)
-{
-	PidginNotificationAuthorizationRequest *request = data;
-
-	pidgin_notification_authorization_request_close(request);
-}
-
-/******************************************************************************
- * GObject Implementation
- *****************************************************************************/
-static void
-pidgin_notification_authorization_request_get_property(GObject *obj,
-                                                       guint param_id,
-                                                       GValue *value,
-                                                       GParamSpec *pspec)
-{
-	PidginNotificationAuthorizationRequest *request = NULL;
-
-	request = PIDGIN_NOTIFICATION_AUTHORIZATION_REQUEST(obj);
-
-	switch(param_id) {
-		case PROP_NOTIFICATION:
-			g_value_set_object(value,
-			                   pidgin_notification_authorization_request_get_notification(request));
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-			break;
-	}
-}
-
-static void
-pidgin_notification_authorization_request_set_property(GObject *obj,
-                                                       guint param_id,
-                                                       const GValue *value,
-                                                       GParamSpec *pspec)
-{
-	PidginNotificationAuthorizationRequest *request = NULL;
-
-	request = PIDGIN_NOTIFICATION_AUTHORIZATION_REQUEST(obj);
-
-	switch(param_id) {
-		case PROP_NOTIFICATION:
-			pidgin_notification_authorization_request_set_notification(request,
-			                                                           g_value_get_object(value));
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-			break;
-	}
-}
-
-static void
-pidgin_notification_authorization_request_dispose(GObject *obj) {
-	PidginNotificationAuthorizationRequest *request = NULL;
-
-	request = PIDGIN_NOTIFICATION_AUTHORIZATION_REQUEST(obj);
-
-	g_clear_object(&request->notification);
-
-	G_OBJECT_CLASS(pidgin_notification_authorization_request_parent_class)->dispose(obj);
-}
-
-static void
-pidgin_notification_authorization_request_init(PidginNotificationAuthorizationRequest *list)
-{
-	gtk_widget_init_template(GTK_WIDGET(list));
-}
-
-static void
-pidgin_notification_authorization_request_class_init(PidginNotificationAuthorizationRequestClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
-
-	obj_class->get_property = pidgin_notification_authorization_request_get_property;
-	obj_class->set_property = pidgin_notification_authorization_request_set_property;
-	obj_class->dispose = pidgin_notification_authorization_request_dispose;
-
-	/**
-	 * PidginNotificationAuthorizationRequest:notification:
-	 *
-	 * The [class@Purple.Notification] that this notification is for.
-	 *
-	 * Since: 3.0
-	 */
-	properties[PROP_NOTIFICATION] = g_param_spec_object(
-		"notification", "notification",
-		"The notification to display",
-		PURPLE_TYPE_NOTIFICATION,
-		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
-
-	gtk_widget_class_set_template_from_resource(
-	    widget_class,
-	    "/im/pidgin/Pidgin3/Notifications/authorizationrequest.ui"
-	);
-
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationAuthorizationRequest,
-	                                     icon);
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationAuthorizationRequest,
-	                                     accept);
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationAuthorizationRequest,
-	                                     deny);
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationAuthorizationRequest,
-	                                     message);
-
-	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_notification_authorization_request_accept_cb);
-	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_notification_authorization_request_deny_cb);
-	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_notification_authorization_request_message_cb);
-	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_notification_authorization_request_remove_cb);
-}
-
-/******************************************************************************
- * API
- *****************************************************************************/
-GtkWidget *
-pidgin_notification_authorization_request_new(PurpleNotification *notification) {
-	return g_object_new(
-		PIDGIN_TYPE_NOTIFICATION_AUTHORIZATION_REQUEST,
-		"notification", notification,
-		NULL);
-}
-
-PurpleNotification *
-pidgin_notification_authorization_request_get_notification(PidginNotificationAuthorizationRequest *request)
-{
-	g_return_val_if_fail(PIDGIN_IS_NOTIFICATION_AUTHORIZATION_REQUEST(request),
-	                     NULL);
-
-	return request->notification;
-}
--- a/pidgin/pidginnotificationauthorizationrequest.h	Tue Sep 17 00:55:06 2024 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Pidgin - Internet Messenger
- * Copyright (C) Pidgin Developers <devel@pidgin.im>
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <https://www.gnu.org/licenses/>.
- */
-
-#if !defined(PIDGIN_GLOBAL_HEADER_INSIDE) && !defined(PIDGIN_COMPILATION)
-# error "only <pidgin.h> may be included directly"
-#endif
-
-#ifndef PIDGIN_NOTIFICATION_AUTHORIZATION_REQUEST_H
-#define PIDGIN_NOTIFICATION_AUTHORIZATION_REQUEST_H
-
-#include <glib.h>
-
-#include <gtk/gtk.h>
-
-#include <adwaita.h>
-
-#include <purple.h>
-
-#include "pidginversion.h"
-
-G_BEGIN_DECLS
-
-/**
- * PidginNotificationAuthorizationRequest:
- *
- * #PidginNotificationAuthorizationRequest is a widget that displays
- * notifications from [class@Purple.NotificationManager] for authorization
- * requests.
- *
- * Since: 3.0
- */
-
-#define PIDGIN_TYPE_NOTIFICATION_AUTHORIZATION_REQUEST (pidgin_notification_authorization_request_get_type())
-
-PIDGIN_AVAILABLE_IN_3_0
-G_DECLARE_FINAL_TYPE(PidginNotificationAuthorizationRequest, pidgin_notification_authorization_request,
-                     PIDGIN, NOTIFICATION_AUTHORIZATION_REQUEST, AdwActionRow)
-
-/**
- * pidgin_notification_authorization_request_new:
- * @notification: A [class@Purple.Notification] to display.
- *
- * Creates a new #PidginNotificationAuthorizationRequest instance that will
- * display @notification.
- *
- * Returns: (transfer full): The new #PidginNotificationAuthorizationRequest
- *          instance.
- *
- * Since: 3.0
- */
-PIDGIN_AVAILABLE_IN_3_0
-GtkWidget *pidgin_notification_authorization_request_new(PurpleNotification *notification);
-
-/**
- * pidgin_notification_authorization_request_get_notification:
- * @request: The instance.
- *
- * Gets the [class@Purple.Notification] that @request is displaying.
- *
- * Returns: (transfer none): The notification.
- *
- * Since: 3.0
- */
-PIDGIN_AVAILABLE_IN_3_0
-PurpleNotification *pidgin_notification_authorization_request_get_notification(PidginNotificationAuthorizationRequest *request);
-
-G_END_DECLS
-
-#endif /* PIDGIN_NOTIFICATION_AUTHORIZATION_REQUEST_H */
--- a/pidgin/pidginnotificationconnectionerror.c	Tue Sep 17 00:55:06 2024 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-/*
- * Pidgin - Internet Messenger
- * Copyright (C) Pidgin Developers <devel@pidgin.im>
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <https://www.gnu.org/licenses/>.
- */
-
-#include <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "pidgin/pidginnotificationconnectionerror.h"
-
-struct _PidginNotificationConnectionError {
-	AdwActionRow parent;
-
-	PurpleNotification *notification;
-
-	GtkWidget *icon;
-	GtkWidget *reconnect;
-	GtkWidget *reenable;
-	GtkWidget *modify;
-};
-
-enum {
-	PROP_0,
-	PROP_NOTIFICATION,
-	N_PROPERTIES,
-};
-static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-
-G_DEFINE_FINAL_TYPE(PidginNotificationConnectionError,
-                    pidgin_notification_connection_error, ADW_TYPE_ACTION_ROW)
-
-/******************************************************************************
- * Helpers
- *****************************************************************************/
-static void
-pidgin_notification_connection_error_update(PidginNotificationConnectionError *error) {
-	PurpleAccount *account = NULL;
-	PurpleConnectionErrorInfo *info = NULL;
-	const gchar *icon_name = NULL, *account_id = NULL, *title = NULL;
-	gboolean enabled = FALSE;
-
-	g_return_if_fail(PIDGIN_IS_NOTIFICATION_CONNECTION_ERROR(error));
-
-	if(!PURPLE_IS_NOTIFICATION(error->notification)) {
-		adw_preferences_row_set_title(ADW_PREFERENCES_ROW(error),
-		                              _("Notification missing"));
-
-		gtk_image_set_from_icon_name(GTK_IMAGE(error->icon), NULL);
-		adw_action_row_set_subtitle(ADW_ACTION_ROW(error), NULL);
-
-		gtk_widget_set_visible(error->reconnect, FALSE);
-		gtk_widget_set_visible(error->reenable, FALSE);
-		gtk_widget_set_visible(error->modify, FALSE);
-
-		return;
-	}
-
-	account = purple_notification_get_account(error->notification);
-	if(!PURPLE_IS_ACCOUNT(account)) {
-		adw_preferences_row_set_title(ADW_PREFERENCES_ROW(error),
-		                              _("Notification is missing an account"));
-
-		gtk_image_set_from_icon_name(GTK_IMAGE(error->icon), NULL);
-		adw_action_row_set_subtitle(ADW_ACTION_ROW(error), NULL);
-
-		gtk_widget_set_visible(error->reconnect, FALSE);
-		gtk_widget_set_visible(error->reenable, FALSE);
-		gtk_widget_set_visible(error->modify, FALSE);
-
-		return;
-	}
-
-	/* Set the target for our actions. */
-	account_id = purple_account_get_id(account);
-	gtk_actionable_set_action_target(GTK_ACTIONABLE(error->reconnect), "s",
-	                                 account_id);
-	gtk_actionable_set_action_target(GTK_ACTIONABLE(error->reenable), "s",
-	                                 account_id);
-	gtk_actionable_set_action_target(GTK_ACTIONABLE(error->modify), "s",
-	                                 account_id);
-
-	/* Set the icon name if one was specified. */
-	icon_name = purple_notification_get_icon_name(error->notification);
-	if(icon_name != NULL) {
-		gtk_image_set_from_icon_name(GTK_IMAGE(error->icon), icon_name);
-	}
-
-	enabled = purple_account_get_enabled(account);
-
-	title = purple_notification_get_title(error->notification);
-	adw_preferences_row_set_title(ADW_PREFERENCES_ROW(error), title);
-
-	info = purple_notification_get_data(error->notification);
-	if(info != NULL) {
-		adw_action_row_set_subtitle(ADW_ACTION_ROW(error), info->description);
-	} else {
-		adw_action_row_set_subtitle(ADW_ACTION_ROW(error), NULL);
-	}
-
-	/* If the account is still enabled, reconnect should be visible, otherwise
-	 * re-enable should be visible.
-	 */
-	gtk_widget_set_visible(error->reconnect, enabled);
-	gtk_widget_set_visible(error->reenable, !enabled);
-}
-
-static void
-pidgin_notification_connection_error_set_notification(PidginNotificationConnectionError *error,
-                                                      PurpleNotification *notification)
-{
-	if(g_set_object(&error->notification, notification)) {
-		pidgin_notification_connection_error_update(error);
-
-		g_object_notify_by_pspec(G_OBJECT(error), properties[PROP_NOTIFICATION]);
-	}
-}
-
-/******************************************************************************
- * Callbacks
- *****************************************************************************/
-static void
-pidgin_notification_connection_error_remove_cb(G_GNUC_UNUSED GtkButton *button,
-                                               gpointer data)
-{
-	PidginNotificationConnectionError *error = data;
-	PurpleNotificationManager *manager = NULL;
-
-	purple_notification_delete(error->notification);
-
-	manager = purple_notification_manager_get_default();
-	purple_notification_manager_remove(manager, error->notification);
-}
-
-/******************************************************************************
- * GObject Implementation
- *****************************************************************************/
-static void
-pidgin_notification_connection_error_get_property(GObject *obj, guint param_id,
-                                                  GValue *value,
-                                                  GParamSpec *pspec)
-{
-	PidginNotificationConnectionError *error = NULL;
-
-	error = PIDGIN_NOTIFICATION_CONNECTION_ERROR(obj);
-
-	switch(param_id) {
-		case PROP_NOTIFICATION:
-			g_value_set_object(value,
-			                   pidgin_notification_connection_error_get_notification(error));
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-			break;
-	}
-}
-
-static void
-pidgin_notification_connection_error_set_property(GObject *obj, guint param_id,
-                                                  const GValue *value,
-                                                  GParamSpec *pspec)
-{
-	PidginNotificationConnectionError *error = NULL;
-
-	error = PIDGIN_NOTIFICATION_CONNECTION_ERROR(obj);
-
-	switch(param_id) {
-		case PROP_NOTIFICATION:
-			pidgin_notification_connection_error_set_notification(error,
-			                                                      g_value_get_object(value));
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-			break;
-	}
-}
-
-static void
-pidgin_notification_connection_error_dispose(GObject *obj) {
-	PidginNotificationConnectionError *error = NULL;
-
-	error = PIDGIN_NOTIFICATION_CONNECTION_ERROR(obj);
-
-	g_clear_object(&error->notification);
-
-	G_OBJECT_CLASS(pidgin_notification_connection_error_parent_class)->dispose(obj);
-}
-
-static void
-pidgin_notification_connection_error_init(PidginNotificationConnectionError *list)
-{
-	gtk_widget_init_template(GTK_WIDGET(list));
-}
-
-static void
-pidgin_notification_connection_error_class_init(PidginNotificationConnectionErrorClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
-
-	obj_class->get_property = pidgin_notification_connection_error_get_property;
-	obj_class->set_property = pidgin_notification_connection_error_set_property;
-	obj_class->dispose = pidgin_notification_connection_error_dispose;
-
-	/**
-	 * PidginNotificationConnectionError:notification:
-	 *
-	 * The [type@Purple.ConnectionErrorInfo] that this notification is for.
-	 *
-	 * Since: 3.0
-	 */
-	properties[PROP_NOTIFICATION] = g_param_spec_object(
-		"notification", "notification",
-		"The notification to display",
-		PURPLE_TYPE_NOTIFICATION,
-		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
-
-	gtk_widget_class_set_template_from_resource(
-	    widget_class,
-	    "/im/pidgin/Pidgin3/Notifications/connectionerror.ui"
-	);
-
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationConnectionError,
-	                                     icon);
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationConnectionError,
-	                                     reconnect);
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationConnectionError,
-	                                     reenable);
-	gtk_widget_class_bind_template_child(widget_class,
-	                                     PidginNotificationConnectionError,
-	                                     modify);
-
-	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_notification_connection_error_remove_cb);
-}
-
-/******************************************************************************
- * API
- *****************************************************************************/
-GtkWidget *
-pidgin_notification_connection_error_new(PurpleNotification *notification) {
-	return g_object_new(
-		PIDGIN_TYPE_NOTIFICATION_CONNECTION_ERROR,
-		"notification", notification,
-		NULL);
-}
-
-PurpleNotification *
-pidgin_notification_connection_error_get_notification(PidginNotificationConnectionError *error)
-{
-	g_return_val_if_fail(PIDGIN_IS_NOTIFICATION_CONNECTION_ERROR(error), NULL);
-
-	return error->notification;
-}
--- a/pidgin/pidginnotificationconnectionerror.h	Tue Sep 17 00:55:06 2024 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Pidgin - Internet Messenger
- * Copyright (C) Pidgin Developers <devel@pidgin.im>
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <https://www.gnu.org/licenses/>.
- */
-
-#if !defined(PIDGIN_GLOBAL_HEADER_INSIDE) && !defined(PIDGIN_COMPILATION)
-# error "only <pidgin.h> may be included directly"
-#endif
-
-#ifndef PIDGIN_NOTIFICATION_CONNECTION_ERROR_H
-#define PIDGIN_NOTIFICATION_CONNECTION_ERROR_H
-
-#include <glib.h>
-
-#include <gtk/gtk.h>
-
-#include <adwaita.h>
-
-#include <purple.h>
-
-#include "pidginversion.h"
-
-G_BEGIN_DECLS
-
-/**
- * PidginNotificationConnectionError:
- *
- * #PidginNotificationConnectionError is a widget that displays notifications from
- * [class@Purple.NotificationManager].
- *
- * Since: 3.0
- */
-
-#define PIDGIN_TYPE_NOTIFICATION_CONNECTION_ERROR (pidgin_notification_connection_error_get_type())
-
-PIDGIN_AVAILABLE_IN_3_0
-G_DECLARE_FINAL_TYPE(PidginNotificationConnectionError, pidgin_notification_connection_error,
-                     PIDGIN, NOTIFICATION_CONNECTION_ERROR, AdwActionRow)
-
-/**
- * pidgin_notification_connection_error_new:
- * @notification: A [class@Purple.Notification] to display.
- *
- * Creates a new #PidginNotificationConnectionError instance that will display
- * @notification.
- *
- * Returns: (transfer full): The new #PidginNotificationConnectionError
- *          instance.
- *
- * Since: 3.0
- */
-PIDGIN_AVAILABLE_IN_3_0
-GtkWidget *pidgin_notification_connection_error_new(PurpleNotification *notification);
-
-/**
- * pidgin_notification_connection_error_get_notification:
- * @error: The instance.
- *
- * Gets the [class@Purple.Notification] that @error is displaying.
- *
- * Returns: (transfer none): The notification.
- *
- * Since: 3.0
- */
-PIDGIN_AVAILABLE_IN_3_0
-PurpleNotification *pidgin_notification_connection_error_get_notification(PidginNotificationConnectionError *error);
-
-G_END_DECLS
-
-#endif /* PIDGIN_NOTIFICATION_CONNECTION_ERROR_H */
--- a/pidgin/pidginnotificationlist.c	Tue Sep 17 00:55:06 2024 -0500
+++ b/pidgin/pidginnotificationlist.c	Tue Sep 17 00:56:55 2024 -0500
@@ -24,12 +24,11 @@
 
 #include <purple.h>
 
-#include "pidgin/pidginnotificationlist.h"
+#include "pidginnotificationlist.h"
 
-#include "pidgin/pidginnotifiable.h"
-#include "pidgin/pidginnotificationaddcontact.h"
-#include "pidgin/pidginnotificationauthorizationrequest.h"
-#include "pidgin/pidginnotificationconnectionerror.h"
+#include "pidginnotifiable.h"
+#include "pidginnotification.h"
+#include "pidginnotificationaddcontact.h"
 
 enum {
 	PROP_0,
@@ -50,27 +49,6 @@
 /******************************************************************************
  * Helpers
  *****************************************************************************/
-static GtkWidget *
-pidgin_notification_generic_new(PurpleNotification *notification) {
-	GtkWidget *row = NULL;
-	GtkWidget *icon = NULL;
-
-	icon = gtk_image_new();
-	gtk_image_set_icon_size(GTK_IMAGE(icon), GTK_ICON_SIZE_LARGE);
-	g_object_bind_property(notification, "icon-name", icon, "icon-name",
-	                       G_BINDING_SYNC_CREATE);
-
-	row = adw_action_row_new();
-	adw_action_row_add_prefix(ADW_ACTION_ROW(row), icon);
-
-	g_object_bind_property(notification, "title", row, "title",
-	                       G_BINDING_SYNC_CREATE);
-	g_object_bind_property(notification, "subtitle", row, "subtitle",
-	                       G_BINDING_SYNC_CREATE);
-
-	return row;
-}
-
 static guint
 pidgin_notification_list_get_count(PidginNotificationList *list) {
 	g_return_val_if_fail(PIDGIN_IS_NOTIFICATION_LIST(list), 0);
@@ -125,20 +103,10 @@
 
 	notification = gtk_list_item_get_item(item);
 
-	switch(purple_notification_get_notification_type(notification)) {
-		case PURPLE_NOTIFICATION_TYPE_CONNECTION_ERROR:
-			widget = pidgin_notification_connection_error_new(notification);
-			break;
-		case PURPLE_NOTIFICATION_TYPE_AUTHORIZATION_REQUEST:
-			widget = pidgin_notification_authorization_request_new(notification);
-			break;
-		case PURPLE_NOTIFICATION_TYPE_ADD_CONTACT:
-			widget = pidgin_notification_add_contact_new(notification);
-			break;
-		case PURPLE_NOTIFICATION_TYPE_GENERIC:
-		default:
-			widget = pidgin_notification_generic_new(notification);
-			break;
+	if(PURPLE_IS_NOTIFICATION_ADD_CONTACT(notification)) {
+		widget = pidgin_notification_add_contact_new(notification);
+	} else {
+		widget = pidgin_notification_new(notification);
 	}
 
 	gtk_list_item_set_child(item, widget);
--- a/pidgin/resources/Notifications/addcontact.ui	Tue Sep 17 00:55:06 2024 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.38.2 
-
-Pidgin - Internet Messenger
-Copyright (C) Pidgin Developers <devel@pidgin.im>
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, see <https://www.gnu.org/licenses/>.
-
--->
-<interface>
-  <requires lib="gtk" version="4.0"/>
-  <requires lib="Adw" version="1.0"/>
-  <!-- interface-license-type gplv2 -->
-  <!-- interface-name Pidgin -->
-  <!-- interface-description Internet Messenger -->
-  <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
-  <template class="PidginNotificationAddContact" parent="AdwActionRow">
-    <property name="focusable">1</property>
-    <property name="activatable">0</property>
-    <property name="title-lines">3</property>
-    <property name="subtitle-lines">3</property>
-    <child type="prefix">
-      <object class="GtkImage" id="icon">
-        <property name="icon-size">large</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="add">
-        <property name="label" translatable="1">Add</property>
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <signal name="clicked" handler="pidgin_notification_add_contact_add_cb" object="PidginNotificationAddContact" swapped="no"/>
-        <style>
-          <class name="suggested-action"/>
-        </style>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="message">
-        <property name="label" translatable="1">Message</property>
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <signal name="clicked" handler="pidgin_notification_add_contact_message_cb" object="PidginNotificationAddContact" swapped="no"/>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="remove">
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="icon-name">edit-delete-symbolic</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <signal name="clicked" handler="pidgin_notification_add_contact_remove_cb" object="PidginNotificationAddContact" swapped="no"/>
-        <style>
-          <class name="flat"/>
-        </style>
-      </object>
-    </child>
-  </template>
-</interface>
--- a/pidgin/resources/Notifications/authorizationrequest.ui	Tue Sep 17 00:55:06 2024 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.38.2 
-
-Pidgin - Internet Messenger
-Copyright (C) Pidgin Developers <devel@pidgin.im>
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, see <https://www.gnu.org/licenses/>.
-
--->
-<interface>
-  <requires lib="gtk" version="4.0"/>
-  <requires lib="Adw" version="1.0"/>
-  <!-- interface-license-type gplv2 -->
-  <!-- interface-name Pidgin -->
-  <!-- interface-description Internet Messenger -->
-  <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
-  <template class="PidginNotificationAuthorizationRequest" parent="AdwActionRow">
-    <property name="focusable">1</property>
-    <property name="activatable">0</property>
-    <property name="title-lines">3</property>
-    <property name="subtitle-lines">3</property>
-    <child type="prefix">
-      <object class="GtkImage" id="icon">
-        <property name="icon-size">large</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="accept">
-        <property name="label" translatable="1">Accept</property>
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <signal name="clicked" handler="pidgin_notification_authorization_request_accept_cb" object="PidginNotificationAuthorizationRequest" swapped="no"/>
-        <style>
-          <class name="suggested-action"/>
-        </style>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="deny">
-        <property name="label" translatable="1">Deny</property>
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <signal name="clicked" handler="pidgin_notification_authorization_request_deny_cb" object="PidginNotificationAuthorizationRequest" swapped="no"/>
-        <style>
-          <class name="destructive-action"/>
-        </style>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="message">
-        <property name="label" translatable="1">Message</property>
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <signal name="clicked" handler="pidgin_notification_authorization_request_message_cb" object="PidginNotificationAuthorizationRequest" swapped="no"/>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="remove">
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="icon-name">edit-delete-symbolic</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <signal name="clicked" handler="pidgin_notification_authorization_request_remove_cb" object="PidginNotificationAuthorizationRequest" swapped="no"/>
-        <style>
-          <class name="flat"/>
-        </style>
-      </object>
-    </child>
-  </template>
-</interface>
--- a/pidgin/resources/Notifications/connectionerror.ui	Tue Sep 17 00:55:06 2024 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Pidgin - Internet Messenger
-Copyright (C) Pidgin Developers <devel@pidgin.im>
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this library; if not, see <https://www.gnu.org/licenses/>.
--->
-<interface>
-  <requires lib="gtk" version="4.0"/>
-  <requires lib="Adw" version="1.0"/>
-  <!-- interface-license-type gplv2 -->
-  <!-- interface-name Pidgin -->
-  <!-- interface-description Internet Messenger -->
-  <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
-  <template class="PidginNotificationConnectionError" parent="AdwActionRow">
-    <property name="focusable">1</property>
-    <property name="activatable">0</property>
-    <property name="subtitle-lines">3</property>
-    <child type="prefix">
-      <object class="GtkImage" id="icon">
-        <property name="icon-size">large</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="reconnect">
-        <property name="label" translatable="1">Reconnect</property>
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <property name="action-name">app.connect-account</property>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="reenable">
-        <property name="label" translatable="1">Re-enable</property>
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <property name="action-name">app.enable-account</property>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="modify">
-        <property name="label" translatable="1">Modify Account</property>
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <property name="action-name">app.edit-account</property>
-      </object>
-    </child>
-    <child>
-      <object class="GtkButton" id="remove">
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <property name="icon-name">edit-delete-symbolic</property>
-        <property name="halign">center</property>
-        <property name="valign">center</property>
-        <signal name="clicked" handler="pidgin_notification_connection_error_remove_cb" object="PidginNotificationConnectionError" swapped="no"/>
-        <style>
-          <class name="flat"/>
-        </style>
-      </object>
-    </child>
-  </template>
-</interface>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/resources/notification.ui	Tue Sep 17 00:56:55 2024 -0500
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Pidgin - Internet Messenger
+Copyright (C) Pidgin Developers <devel@pidgin.im>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <https://www.gnu.org/licenses/>.
+-->
+<interface>
+  <requires lib="gtk" version="4.0"/>
+  <requires lib="Adw" version="1.0"/>
+  <!-- interface-license-type gplv2 -->
+  <!-- interface-name Pidgin -->
+  <!-- interface-description Internet Messenger -->
+  <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+  <template class="PidginNotification" parent="GtkBox">
+    <property name="orientation">horizontal</property>
+    <property name="spacing">6</property>
+    <property name="margin-start">2</property>
+    <property name="margin-end">2</property>
+    <property name="margin-top">2</property>
+    <property name="margin-bottom">2</property>
+    <child>
+      <object class="GtkImage" id="icon">
+        <property name="icon-size">large</property>
+        <property name="halign">center</property>
+        <property name="valign">center</property>
+        <binding name="icon-name">
+          <lookup name="icon-name" type="PurpleNotification">
+            <lookup name="notification">PidginNotification</lookup>
+          </lookup>
+        </binding>
+      </object>
+    </child>
+    <child>
+      <object class="GtkBox" id="details">
+        <property name="halign">fill</property>
+        <property name="hexpand">true</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">0</property>
+        <property name="valign">center</property>
+        <child>
+          <object class="GtkLabel">
+            <property name="ellipsize">end</property>
+            <property name="lines">3</property>
+            <property name="xalign">0</property>
+            <binding name="label">
+              <lookup name="title" type="PurpleNotification">
+                <lookup name="notification">PidginNotification</lookup>
+              </lookup>
+            </binding>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="ellipsize">end</property>
+            <property name="lines">3</property>
+            <property name="xalign">0</property>
+            <binding name="label">
+              <lookup name="subtitle" type="PurpleNotification">
+                <lookup name="notification">PidginNotification</lookup>
+              </lookup>
+            </binding>
+            <binding name="visible">
+              <closure type="gboolean" function="pidgin_notification_show_subtitle">
+                <lookup name="subtitle" type="PurpleNotification">
+                  <lookup name="notification">PidginNotification</lookup>
+                </lookup>
+              </closure>
+            </binding>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkButton">
+        <property name="focusable">1</property>
+        <property name="receives-default">1</property>
+        <property name="icon-name">edit-delete-symbolic</property>
+        <property name="halign">center</property>
+        <property name="valign">center</property>
+        <property name="action-name">notification.close</property>
+        <style>
+          <class name="flat"/>
+        </style>
+      </object>
+    </child>
+  </template>
+</interface>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/resources/notificationaddcontact.ui	Tue Sep 17 00:56:55 2024 -0500
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Pidgin - Internet Messenger
+Copyright (C) Pidgin Developers <devel@pidgin.im>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+-->
+<interface>
+  <requires lib="gtk" version="4.0"/>
+  <!-- interface-license-type gplv2 -->
+  <!-- interface-name Pidgin -->
+  <!-- interface-description Internet Messenger -->
+  <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+  <template class="PidginNotificationAddContact" parent="PidginNotification">
+    <property name="child">
+      <object class="GtkBox">
+        <property name="orientation">horizontal</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkButton" id="add">
+            <property name="label" translatable="1">Add</property>
+            <property name="focusable">1</property>
+            <property name="receives-default">1</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="action-name">notification.add-contact</property>
+            <style>
+              <class name="suggested-action"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkButton" id="message">
+            <property name="label" translatable="1">Message</property>
+            <property name="focusable">1</property>
+            <property name="receives-default">1</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="action-name">notification.message</property>
+          </object>
+        </child>
+      </object>
+    </property>
+  </template>
+</interface>
--- a/pidgin/resources/pidgin.gresource.xml	Tue Sep 17 00:55:06 2024 -0500
+++ b/pidgin/resources/pidgin.gresource.xml	Tue Sep 17 00:56:55 2024 -0500
@@ -14,9 +14,6 @@
     <file compressed="true" preprocess="xml-stripblanks">Debug/debug.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">Keypad/keypad.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">Media/window.ui</file>
-    <file compressed="true" preprocess="xml-stripblanks">Notifications/addcontact.ui</file>
-    <file compressed="true" preprocess="xml-stripblanks">Notifications/authorizationrequest.ui</file>
-    <file compressed="true" preprocess="xml-stripblanks">Notifications/connectionerror.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">Prefs/away.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">Prefs/conversation.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">Prefs/credentials.ui</file>
@@ -38,6 +35,8 @@
     <file compressed="true" preprocess="xml-stripblanks">display-item.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">display-window.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">infopane.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks">notification.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks">notificationaddcontact.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">notificationlist.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">presenceicon.ui</file>
     <file compressed="true">style.css</file>

mercurial