Skip to content

Commit 20eed34

Browse files
committed
[linux] Implemented close and destroy method. #2
1 parent e25fdf0 commit 20eed34

File tree

3 files changed

+119
-11
lines changed

3 files changed

+119
-11
lines changed

lib/src/local_notifier.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class LocalNotifier {
7474

7575
/// Immediately shows the notification to the user.
7676
Future<void> notify(LocalNotification notification) async {
77-
if (Platform.isWindows && _appName == null) {
77+
if ((Platform.isLinux || Platform.isWindows) && _appName == null) {
7878
throw Exception(
7979
'Missing appName, must call `localNotifier.setAppName` to set.',
8080
);

linux/local_notifier_plugin.cc

Lines changed: 117 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,25 @@
44
#include <gtk/gtk.h>
55
#include <sys/utsname.h>
66

7+
#include <algorithm>
78
#include <cstring>
9+
#include <map>
10+
#include <vector>
811

912
#include <libnotify/notify.h>
1013

1114
#define LOCAL_NOTIFIER_PLUGIN(obj) \
1215
(G_TYPE_CHECK_INSTANCE_CAST((obj), local_notifier_plugin_get_type(), \
1316
LocalNotifierPlugin))
1417

18+
LocalNotifierPlugin* plugin_instance;
19+
std::map<std::string, int> notification_id_map_;
20+
std::vector<NotifyNotification*> notifications_;
21+
1522
struct _LocalNotifierPlugin {
1623
GObject parent_instance;
1724
FlPluginRegistrar* registrar;
25+
FlMethodChannel* channel;
1826
};
1927

2028
G_DEFINE_TYPE(LocalNotifierPlugin, local_notifier_plugin, g_object_get_type())
@@ -32,17 +40,113 @@ GdkWindow* get_gdk_window(LocalNotifierPlugin* self) {
3240
return gtk_widget_get_window(GTK_WIDGET(get_window(self)));
3341
}
3442

43+
const char* _get_identifier(NotifyNotification* notification) {
44+
int notification_id = -1;
45+
g_object_get(G_OBJECT(notification), "id", &notification_id, NULL);
46+
47+
auto result = std::find_if(
48+
notification_id_map_.begin(), notification_id_map_.end(),
49+
[notification_id](const auto& e) { return e.second == notification_id; });
50+
51+
if (result != notification_id_map_.end())
52+
return result->first.c_str();
53+
54+
return "";
55+
}
56+
57+
void _on_notification_close(NotifyNotification* notification,
58+
gpointer user_data) {
59+
const char* identifier = _get_identifier(notification);
60+
61+
g_autoptr(FlValue) result_data = fl_value_new_map();
62+
fl_value_set_string_take(result_data, "notificationId",
63+
fl_value_new_string(identifier));
64+
fl_method_channel_invoke_method(plugin_instance->channel,
65+
"onLocalNotificationClose", result_data,
66+
nullptr, nullptr, nullptr);
67+
}
68+
69+
void _action_callback(NotifyNotification* notification,
70+
char* action,
71+
gpointer user_data) {
72+
const char* identifier = _get_identifier(notification);
73+
74+
gint index = GPOINTER_TO_INT(user_data);
75+
76+
g_autoptr(FlValue) result_data = fl_value_new_map();
77+
fl_value_set_string_take(result_data, "notificationId",
78+
fl_value_new_string(identifier));
79+
fl_value_set_string_take(result_data, "actionIndex", fl_value_new_int(index));
80+
fl_method_channel_invoke_method(plugin_instance->channel,
81+
"onLocalNotificationClickAction", result_data,
82+
nullptr, nullptr, nullptr);
83+
}
84+
3585
static FlMethodResponse* notify(LocalNotifierPlugin* self, FlValue* args) {
86+
const gchar* app_name =
87+
fl_value_get_string(fl_value_lookup_string(args, "appName"));
88+
89+
const gchar* identifier =
90+
fl_value_get_string(fl_value_lookup_string(args, "identifier"));
3691
const gchar* title =
3792
fl_value_get_string(fl_value_lookup_string(args, "title"));
38-
const gchar* subtitle =
39-
fl_value_get_string(fl_value_lookup_string(args, "subtitle"));
40-
// const gchar *body = fl_value_get_string(fl_value_lookup_string(args,
41-
// "body"));
93+
const gchar* body = fl_value_get_string(fl_value_lookup_string(args, "body"));
94+
FlValue* actions_value = fl_value_lookup_string(args, "actions");
95+
96+
notify_init(app_name);
97+
NotifyNotification* notification = notify_notification_new(title, body, 0);
98+
notify_notification_set_app_name(notification, app_name);
99+
100+
for (gint i = 0; i < fl_value_get_length(actions_value); i++) {
101+
FlValue* action_item_value = fl_value_get_list_value(actions_value, i);
102+
const char* action_text =
103+
fl_value_get_string(fl_value_lookup_string(action_item_value, "text"));
104+
105+
notify_notification_add_action(notification, action_text, // action
106+
action_text, // label
107+
(NotifyActionCallback)_action_callback,
108+
GINT_TO_POINTER(i), // user_data,
109+
NULL);
110+
}
111+
112+
notify_notification_show(notification, 0);
113+
114+
g_signal_connect(notification, "closed", G_CALLBACK(_on_notification_close),
115+
NULL);
116+
117+
notifications_.push_back(notification);
42118

43-
notify_init("local_notifier");
44-
NotifyNotification* n = notify_notification_new(title, subtitle, 0);
45-
notify_notification_show(n, 0);
119+
int notification_id = -1;
120+
g_object_get(G_OBJECT(notification), "id", &notification_id, NULL);
121+
122+
notification_id_map_.erase(identifier);
123+
notification_id_map_.insert(
124+
std::pair<std::string, int>(identifier, notification_id));
125+
126+
g_autoptr(FlValue) result_data = fl_value_new_map();
127+
fl_value_set_string_take(result_data, "notificationId",
128+
fl_value_new_string(identifier));
129+
fl_method_channel_invoke_method(plugin_instance->channel,
130+
"onLocalNotificationShow", result_data,
131+
nullptr, nullptr, nullptr);
132+
133+
return FL_METHOD_RESPONSE(
134+
fl_method_success_response_new(fl_value_new_bool(true)));
135+
}
136+
137+
static FlMethodResponse* close(LocalNotifierPlugin* self, FlValue* args) {
138+
const gchar* identifier =
139+
fl_value_get_string(fl_value_lookup_string(args, "identifier"));
140+
141+
for (int i = 0; i < notifications_.size(); i++) {
142+
NotifyNotification* notification = notifications_[i];
143+
const char* item_identifier = _get_identifier(notification);
144+
if (strcmp(identifier, item_identifier) == 0) {
145+
notify_notification_close(notification, NULL);
146+
notifications_.erase(notifications_.begin() + i);
147+
break;
148+
}
149+
}
46150

47151
return FL_METHOD_RESPONSE(
48152
fl_method_success_response_new(fl_value_new_bool(true)));
@@ -58,6 +162,8 @@ static void local_notifier_plugin_handle_method_call(
58162
FlValue* args = fl_method_call_get_args(method_call);
59163
if (strcmp(method, "notify") == 0) {
60164
response = notify(self, args);
165+
} else if (strcmp(method, "close") == 0) {
166+
response = close(self, args);
61167
} else {
62168
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
63169
}
@@ -90,11 +196,13 @@ void local_notifier_plugin_register_with_registrar(
90196
plugin->registrar = FL_PLUGIN_REGISTRAR(g_object_ref(registrar));
91197

92198
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
93-
g_autoptr(FlMethodChannel) channel =
199+
plugin->channel =
94200
fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),
95201
"local_notifier", FL_METHOD_CODEC(codec));
96202
fl_method_channel_set_method_call_handler(
97-
channel, method_call_cb, g_object_ref(plugin), g_object_unref);
203+
plugin->channel, method_call_cb, g_object_ref(plugin), g_object_unref);
204+
205+
plugin_instance = plugin;
98206

99207
g_object_unref(plugin);
100208
}

test/local_notifier_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'package:flutter/services.dart';
22
import 'package:flutter_test/flutter_test.dart';
3-
import 'package:local_notifier/local_notifier.dart';
3+
// import 'package:local_notifier/local_notifier.dart';
44

55
void main() {
66
const MethodChannel channel = MethodChannel('local_notifier');

0 commit comments

Comments
 (0)