diff --git a/po/POTFILES.in b/po/POTFILES.in
index b36608be..2d0d908d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -76,6 +76,7 @@ src/client/folder-list/folder-list-inboxes-branch.vala
src/client/folder-list/folder-list-search-branch.vala
src/client/folder-list/folder-list-special-grouping.vala
src/client/folder-list/folder-list-tree.vala
+src/client/notification/in-app-notification.vala
src/client/notification/libmessagingmenu.vala
src/client/notification/libnotify.vala
src/client/notification/new-messages-indicator.vala
@@ -421,6 +422,7 @@ ui/find_bar.glade
ui/folder-popover.ui
ui/gtk/help-overlay.ui
ui/gtk/menus.ui
+ui/in-app-notification.ui
ui/login.glade
ui/main-toolbar.ui
ui/main-toolbar-menus.ui
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3c4d50bf..12fba45f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -403,6 +403,7 @@ client/folder-list/folder-list-inbox-folder-entry.vala
client/folder-list/folder-list-search-branch.vala
client/folder-list/folder-list-special-grouping.vala
+client/notification/in-app-notification.vala
client/notification/libmessagingmenu.vala
client/notification/libnotify.vala
client/notification/new-messages-indicator.vala
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 33b4eca4..159dd5af 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -2713,6 +2713,13 @@ public class GearyController : Geary.BaseObject {
}
private void on_sent(Geary.RFC822.Message rfc822) {
+ // Translators: The label for an in-app notification. The
+ // string substitution is a list of recipients of the email.
+ string message = _(
+ "Successfully sent mail to %s."
+ ).printf(EmailUtil.to_short_recipient_display(rfc822.to));
+ InAppNotification notification = new InAppNotification(message);
+ this.main_window.add_notification(notification);
Libnotify.play_sound("message-sent-email");
}
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index d7fe781a..7e5ab0ef 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -49,6 +49,8 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
private Gtk.Box conversation_box;
[GtkChild]
private Gtk.ScrolledWindow conversation_list_scrolled;
+ [GtkChild]
+ private Gtk.Overlay overlay;
// This is a frame so users can use F6/Shift-F6 to get to it
[GtkChild]
@@ -170,6 +172,11 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
}
}
+ public void add_notification(InAppNotification notification) {
+ this.overlay.add_overlay(notification);
+ notification.show();
+ }
+
private void set_styling() {
Gtk.CssProvider provider = new Gtk.CssProvider();
Gtk.StyleContext.add_provider_for_screen(Gdk.Display.get_default().get_default_screen(),
diff --git a/src/client/meson.build b/src/client/meson.build
index d7123ab5..b0559b8d 100644
--- a/src/client/meson.build
+++ b/src/client/meson.build
@@ -78,6 +78,7 @@ geary_client_vala_sources = files(
'folder-list/folder-list-search-branch.vala',
'folder-list/folder-list-special-grouping.vala',
+ 'notification/in-app-notification.vala',
'notification/libmessagingmenu.vala',
'notification/libnotify.vala',
'notification/new-messages-indicator.vala',
diff --git a/src/client/notification/in-app-notification.vala b/src/client/notification/in-app-notification.vala
new file mode 100644
index 00000000..88993092
--- /dev/null
+++ b/src/client/notification/in-app-notification.vala
@@ -0,0 +1,66 @@
+/* Copyright 2017 Software Freedom Conservancy Inc.
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+/**
+ * Represents an in-app notification.
+ *
+ * Following the GNOME HIG, it should only contain a label and maybe a button.
+ */
+[GtkTemplate (ui = "/org/gnome/Geary/in-app-notification.ui")]
+public class InAppNotification : Gtk.Revealer {
+
+ /** Length of the default timeout to close the notification. */
+ public const uint DEFAULT_KEEPALIVE = 5;
+
+ [GtkChild]
+ private Gtk.Label message_label;
+ [GtkChild]
+ private Gtk.Button action_button;
+
+ /**
+ * Creates an in-app notification.
+ *
+ * @param message The messag that should be displayed.
+ * @param keepalive The amount of seconds that the notification should stay visible.
+ */
+ public InAppNotification(string message, uint keepalive = DEFAULT_KEEPALIVE) {
+ this.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN;
+ this.message_label.label = message;
+
+ // Close after the given amount of time.
+ Timeout.add_seconds(keepalive, () => { close(); return false; });
+ }
+
+ /**
+ * Sets a button for the notification.
+ */
+ public void set_button(string label, string action_name) {
+ this.action_button.visible = true;
+ this.action_button.label = label;
+ this.action_button.action_name = action_name;
+ }
+
+ public override void show() {
+ base.show();
+ this.reveal_child = true;
+ }
+
+ /**
+ * Closes the in-app notification.
+ */
+ [GtkCallback]
+ public void close() {
+ // Allows for the disappearing transition
+ this.reveal_child = false;
+ }
+
+ // Make sure the notification gets destroyed after closing.
+ [GtkCallback]
+ private void on_child_revealed(Object src, ParamSpec p) {
+ if (!this.child_revealed)
+ destroy();
+ }
+}
diff --git a/src/client/util/util-email.vala b/src/client/util/util-email.vala
index 40d16928..143465e5 100644
--- a/src/client/util/util-email.vala
+++ b/src/client/util/util-email.vala
@@ -30,5 +30,40 @@ public string strip_subject_prefixes(Geary.Email email) {
return !Geary.String.is_empty(cleaned) ? cleaned : _("(no subject)");
}
-}
+ /**
+ * Returns a shortened recipient list suitable for display.
+ *
+ * This is useful in case there are a lot of recipients, or there
+ * is little room for the display.
+ *
+ * @return a string containing at least the first mailbox
+ * serialised by {@link MailboxAddress.to_short_display}, if the
+ * list contains more mailboxes then an indication of how many
+ * additional are present.
+ */
+ public string to_short_recipient_display(Geary.RFC822.MailboxAddresses mailboxes) {
+ if (mailboxes.size == 0) {
+ // Translators: This is shown for displaying a list of
+ // email recipients that happens to be empty,
+ // i.e. contains no email addresses.
+ return _("(No recipients)");
+ }
+ // Always mention the first recipient
+ string first_recipient = mailboxes.get(0).to_short_display();
+ if (mailboxes.size == 1)
+ return first_recipient;
+
+ // Translators: This is used for displaying a short list of
+ // email recipients lists with two or more addresses. The
+ // first (string) substitution is address of the first, the
+ // second substitution is the number of n - 1 remaining
+ // recipients.
+ return GLib.ngettext(
+ "%s and %d other",
+ "%s and %d others",
+ mailboxes.size - 1
+ ).printf(first_recipient, mailboxes.size - 1);
+ }
+
+}
diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt
index 4513df64..4449d945 100644
--- a/ui/CMakeLists.txt
+++ b/ui/CMakeLists.txt
@@ -26,6 +26,7 @@ set(RESOURCE_LIST
STRIPBLANKS "folder-popover.ui"
STRIPBLANKS "gtk/help-overlay.ui"
STRIPBLANKS "gtk/menus.ui"
+ STRIPBLANKS "in-app-notification.ui"
STRIPBLANKS "login.glade"
STRIPBLANKS "main-toolbar.ui"
STRIPBLANKS "main-toolbar-menus.ui"
diff --git a/ui/in-app-notification.ui b/ui/in-app-notification.ui
new file mode 100644
index 00000000..087d794b
--- /dev/null
+++ b/ui/in-app-notification.ui
@@ -0,0 +1,48 @@
+
+
+
+
+ False
+ center
+ start
+
+
+
+
+
+
diff --git a/ui/main-window.ui b/ui/main-window.ui
index e09e308a..ae2aa252 100644
--- a/ui/main-window.ui
+++ b/ui/main-window.ui
@@ -1,5 +1,5 @@
-
+
@@ -11,175 +11,163 @@
-
+
True
False
- vertical
-
+
True
False
+ vertical
-
+
True
- False
- vertical
+ True
-
+
True
False
+ vertical
-
+
True
- False
- vertical
+ True
-
+
True
False
- 0
- in
+ vertical
-
- 100
+
True
False
- never
+ 0
+ in
+
+
+ 100
+ True
+ True
+ never
+
+
+
+
+ True
+ True
+ 0
+
-
- True
- True
- 0
+ False
+ False
-
-
- False
- False
-
-
-
-
- True
- False
- vertical
-
+
True
False
- 0
- in
+ vertical
-
- 250
+
True
False
+ 0
+ in
+
+
+ 250
+ True
+ True
+
+
+
+
+ True
+ True
+ 0
+
-
- True
- True
- 0
+ True
+ False
+
- True
- False
+ True
+ True
+ end
+ 0
- True
- True
- end
- 0
+ False
+ False
+
+
+
+
+
+ True
+ True
+ end
+ 0
+
+
+
+
+ False
+ True
+ 0
+ in
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+
- False
- False
+ False
+ True
+ 1
- True
- True
- end
- 0
-
-
-
-
- False
- True
- 0
- in
-
-
- True
- False
- vertical
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- False
- True
- 1
+ -1
+
+
+
diff --git a/ui/org.gnome.Geary.gresource.xml b/ui/org.gnome.Geary.gresource.xml
index d545a9af..e69af90b 100644
--- a/ui/org.gnome.Geary.gresource.xml
+++ b/ui/org.gnome.Geary.gresource.xml
@@ -27,6 +27,7 @@
folder-popover.ui
gtk/help-overlay.ui
gtk/menus.ui
+ in-app-notification.ui
login.glade
main-toolbar.ui
main-toolbar-menus.ui