[gnome-shell] messageTray: fix handling of markup vs non-markup notifications



commit d6f1c10b1bae6b0059bbe5827e3b7424fd692d6b
Author: Dan Winship <danw gnome org>
Date:   Wed Nov 24 02:31:55 2010 +0300

    messageTray: fix handling of markup vs non-markup notifications
    
    NotificationDaemon-based notifications have markup in the banner/body,
    but Telepathy-based notifications don't. (Eg, an XMPP message
    containing "<b>foo</b>" should show up angle brackets and all, not as
    bold.) Fix MessageTray.Notification to allow explicitly specifying
    where there should and shouldn't be markup, and use that
    appropriately.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=610219

 js/ui/messageTray.js        |   59 ++++++++++++++++++++++++++++--------------
 js/ui/notificationDaemon.js |    7 +++--
 2 files changed, 43 insertions(+), 23 deletions(-)
---
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index 2b6226a..05335b5 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -38,21 +38,27 @@ const State = {
     HIDING:  3
 };
 
-function _cleanMarkup(text) {
-    // Support &amp;, &quot;, &apos;, &lt; and &gt;, escape all other
-    // occurrences of '&'.
-    let _text = text.replace(/&(?!amp;|quot;|apos;|lt;|gt;)/g, '&amp;');
-    // Support <b>, <i>, and <u>, escape anything else
-    // so it displays as raw markup.
-    return _text.replace(/<(\/?[^biu]>|[^>\/][^>])/g, '&lt;$1');
+function _fixMarkup(text, allowMarkup) {
+    if (allowMarkup) {
+        // Support &amp;, &quot;, &apos;, &lt; and &gt;, escape all other
+        // occurrences of '&'.
+        let _text = text.replace(/&(?!amp;|quot;|apos;|lt;|gt;)/g, '&amp;');
+        // Support <b>, <i>, and <u>, escape anything else
+        // so it displays as raw markup.
+        return _text.replace(/<(\/?[^biu]>|[^>\/][^>])/g, '&lt;$1');
+    } else {
+        // Escape everything
+        let _text = text.replace(/&/g, '&amp;');
+        return _text.replace(/</g, '&lt;');
+    }
 }
 
-function URLHighlighter(text, lineWrap) {
-    this._init(text, lineWrap);
+function URLHighlighter(text, lineWrap, allowMarkup) {
+    this._init(text, lineWrap, allowMarkup);
 }
 
 URLHighlighter.prototype = {
-    _init: function(text, lineWrap) {
+    _init: function(text, lineWrap, allowMarkup) {
         if (!text)
             text = '';
         this.actor = new St.Label({ reactive: true, style_class: 'url-highlighter' });
@@ -74,7 +80,7 @@ URLHighlighter.prototype = {
             this.actor.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
         }
 
-        this.setMarkup(text);
+        this.setMarkup(text, allowMarkup);
         this.actor.connect('button-release-event', Lang.bind(this, function (actor, event) {
             let urlId = this._findUrlAtPos(event);
             if (urlId != -1) {
@@ -112,8 +118,8 @@ URLHighlighter.prototype = {
         }));
     },
 
-    setMarkup: function(text) {
-        text = text ? _cleanMarkup(text) : '';
+    setMarkup: function(text, allowMarkup) {
+        text = text ? _fixMarkup(text, allowMarkup) : '';
         this._text = text;
 
         this.actor.clutter_text.set_markup(text);
@@ -187,7 +193,8 @@ URLHighlighter.prototype = {
 // area.
 //
 // @params can contain values for 'customContent', 'body', 'icon',
-// and 'clear' parameters.
+// 'titleMarkup', 'bannerMarkup', 'bodyMarkup', and 'clear'
+// parameters.
 //
 // If @params contains a 'customContent' parameter with the value %true,
 // then @banner will not be shown in the body of the notification when the
@@ -201,6 +208,12 @@ URLHighlighter.prototype = {
 // source.createNotificationIcon(). However, if @params contains an 'icon'
 // parameter, the passed in icon will be used.
 //
+// If @params contains a 'titleMarkup', 'bannerMarkup', or
+// 'bodyMarkup' parameter with the value %true, then the corresponding
+// element is assumed to use pango markup. If the parameter is not
+// present for an element, then anything that looks like markup in
+// that element will appear literally in the output.
+//
 // If @params contains a 'clear' parameter with the value %true, then
 // the content and the action area of the notification will be cleared.
 // The content area is also always cleared if 'customContent' is false
@@ -217,6 +230,7 @@ Notification.prototype = {
         this._useActionIcons = false;
         this._customContent = false;
         this._bannerBodyText = null;
+        this._bannerBodyMarkup = false;
         this._titleFitsInBannerMode = true;
         this._spacing = 0;
 
@@ -290,6 +304,9 @@ Notification.prototype = {
         params = Params.parse(params, { customContent: false,
                                         body: null,
                                         icon: null,
+                                        titleMarkup: false,
+                                        bannerMarkup: false,
+                                        bodyMarkup: false,
                                         clear: false });
 
         this._customContent = params.customContent;
@@ -320,7 +337,7 @@ Notification.prototype = {
                                      y_fill: false,
                                      y_align: St.Align.START });
 
-        title = title ? _cleanMarkup(title.replace(/\n/g, ' ')) : '';
+        title = title ? _fixMarkup(title.replace(/\n/g, ' '), params.titleMarkup) : '';
         this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>');
 
         // Unless the notification has custom content, we save this._bannerBodyText
@@ -328,10 +345,11 @@ Notification.prototype = {
         // expandable due to other elements in its content area or due to the banner
         // not fitting fully in the single-line mode.
         this._bannerBodyText = this._customContent ? null : banner;
+        this._bannerBodyMarkup = params.bannerMarkup;
 
         banner = banner ? banner.replace(/\n/g, '  ') : '';
 
-        this._bannerUrlHighlighter.setMarkup(banner);
+        this._bannerUrlHighlighter.setMarkup(banner, params.bannerMarkup);
         this._bannerLabel.queue_relayout();
 
         // Add the bannerBody now if we know for sure we'll need it
@@ -339,7 +357,7 @@ Notification.prototype = {
             this._addBannerBody();
 
         if (params.body)
-            this.addBody(params.body);
+            this.addBody(params.body, params.bodyMarkup);
         this._updated();
     },
 
@@ -370,12 +388,13 @@ Notification.prototype = {
 
     // addBody:
     // @text: the text
+    // @markup: %true if @text contains pango markup
     //
     // Adds a multi-line label containing @text to the notification.
     //
     // Return value: the newly-added label
-    addBody: function(text) {
-        let label = new URLHighlighter(text, true);
+    addBody: function(text, markup) {
+        let label = new URLHighlighter(text, true, markup);
 
         this.addActor(label.actor);
         return label.actor;
@@ -385,7 +404,7 @@ Notification.prototype = {
         if (this._bannerBodyText) {
             let text = this._bannerBodyText;
             this._bannerBodyText = null;
-            this.addBody(text);
+            this.addBody(text, this._bannerBodyMarkup);
         }
     },
 
diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js
index c62cb4c..dc50537 100644
--- a/js/ui/notificationDaemon.js
+++ b/js/ui/notificationDaemon.js
@@ -205,8 +205,6 @@ NotificationDaemon.prototype = {
             return id;
         }
 
-        summary = GLib.markup_escape_text(summary, -1);
-
         let rewrites = rewriteRules[appName];
         if (rewrites) {
             for (let i = 0; i < rewrites.length; i++) {
@@ -281,7 +279,9 @@ NotificationDaemon.prototype = {
         let iconActor = this._iconForNotificationData(icon, hints, source.ICON_SIZE);
 
         if (notification == null) {
-            notification = new MessageTray.Notification(source, summary, body, { icon: iconActor });
+            notification = new MessageTray.Notification(source, summary, body,
+                                                        { icon: iconActor,
+                                                          bannerMarkup: true });
             ndata.notification = notification;
             notification.connect('clicked', Lang.bind(this,
                 function(n) {
@@ -294,6 +294,7 @@ NotificationDaemon.prototype = {
             notification.connect('action-invoked', Lang.bind(this, this._actionInvoked, source, id));
         } else {
             notification.update(summary, body, { icon: iconActor,
+                                                 bannerMarkup: true,
                                                  clear: true });
         }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]