[polari/wip/bastianilso/status-hiding] WIP



commit 58641c31d4175094e285295f7c338bbf28d5efed
Author: Bastian Ilsø <hougaard junior gmail com>
Date:   Wed Dec 2 18:27:45 2015 +0100

    WIP

 src/chatView.js |  206 ++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 144 insertions(+), 62 deletions(-)
---
diff --git a/src/chatView.js b/src/chatView.js
index 9d8d879..830d94d 100644
--- a/src/chatView.js
+++ b/src/chatView.js
@@ -11,7 +11,7 @@ const Mainloop = imports.mainloop;
 const Utils = imports.utils;
 
 const MAX_NICK_CHARS = 8;
-const IGNORE_STATUS_TIME = 5;
+const IGNORE_STATUS_TIME = 1; // ???????? // was 5
 const TP_CURRENT_TIME = GLib.MAXUINT32;
 
 const SCROLL_TIMEOUT = 100; // ms
@@ -19,7 +19,7 @@ const SCROLL_TIMEOUT = 100; // ms
 const TIMESTAMP_INTERVAL = 300; // seconds of inactivity after which to
                                 // insert a timestamp
 
-const ACTIVITY_DURATION = 300; // min
+const ACTIVITY_DURATION = 30; // s? // was 300
 const STATUS_NOISE_MAXIMUM = 4;
 
 const NUM_INITIAL_LOG_EVENTS = 50; // number of log events to fetch on start
@@ -104,13 +104,11 @@ const ChatView = new Lang.Class({
         this._needsIndicator = true;
         this._pending = {};
         this._pendingLogs = [];
-        this._statusCount = [
-            { name: 'left',
-              count: 0 },
-            { name: 'joined',
-              count: 0 }
+        this._statusCounts = [
+            { left: 0,
+              joined: 0,
+              total: 0 },
             ];
-        this._statusTexts = [];
 
         let isRoom = room.type == Tp.HandleType.ROOM;
         let target = new Tpl.Entity({ type: isRoom ? Tpl.EntityType.ROOM
@@ -174,7 +172,8 @@ const ChatView = new Lang.Class({
           { name: 'status',
             left_margin: MARGIN,
             indent: 0,
-            justification: Gtk.Justification.RIGHT },
+            justification: Gtk.Justification.RIGHT,
+            invisible: false },
           { name: 'timestamp',
             left_margin: MARGIN,
             indent: 0,
@@ -187,7 +186,7 @@ const ChatView = new Lang.Class({
           { name: 'expandable',
             underline: Pango.Underline.SINGLE },
           { name: 'loading',
-            justification: Gtk.Justification.CENTER }
+            justification: Gtk.Justification.CENTER },
         ];
         tags.forEach(function(tagProps) {
             tagTable.add(new Gtk.TextTag(tagProps));
@@ -485,8 +484,7 @@ const ChatView = new Lang.Class({
         let iter = view.get_iter_at_location(x, y);
         let tags = iter.get_tags();
         for (let i = 0; i < tags.length; i++) {
-            let url = tags[i]._url;
-            let statusTexts = tags[i]._statusTexts;
+            let url = tags[i]._url
             if (url) {
                 if (url.indexOf(':') == -1)
                     url = 'http://' + url;
@@ -502,19 +500,12 @@ const ChatView = new Lang.Class({
                     return Gdk.EVENT_STOP;
                 }
                 break;
-            } else if (statusTexts) {
-                let buffer = this._view.get_buffer();
-                let startIter = buffer.get_iter_at_line(iter.get_line());
-                let startMark = buffer.create_mark(null, iter, true);
-                let endMark = buffer.create_mark(null, iter, false);
-                iter.forward_to_line_end();
-                buffer.delete(startIter, iter);
-                statusTexts.forEach(Lang.bind(this, function(statusText) {
-                    buffer.insert(buffer.get_iter_at_mark(startMark), statusText + '\n', -1);
-                    let startIter = buffer.get_iter_at_mark(startMark);
-                    let endIter = buffer.get_iter_at_mark(endMark);
-                    buffer.apply_tag(this._lookupTag('status'), startIter, endIter);
-                }));
+            } else if (tags[i].name.indexOf('status-compressed') != -1) {
+                if (isPress && button == Gdk.BUTTON_PRIMARY) {
+                    let statusTag = this._lookupTag('status' + tags[i].name.slice(-1));
+                    statusTag.invisible = !statusTag.invisible;
+                }
+                return Gdk.EVENT_STOP;
             }
         }
         return Gdk.EVENT_PROPAGATE;
@@ -528,7 +519,7 @@ const ChatView = new Lang.Class({
         let tags = iter.get_tags();
         let hovering = false;
         for (let i = 0; i < tags.length && !hovering; i++)
-            if (tags[i]._url || tags[i]._statusTexts)
+            if (tags[i]._url || tags[i].name.indexOf('status-compressed' != -1))
                 hovering = true;
 
         if (this._hoveringLink != hovering) {
@@ -723,8 +714,10 @@ const ChatView = new Lang.Class({
             text += ' (%s)'.format(message);
         if (this._shouldStatus(member.alias)) {
             this._insertStatus(text);
+            log("member was active, inserting status..");
         } else if (time - this._state.lastTimestamp > ACTIVITY_DURATION) {
             this._insertStatusCompressed(text, 'left');
+            log("channel is idle, inserting status compressed..");
         }
         this._setNickStatus(member.alias, Tp.ConnectionPresenceType.OFFLINE);
     },
@@ -746,15 +739,15 @@ const ChatView = new Lang.Class({
     },
 
     _resetStatusCompressed: function() {
-        let mark = this._view.buffer.get_mark('idle-status');
-        if (!mark)
+        let markStart = this._view.buffer.get_mark('idle-status-start');
+        let markEnd = this._view.buffer.get_mark('idle-status-end');
+        if (!markStart || !markEnd)
             return;
 
-        this._view.buffer.delete_mark(mark);
-        this._statusTexts = [];
-        this._statusCount.forEach(function(statusEntry) {
-            statusEntry.count = 0;
-        });
+        this._view.buffer.delete_mark(markStart);
+        this._view.buffer.delete_mark(markEnd);
+        let statusCount =  { left: 0, joined: 0, total: 0 };
+        this._statusCounts.push(statusCount);
     },
 
     _shouldStatus: function(nick) {
@@ -767,51 +760,140 @@ const ChatView = new Lang.Class({
         return time - nickTag._active < ACTIVITY_DURATION;
     },
 
+    // InsertStatusCompressed is called whenenver we insert messages in idle channels
+    // Even if we dont insert them compressed (the 4 first messages fx).
     _insertStatusCompressed: function(statusText, status) {
         let time = GLib.DateTime.new_now_utc().to_unix();
+        let buffer = this._view.buffer;
+
+        // OK so this seems to make sure we dont show status message from the log history i think.
         if (time - this._joinTime < IGNORE_STATUS_TIME)
             return;
 
-        this._statusTexts.push(statusText);
+        // Create a statusGroupTag which we can use to toggle invisibility
+        let statusGroupNumber = this._statusCounts.length-1;
+        let statusGroupTag = this._lookupTag('status' + statusGroupNumber);
+        if (!statusGroupTag) {
+            statusGroupTag = new Gtk.TextTag({ name: 'status' + statusGroupNumber });
+            buffer.tag_table.add(statusGroupTag);
+            //log('created new tag ' + statusTag.name);
+        }
+
+        // this tag is just cosmetic stuff.
+        let statusTag = this._lookupTag('status');
 
-        let compressedText = '';
-        this._statusCount.forEach(function(statusEntry) {
-            if (statusEntry.name == status)
-                statusEntry.count++;
+        // Regardless of whether we need to compress, we still insert the tagged text.
+        // It might be invisible, though.
+        // Add to the count of the latest group of status texts.
+        let statusCount = this._statusCounts[this._statusCounts.length-1];
 
-            if (statusEntry.count) {
-                if (compressedText)
-                    compressedText = compressedText + ', '
+        // If this is the first status message, then we need to ensureNewLine first.
+        if (statusCount.total == 0) //TODO: Make sure that we refactor "StatusCount" other places
+            this._ensureNewLine();
+
+        if (status == 'left')
+            statusCount.left++;
+        else if (status == 'joined')
+            statusCount.joined++;
+        statusCount.total++;
+
+        // We get the mark of the latest idle-status message, if it doesnt exist, we create it.
+        // we use the mark to get the iter from which we insert text.
+        // We do this after we ensure a new line for the first message
+        let markStart = buffer.get_mark('idle-status-start');
+        if (!markStart) {
+            let iter = buffer.get_end_iter() //buffer.get_iter_at_line(buffer.get_line_count()-1);
+            markStart = buffer.create_mark('idle-status-start', iter, true);
+        }
 
-                compressedText = compressedText + statusEntry.count +
-                                 ' users ' + statusEntry.name;
+        // not sure what this does..
+        this._state.lastNick = null;
+
+        // we get the iter of the buffer at which we need to insert the text.
+        let endIter = buffer.get_end_iter();
+
+        // Insert the text with our statusTags.
+        log('inserting statusText at: ' + endIter.get_line() + ':' + endIter.get_line_offset());
+        this._insertWithTags(endIter, statusText + '\n', [statusGroupTag, statusTag]);
+
+
+        //let markStartIter = buffer.get_iter_at_mark(markStart);
+        //this._insertWithTags(markStartIter, '|markStart|' , [statusTag]);
+
+
+        // Do we have more than 4 messages in the buffer?
+        // Then its time to compress.
+        if (statusCount.total > STATUS_NOISE_MAXIMUM) {
+
+            let statusCompressedTag = this._lookupTag('status-compressed' + statusGroupNumber);
+            if (!statusCompressedTag) {
+                statusCompressedTag = new Gtk.TextTag({ name: 'status-compressed' + statusGroupNumber });
+                buffer.tag_table.add(statusCompressedTag);
+                //log('created a statusCompressedTag:' + statusCompressedTag.name);
+                statusGroupTag.invisible = true;
             }
-        });
-        let buffer = this._view.buffer;
-        let mark = buffer.get_mark('idle-status');
-        if (!mark) {
-            let iter = buffer.get_end_iter();
-            buffer.create_mark('idle-status', iter, true);
+            // create a compressed text message
+            let compressedText = statusCount.joined + " users joined, "
+                                 + statusCount.left + " users left. ";
+
+            // Insert a compressed text message before the invisible text.
+
+            let markStartIter = buffer.get_iter_at_mark(markStart);
+            let markEndIter = markStartIter.copy();
+            markEndIter.forward_line();
+            log('deleting text between: ' + markStartIter.get_line() + ':' + markStartIter.get_line_offset() 
+ ' and ' + markEndIter.get_line() + ':' + markEndIter.get_line_offset());
+            buffer.delete(markStartIter, markEndIter);
+            log('Deleted the previous message');
+
+            log('that test code is not messing up anything');
+            markStartIter = buffer.get_iter_at_mark(markStart);
+            log('inserting compressed status message at: ' + markStartIter.get_line() + ':' + 
markStartIter.get_line_offset());
+            this._insertWithTags(markStartIter, compressedText + ' ( \u2026 ) \n' , [statusTag, 
statusCompressedTag]);
+
         }
+    },
+
+
+/*
+            //buffer.delete(startIter, endIter);
+
+            // Toggle invisibility when we reach noise maximum
+            //let statusGroupTag = this._lookupTag('status-group-tag');
+            //statusGroupTag.invisible = true;
+
 
-        if (this._statusTexts.length > STATUS_NOISE_MAXIMUM) {
-            let markIter = buffer.get_iter_at_mark(mark);
-            let startIter = buffer.get_iter_at_line(markIter.get_line());
-            let endIter = buffer.get_end_iter();
-            buffer.delete(startIter, endIter);
-            let tags = [this._lookupTag('status')];
             this._state.lastNick = null;
-            this._ensureNewLine();
-            this._insertWithTags(endIter, compressedText + ' ( ', tags);
+            // WE CANT use ensureNewLine because the "/n" wont have the invisible tag...
+            //this._ensureNewLine();
+ // lets assume this is start of all status messages.
+
+            log("Current lines of text to hide:");
+            log(buffer.get_text(startIter, endIter, false));
+
             let tag = new Gtk.TextTag();
             tag._statusTexts = this._statusTexts;
             this._view.get_buffer().tag_table.add(tag);
-            this._insertWithTags(endIter, '\u2026', tags.concat(this._lookupTag('expandable'), tag));
-            this._insertWithTags(endIter, ' )', tags);
-        } else {
-        this._insertStatus(statusText);
+
+        } else { // If we dont have more than 4 messages in the buffer, just insert normally.
+        // What we need to do, is to ensure that the inserted statuses at this point
+        // Receives their own tag, so we can hide that specific tag.
+        // We could use a timecode or a simple count to keep track.
+        // Either option implies that we check if there was a status message previously i guess?
+        // and then make sure that we give the same tag as previously.
+        // Well, if our count is higher than 0, then we need to use the same.
+
+        let statusGroupTag = this._lookupTag('status-group-tag');
+        if (!statusGroupTag) {
+            statusGroupTag = new Gtk.TextTag({ name: 'status-group-tag'});
+            this._view.get_buffer().get_tag_table().add(statusGroupTag);
         }
-    },
+
+        this._ensureNewLine();
+        let iter = buffer.get_end_iter();
+        let tags = [statusGroupTag, this._lookupTag('status')];
+
+        //this._insertStatus(statusText);
+        }*/
 
     _insertStatus: function(text) {
         let time = GLib.DateTime.new_now_utc().to_unix();


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