summaryrefslogtreecommitdiff
path: root/finch
diff options
context:
space:
mode:
authorGary Kramlich <grim@reaperworld.com>2022-08-19 00:27:38 -0500
committerGary Kramlich <grim@reaperworld.com>2022-08-19 00:27:38 -0500
commit31664a332591cbcad1820e4cc6b7615433dd8d4c (patch)
tree0b4dcd158eb2060118b32d598f1fb2e92e1f6389 /finch
parent8d3daa061744f6da813e9da4ec91ebb7ce57c03d (diff)
downloadpidgin-31664a332591cbcad1820e4cc6b7615433dd8d4c.tar.gz
Implement notifications in Finch
This includes an Notifications item in the action list that opens the notifcations list. The notifications list shows the title of each notification and allows the user to open the notification and interact with it. Testing Done: Created some accounts that couldn't connect to make their connection errors show up as notifications. Reviewed at https://reviews.imfreedom.org/r/1602/
Diffstat (limited to 'finch')
-rw-r--r--finch/finchnotifications.c314
-rw-r--r--finch/finchnotifications.h60
-rw-r--r--finch/gntconn.c30
-rw-r--r--finch/gntui.c2
-rw-r--r--finch/meson.build2
5 files changed, 378 insertions, 30 deletions
diff --git a/finch/finchnotifications.c b/finch/finchnotifications.c
new file mode 100644
index 0000000000..ac6b8f564d
--- /dev/null
+++ b/finch/finchnotifications.c
@@ -0,0 +1,314 @@
+/*
+ * Finch - Universal Text Chat Client
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Finch 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 <config.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+
+#include <purple.h>
+
+#include <gnt.h>
+
+#include "finchnotifications.h"
+
+#include "gntaccount.h"
+
+static struct {
+ GntWidget *window;
+ GntWidget *list;
+} notifications;
+
+/*******************************************************************************
+ * Helpers
+ ******************************************************************************/
+static void
+finch_notifications_update(GntTree *list, GListModel *model) {
+ guint index = 0;
+
+ gnt_tree_remove_all(GNT_TREE(list));
+
+ for(index = 0; index < g_list_model_get_n_items(model); index++) {
+ PurpleNotification *notification = g_list_model_get_item(model, index);
+ GntTreeRow *row = NULL;
+
+ row = gnt_tree_create_row(list,
+ purple_notification_get_title(notification));
+ gnt_tree_add_row_last(list, notification, row, NULL);
+ }
+}
+
+static void
+finch_notification_delete_notification(PurpleNotification *notification) {
+ if(PURPLE_IS_NOTIFICATION(notification)) {
+ PurpleNotificationManager *manager = NULL;
+
+ manager = purple_notification_manager_get_default();
+
+ purple_notification_manager_remove(manager, notification);
+ }
+}
+
+/*******************************************************************************
+ * Finch Notification Callbacks
+ ******************************************************************************/
+static void
+finch_notification_delete(G_GNUC_UNUSED GntWidget *widget, gpointer data) {
+ PurpleNotification *notification = g_object_get_data(data, "notification");
+
+ finch_notification_delete_notification(notification);
+
+ gnt_widget_destroy(GNT_WIDGET(data));
+}
+
+static void
+finch_notification_reconnect_account(G_GNUC_UNUSED GntWidget *widget,
+ gpointer data)
+{
+ PurpleNotification *notification = g_object_get_data(data, "notification");
+ PurpleAccount *account = purple_notification_get_account(notification);
+
+ if(PURPLE_IS_ACCOUNT(account)) {
+ purple_account_connect(account);
+ }
+
+ gnt_widget_destroy(GNT_WIDGET(data));
+}
+
+static void
+finch_notification_reenable_account(G_GNUC_UNUSED GntWidget *widget,
+ gpointer data)
+{
+ PurpleNotification *notification = g_object_get_data(data, "notification");
+ PurpleAccount *account = purple_notification_get_account(notification);
+
+ if(PURPLE_IS_ACCOUNT(account)) {
+ purple_account_set_enabled(account, TRUE);
+ }
+
+ gnt_widget_destroy(GNT_WIDGET(data));
+}
+
+static void
+finch_notification_modify_account(G_GNUC_UNUSED GntWidget *widget,
+ gpointer data)
+{
+ PurpleNotification *notification = g_object_get_data(data, "notification");
+ PurpleAccount *account = purple_notification_get_account(notification);
+
+ if(PURPLE_IS_ACCOUNT(account)) {
+ finch_account_dialog_show(account);
+ }
+
+ gnt_widget_destroy(GNT_WIDGET(data));
+}
+
+/*******************************************************************************
+ * Finch Notification API
+ ******************************************************************************/
+static void
+finch_notification_show(PurpleNotification *notification) {
+ GntWidget *dialog = NULL, *label = NULL, *hbox = NULL, *button = NULL;
+ PurpleAccount *account = NULL;
+ PurpleNotificationType type;
+ gpointer data = NULL;
+
+ account = purple_notification_get_account(notification);
+
+ dialog = gnt_box_new(FALSE, TRUE);
+ gnt_box_set_toplevel(GNT_BOX(dialog), TRUE);
+ gnt_box_set_alignment(GNT_BOX(dialog), GNT_ALIGN_MID);
+ g_object_set_data(G_OBJECT(dialog), "notification", notification);
+
+ label = gnt_label_new(purple_notification_get_title(notification));
+ gnt_box_add_widget(GNT_BOX(dialog), label);
+
+ hbox = gnt_box_new(FALSE, FALSE);
+
+ type = purple_notification_get_notification_type(notification);
+ data = purple_notification_get_data(notification);
+
+ if(type == PURPLE_NOTIFICATION_TYPE_GENERIC) {
+ gnt_box_set_title(GNT_BOX(dialog),
+ purple_notification_get_title(notification));
+ label = gnt_label_new(purple_notification_get_data(notification));
+ } else if(type == PURPLE_NOTIFICATION_TYPE_CONNECTION_ERROR) {
+ PurpleConnectionErrorInfo *info = data;
+
+ /* Set the title and name */
+ gnt_box_set_title(GNT_BOX(dialog), _("Connection Error"));
+
+ /* Add the connection error reason. */
+ label = gnt_label_new(info->description);
+ gnt_box_add_widget(GNT_BOX(dialog), label);
+
+ /* Add the buttons. */
+ if(purple_account_get_enabled(account)) {
+ button = gnt_button_new(_("Reconnect"));
+ g_signal_connect(button, "activate",
+ G_CALLBACK(finch_notification_reconnect_account),
+ dialog);
+ } else {
+ button = gnt_button_new(_("Re-enable"));
+ g_signal_connect(button, "activate",
+ G_CALLBACK(finch_notification_reenable_account),
+ dialog);
+ }
+ gnt_box_add_widget(GNT_BOX(hbox), button);
+
+ button = gnt_button_new(_("Modify Account"));
+ g_signal_connect(button, "activate",
+ G_CALLBACK(finch_notification_modify_account),
+ dialog);
+ gnt_box_add_widget(GNT_BOX(hbox), button);
+ }
+
+ gnt_box_add_widget(GNT_BOX(dialog), hbox);
+
+ button = gnt_button_new(_("Delete"));
+ g_signal_connect(button, "activate",
+ G_CALLBACK(finch_notification_delete), dialog);
+ gnt_box_add_widget(GNT_BOX(hbox), button);
+
+ gnt_widget_show(dialog);
+}
+
+/*******************************************************************************
+ * Callbacks
+ ******************************************************************************/
+static void
+finch_notifications_changed_cb(GListModel *model,
+ G_GNUC_UNUSED guint position,
+ G_GNUC_UNUSED guint removed,
+ guint added,
+ gpointer data)
+{
+ finch_notifications_update(data, model);
+
+ if(added > 0) {
+ gnt_widget_set_urgent(notifications.window);
+ }
+}
+
+static void
+finch_notifications_open_cb(G_GNUC_UNUSED GntWidget *w, gpointer data) {
+ PurpleNotification *notification = NULL;
+
+ notification = gnt_tree_get_selection_data(GNT_TREE(notifications.list));
+ if(!PURPLE_IS_NOTIFICATION(notification)) {
+ return;
+ }
+
+ finch_notification_show(notification);
+}
+
+static void
+finch_notifications_delete_cb(G_GNUC_UNUSED GntWidget *widget, gpointer data) {
+ PurpleNotification *notification = NULL;
+
+ notification = gnt_tree_get_selection_data(GNT_TREE(notifications.list));
+
+ finch_notification_delete_notification(notification);
+}
+
+
+static void
+finch_notifications_activate_cb(G_GNUC_UNUSED GntWidget *w,
+ G_GNUC_UNUSED gpointer data)
+{
+ PurpleNotification *notification = NULL;
+
+ notification = gnt_tree_get_selection_data(GNT_TREE(notifications.list));
+
+ finch_notification_show(notification);
+}
+
+/*******************************************************************************
+ * Public API
+ ******************************************************************************/
+void
+finch_notifications_window_show(void) {
+ PurpleNotificationManager *manager = NULL;
+ GntWidget *wid, *box;
+ GListModel *model = NULL;
+
+ if(notifications.window) {
+ gnt_window_present(notifications.window);
+
+ return;
+ }
+
+ notifications.window = gnt_vbox_new(FALSE);
+ gnt_box_set_toplevel(GNT_BOX(notifications.window), TRUE);
+ gnt_box_set_fill(GNT_BOX(notifications.window), TRUE);
+ gnt_box_set_title(GNT_BOX(notifications.window), _("Notifications"));
+ gnt_box_set_alignment(GNT_BOX(notifications.window), GNT_ALIGN_MID);
+ gnt_box_set_pad(GNT_BOX(notifications.window), 0);
+ gnt_widget_set_name(notifications.window, "notifications");
+
+ /* Create the box that lists all of the notifications. */
+ notifications.list = gnt_tree_new_with_columns(1);
+ gnt_tree_set_compare_func(GNT_TREE(notifications.list),
+ purple_notification_compare);
+ gnt_widget_set_has_border(notifications.list, FALSE);
+ gnt_box_add_widget(GNT_BOX(notifications.window), notifications.list);
+ g_signal_connect(notifications.list, "activate",
+ G_CALLBACK(finch_notifications_activate_cb), NULL);
+
+ /* Get the notification manager to get the model and populate the list. */
+ manager = purple_notification_manager_get_default();
+ model = purple_notification_manager_get_model(manager);
+ finch_notifications_update(GNT_TREE(notifications.list), model);
+ g_signal_connect_object(model, "items-changed",
+ G_CALLBACK(finch_notifications_changed_cb),
+ notifications.list, 0);
+
+ gnt_box_add_widget(GNT_BOX(notifications.window), gnt_line_new(FALSE));
+
+ box = gnt_hbox_new(FALSE);
+ gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID);
+ gnt_box_set_fill(GNT_BOX(box), FALSE);
+
+ wid = gnt_button_new(_("Open"));
+ g_signal_connect(wid, "activate", G_CALLBACK(finch_notifications_open_cb),
+ NULL);
+ gnt_box_add_widget(GNT_BOX(box), wid);
+
+ wid = gnt_button_new(_("Delete"));
+ g_signal_connect(wid, "activate", G_CALLBACK(finch_notifications_delete_cb),
+ NULL);
+ gnt_box_add_widget(GNT_BOX(box), wid);
+
+ gnt_box_add_widget(GNT_BOX(notifications.window), box);
+
+ gnt_widget_show(notifications.window);
+}
+
+void
+finch_notifications_init(void) {
+}
+
+void
+finch_notifications_uninit(void) {
+ g_clear_pointer(&notifications.window, gnt_widget_destroy);
+}
diff --git a/finch/finchnotifications.h b/finch/finchnotifications.h
new file mode 100644
index 0000000000..67c7f6ca73
--- /dev/null
+++ b/finch/finchnotifications.h
@@ -0,0 +1,60 @@
+/*
+ * Finch - Universal Text Chat Client
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Finch 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(FINCH_GLOBAL_HEADER_INSIDE) && !defined(FINCH_COMPILATION)
+# error "only <finch.h> may be included directly"
+#endif
+
+#ifndef FINCH_NOTIFICATIONS_H
+#define FINCH_NOTIFICATIONS_H
+
+#include <purple.h>
+
+G_BEGIN_DECLS
+
+/**
+ * finch_notifications_init:
+ *
+ * Perform necessary initializations.
+ *
+ * Since: 3.0.0
+ */
+void finch_notifications_init(void);
+
+/**
+ * finch_notifications_uninit:
+ *
+ * Perform necessary uninitialization.
+ */
+void finch_notifications_uninit(void);
+
+/**
+ * finch_notifications_window_show:
+ *
+ * Show the notifications window.
+ */
+void finch_notifications_window_show(void);
+
+G_END_DECLS
+
+#endif /* FINCH_NOTIFICATIONS_H */
+
diff --git a/finch/gntconn.c b/finch/gntconn.c
index f09949819b..e5fcdec299 100644
--- a/finch/gntconn.c
+++ b/finch/gntconn.c
@@ -83,18 +83,6 @@ do_signon(gpointer data)
}
static void
-ce_modify_account_cb(PurpleAccount *account)
-{
- finch_account_dialog_show(account);
-}
-
-static void
-ce_enable_account_cb(PurpleAccount *account)
-{
- purple_account_set_enabled(account, TRUE);
-}
-
-static void
finch_connection_report_disconnect(PurpleConnection *gc, PurpleConnectionError reason,
const char *text)
{
@@ -115,24 +103,6 @@ finch_connection_report_disconnect(PurpleConnection *gc, PurpleConnectionError r
}
info->timeout = g_timeout_add_seconds(info->delay, do_signon, account);
} else {
- char *act, *primary, *secondary;
- act = g_strdup_printf(_("%s (%s)"), purple_account_get_username(account),
- purple_account_get_protocol_name(account));
-
- primary = g_strdup_printf(_("%s disconnected."), act);
- secondary = g_strdup_printf(_("%s\n\n"
- "Finch will not attempt to reconnect the account until you "
- "correct the error and re-enable the account."), text);
-
- purple_request_action(account, NULL, primary, secondary, 2,
- purple_request_cpar_from_account(account), account, 3,
- _("OK"), NULL,
- _("Modify Account"), G_CALLBACK(ce_modify_account_cb),
- _("Re-enable Account"), G_CALLBACK(ce_enable_account_cb));
-
- g_free(act);
- g_free(primary);
- g_free(secondary);
purple_account_set_enabled(account, FALSE);
}
}
diff --git a/finch/gntui.c b/finch/gntui.c
index 11ee3752b6..faf7d8a176 100644
--- a/finch/gntui.c
+++ b/finch/gntui.c
@@ -28,6 +28,7 @@
#include "gntui.h"
+#include "finchnotifications.h"
#include "gntaccount.h"
#include "gntblist.h"
#include "gntconn.h"
@@ -132,6 +133,7 @@ void finch_ui_init()
gnt_register_action(_("Accounts"), finch_accounts_show_all);
gnt_register_action(_("Buddy List"), finch_blist_show);
+ gnt_register_action(_("Notifications"), finch_notifications_window_show);
gnt_register_action(_("Debug Window"), finch_debug_window_show);
gnt_register_action(_("File Transfers"), finch_xfer_dialog_show);
gnt_register_action(_("Plugins"), finch_plugins_show_all);
diff --git a/finch/meson.build b/finch/meson.build
index 8a3bc66125..1165a2e6c0 100644
--- a/finch/meson.build
+++ b/finch/meson.build
@@ -84,6 +84,7 @@ endif
libfinch_SOURCES = [
+ 'finchnotifications.c',
'gntaccount.c',
'gntblist.c',
'gntconn.c',
@@ -105,6 +106,7 @@ libfinch_SOURCES = [
]
libfinch_headers = [
+ 'finchnotifications.h',
'gntaccount.h',
'gntblist.h',
'gntconn.h',