[polari/wip/raresv/blankStateWidgets: 2/2] chatView: add the blank state feature



commit 9736401958cf1972f80a7971f60e25a95a54df23
Author: Rares Visalom <rares visalom gmail com>
Date:   Tue Nov 29 00:43:37 2016 +0200

    chatView: add the blank state feature
    
    The blank state marks the beginning of the history
    or chat logs in that specific room. It is also
    a way of telling the user what the chatroom is used
    for and provide any additional information like the
    name and topic of the current room.
    
    The blank state is inserted automatically when the
    beginning of the log history is reached. It is not
    inserted within the log itself, but rather inserted
    on demand. It is only inserted after the connection
    is established.

 src/chatView.js |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 94 insertions(+), 1 deletions(-)
---
diff --git a/src/chatView.js b/src/chatView.js
index 05dbdab..fea94ab 100644
--- a/src/chatView.js
+++ b/src/chatView.js
@@ -8,6 +8,7 @@ const PangoCairo = imports.gi.PangoCairo;
 const Polari = imports.gi.Polari;
 const Tp = imports.gi.TelepathyGLib;
 const Tpl = imports.gi.TelepathyLogger;
+const GdkPixbuf = imports.gi.GdkPixbuf;
 
 const Lang = imports.lang;
 const Mainloop = imports.mainloop;
@@ -16,6 +17,7 @@ const Signals = imports.signals;
 const Utils = imports.utils;
 const UserTracker = imports.userTracker;
 const UserList = imports.userList;
+const RoomManager = imports.roomManager;
 
 const MAX_NICK_CHARS = 8;
 const IGNORE_STATUS_TIME = 5;
@@ -350,6 +352,8 @@ const ChatView = new Lang.Class({
         this._view.connect_after('style-updated',
                                  Lang.bind(this, this._updateIndent));
 
+        this._roomManager = RoomManager.getDefault();
+
         this._room = room;
         this._state = { lastNick: null, lastTimestamp: 0, lastStatusGroup: 0 };
         this._joinTime = 0;
@@ -361,6 +365,10 @@ const ChatView = new Lang.Class({
         this._initialPending = [];
         this._backlogTimeoutId = 0;
         this._statusCount = { left: 0, joined: 0, total: 0 };
+        this._canBlankStateBeInserted = false;
+        this._isBlankStateInserted = false;
+
+        this._room.connect("notify::topic", () => {this._canBlankStateBeInserted = true;});
 
         let statusMonitor = UserTracker.getUserStatusMonitor();
         this._userTracker = statusMonitor.getUserTrackerForAccount(room.account);
@@ -459,7 +467,22 @@ const ChatView = new Lang.Class({
           { name: 'indicator-line',
             pixels_above_lines: 24 },
           { name: 'loading',
-            justification: Gtk.Justification.CENTER }
+            justification: Gtk.Justification.CENTER },
+          {
+            name: 'blank-state-header',
+            left_margin: MARGIN,
+            size: 18000
+          },
+          {
+            name: 'blank-state-topic',
+            left_margin: MARGIN,
+            size: 13000
+          },
+          {
+            name: 'blank-state-tips',
+            left_margin: MARGIN,
+            size: 10000
+          }
         ];
         tags.forEach(function(tagProps) {
             tagTable.add(new Gtk.TextTag(tagProps));
@@ -506,6 +529,12 @@ const ChatView = new Lang.Class({
             foreground_rgba: dimColor },
           { name: 'timestamp',
             foreground_rgba: dimColor },
+          { name: 'blank-state-header',
+            foreground_rgba: dimColor },
+          { name: 'blank-state-topic',
+            foreground_rgba: dimColor },
+          { name: 'blank-state-tips',
+            foreground_rgba: dimColor },
           { name: 'url',
             foreground_rgba: linkColor }
         ];
@@ -731,6 +760,8 @@ const ChatView = new Lang.Class({
     },
 
     _fetchBacklog: function() {
+        this._tryToInsertBlankState();
+
         if (this.vadjustment.value != 0 ||
             this._logWalker.is_end())
             return Gdk.EVENT_PROPAGATE;
@@ -750,6 +781,68 @@ const ChatView = new Lang.Class({
         return Gdk.EVENT_STOP;
     },
 
+    _tryToInsertBlankState: function() {
+        if (this._logWalker.is_end() && !this._isBlankStateInserted && this._canBlankStateBeInserted) {
+            this._insertBlankState();
+            this._isBlankStateInserted = true;
+        }
+    },
+
+    _insertBlankState: function () {
+        let buffer = this._view.get_buffer();
+
+        let blankStateMark = this._view.buffer.create_mark('blank-state-mark',
+                                                           this._view.buffer.get_start_iter(),
+                                                           false);
+
+        let header = 'Conversations in ' + this._room.channel_name + ' start here.\n';
+
+        let tags = [this._lookupTag('blank-state-header')];
+        this._insertWithTags(this._view.buffer.get_iter_at_mark(blankStateMark), header, tags);
+
+        let topic = 'The topic of ' + this._room.channel_name + ' is: ' + this._room.topic + '\n';
+
+        tags = [this._lookupTag('blank-state-topic')];
+        this._insertWithTags(this._view.buffer.get_iter_at_mark(blankStateMark),
+                             topic,
+                             tags);
+
+        tags = [this._lookupTag('blank-state-tips')];
+        if (this._roomManager.isFirstRun) {
+            this._insertImageAtMarkWithTags('polari-user-notify-symbolic', blankStateMark, tags);
+            this._insertWithTags(this._view.buffer.get_iter_at_mark(blankStateMark),
+                                 "Notify other users of your message by including their nickname.\n",
+                                 tags);
+
+            this._insertImageAtMarkWithTags('polari-user-notify-symbolic', blankStateMark, tags);
+            this._insertWithTags(this._view.buffer.get_iter_at_mark(blankStateMark),
+                                 "Share text and images by pasting them into the text field.\n",
+                                 tags);
+
+            this._insertImageAtMarkWithTags('polari-user-notify-symbolic', blankStateMark, tags);
+            this._insertWithTags(this._view.buffer.get_iter_at_mark(blankStateMark),
+                                 "If this is your first time using IRC, we recommend glacing over the IRC 
netiquette.\n",
+                                 tags);
+        }
+    },
+
+    _insertImageAtMarkWithTags: function(imageName, mark, tags) {
+        let image1 = new Gtk.Image({ icon_name: imageName,
+                                     visible: true });
+
+        let iter = this._view.buffer.get_iter_at_mark(mark);
+        let offset = iter.get_offset();
+
+        let anchor = this._view.buffer.create_child_anchor(iter);
+        this._view.add_child_at_anchor(image1, anchor);
+
+        let start = this._view.buffer.get_iter_at_offset(offset);
+
+        this._view.buffer.remove_all_tags(start, iter);
+        for (let i = 0; i < tags.length; i++)
+            this._view.buffer.apply_tag(tags[i], start, iter);
+    },
+
     _onValueChanged: function() {
         if (this._valueChangedId)
             return;


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