From: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Date: Fri, 20 May 2016 14:27:57 +0800
Subject: lp341684_device_sensitive_disconnect_notify

---
 src/applet-device-wifi.c |   2 +
 src/applet.c             | 142 +++++++++++++++++++++++++++++++++++++++++++++--
 src/applet.h             |   5 +-
 3 files changed, 143 insertions(+), 6 deletions(-)

diff --git a/src/applet-device-wifi.c b/src/applet-device-wifi.c
index 7af9c0f..b94554d 100644
--- a/src/applet-device-wifi.c
+++ b/src/applet-device-wifi.c
@@ -1322,6 +1322,8 @@ wifi_notify_connected (NMDevice *device,
 
 	ap = _active_ap_get (applet, device);
 
+	g_object_set_data_full (G_OBJECT(device), "canonical-last-essid", g_strdup (esc_ssid), (GDestroyNotify) g_free);
+
 	esc_ssid = get_ssid_utf8 (ap);
 
 	if (!ap)
diff --git a/src/applet.c b/src/applet.c
index 9f0a433..552fbf9 100644
--- a/src/applet.c
+++ b/src/applet.c
@@ -155,6 +155,19 @@ get_device_class_from_connection (NMConnection *connection, NMApplet *applet)
 	return NULL;
 }
 
+struct _OfflineNotificationContextInfo {
+	NMState state;
+	NMDeviceState device_state;
+	NMDeviceStateReason device_state_reason;
+	NMDeviceType device_type;
+	gchar* title;
+	gchar* text;
+	const gchar* icon;
+	NotifyUrgency urgency;
+};
+
+typedef struct _OfflineNotificationContextInfo OfflineNotificationContextInfo;
+
 static NMActiveConnection *
 applet_get_best_activating_connection (NMApplet *applet, NMDevice **device)
 {
@@ -2132,6 +2145,64 @@ applet_get_exported_connection_for_device (NMDevice *device, NMApplet *applet)
 	return NULL;
 }
 
+static gboolean
+select_merged_notification_text (OfflineNotificationContextInfo *info)
+{
+	info->urgency = NOTIFY_URGENCY_LOW;
+	/* only do something if this is about full offline state */
+	if(info->state != NM_STATE_UNKNOWN || info->device_state != NM_DEVICE_STATE_UNKNOWN) {
+		info->urgency = NOTIFY_URGENCY_NORMAL;
+		if (!info->text)
+			info->text = g_strdup (_("Network"));
+	        if (info->state == NM_STATE_DISCONNECTED || info->state == NM_STATE_ASLEEP) {
+			info->title = _("Disconnected - you are now offline");
+		} else
+			info->title = _("Disconnected");
+
+		switch (info->device_type) {
+			case NM_DEVICE_TYPE_ETHERNET:
+				info->icon = "notification-network-ethernet-disconnected";
+				break;
+			case NM_DEVICE_TYPE_WIFI:
+				info->icon = "notification-network-wireless-disconnected";
+				break;
+			case NM_DEVICE_TYPE_MODEM:
+				info->icon = "notification-gsm-disconnected";
+				break;
+			default:
+				info->icon = "nm-no-connection";
+				break;
+		}
+		g_debug("going for offline with icon: %s", info->icon);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+foo_online_offline_deferred_notify (gpointer user_data)
+{
+	NMApplet *applet = NM_APPLET (user_data);
+	OfflineNotificationContextInfo *info = applet->notification_queue_data;
+	if(select_merged_notification_text (info))
+		if (!g_settings_get_boolean (applet->gsettings, PREF_DISABLE_DISCONNECTED_NOTIFICATIONS))
+			applet_do_notify (applet, info->urgency, info->title,
+			                  info->text, info->icon,
+			                  PREF_DISABLE_DISCONNECTED_NOTIFICATIONS,
+			                  _("Don't show this message again"),
+			                  notify_dont_show_cb,
+			                  applet);
+	else
+		g_debug("no notification because merged found that we have nothing to say (e.g. not offline)");
+	if (info->text)
+		g_free (info->text);
+	info->text = NULL;
+	g_free (applet->notification_queue_data);
+	applet->notification_queue_data = NULL;
+	applet->deferred_id = 0;
+	return FALSE;
+}
+
 static void
 applet_common_device_state_changed (NMDevice *device,
                                     NMDeviceState new_state,
@@ -2146,6 +2217,54 @@ applet_common_device_state_changed (NMDevice *device,
 
 
 	switch (new_state) {
+	case NM_DEVICE_STATE_FAILED:
+	case NM_DEVICE_STATE_DISCONNECTED:
+	case NM_DEVICE_STATE_UNMANAGED:
+	case NM_DEVICE_STATE_UNAVAILABLE:
+	{
+		if (old_state != NM_DEVICE_STATE_FAILED &&
+		    old_state != NM_DEVICE_STATE_UNKNOWN &&
+		    old_state != NM_DEVICE_STATE_DISCONNECTED &&
+		    old_state != NM_DEVICE_STATE_UNMANAGED &&
+		    old_state != NM_DEVICE_STATE_UNAVAILABLE) {
+	                OfflineNotificationContextInfo *info = applet->notification_queue_data;
+			if (!info) {
+				info = g_new0(OfflineNotificationContextInfo, 1);
+				applet->notification_queue_data = info;
+			}
+
+	                info->device_state = new_state;
+	                info->device_state_reason = reason;
+			if (info->text) {
+				g_free(info->text);
+				info->text = NULL;
+			}
+			if (NM_IS_DEVICE_WIFI (device)) {
+				info->device_type = NM_DEVICE_TYPE_WIFI;
+				info->text = g_strdup(g_object_get_data (G_OBJECT(device), "canonical-last-essid"));
+				if (!info->text)
+					info->text = g_strdup (_("Wireless network"));
+			} else if (NM_IS_DEVICE_ETHERNET (device)) {
+				info->device_type = NM_DEVICE_TYPE_ETHERNET;
+				info->text = g_strdup(_("Ethernet network"));
+			} else if (NM_IS_DEVICE_MODEM (device)) {
+				info->device_type = NM_DEVICE_TYPE_MODEM;
+				info->text = g_strdup (_("Modem network"));
+			} else {
+				info->device_type = NM_DEVICE_TYPE_UNKNOWN;
+				info->text = g_strdup (_("Network"));
+			}
+
+	                if (applet->deferred_id)
+	                        g_source_remove (applet->deferred_id);
+	                applet->deferred_id = g_timeout_add (1000, foo_online_offline_deferred_notify, applet);
+
+			clear_animation_timeout (applet);
+		} else {
+			g_debug ("old state indicates that this was not a disconnect %d", old_state);
+		}
+		break;
+	}
 	case NM_DEVICE_STATE_PREPARE:
 	case NM_DEVICE_STATE_CONFIG:
 	case NM_DEVICE_STATE_NEED_AUTH:
@@ -2232,13 +2351,26 @@ foo_client_state_changed_cb (NMClient *client, GParamSpec *pspec, gpointer user_
 {
 	NMApplet *applet = NM_APPLET (user_data);
 
+	g_debug("foo_client_state_changed_cb");
 	switch (nm_client_get_state (client)) {
 	case NM_STATE_DISCONNECTED:
-		applet_do_notify_with_pref (applet, _("Disconnected"),
-		                            _("The network connection has been disconnected."),
-		                            "nm-no-connection",
-		                            PREF_DISABLE_DISCONNECTED_NOTIFICATIONS);
-		break;
+	case NM_STATE_ASLEEP:
+	{
+		OfflineNotificationContextInfo *info = applet->notification_queue_data;
+		if (!info) {
+			info = g_new0(OfflineNotificationContextInfo, 1);
+			applet->notification_queue_data = info;
+		}
+
+		info->state = nm_client_get_state (client);
+		select_merged_notification_text (info);
+
+		if (applet->deferred_id)
+			g_source_remove (applet->deferred_id);
+		applet->deferred_id = g_timeout_add (1000, foo_online_offline_deferred_notify, applet);
+
+		/* Fall through */
+	}
 	default:
 		break;
 	}
diff --git a/src/applet.h b/src/applet.h
index 5392a3e..5978693 100644
--- a/src/applet.h
+++ b/src/applet.h
@@ -145,8 +145,11 @@ typedef struct {
 
 	/* Tracker objects for secrets requests */
 	GSList *        secrets_reqs;
-
 	guint           wifi_scan_id;
+
+	gpointer	notification_queue_data;
+	guint		deferred_id;
+
 } NMApplet;
 
 typedef void (*AppletNewAutoConnectionCallback) (NMConnection *connection,
