From 470a44e09293fe43343fa35d8288edf74831c203 Mon Sep 17 00:00:00 2001 From: Enrico Fasoli Date: Tue, 1 Sep 2015 01:12:39 +0200 Subject: [PATCH] many. many improvements especially to history download and ui --- lib/ui.js | 33 +++++++++------- lib/util.js | 99 ++++++++++++++++++++++++++++++++++++++---------- telecommander.js | 69 +++++++++++++++++++-------------- 3 files changed, 140 insertions(+), 61 deletions(-) diff --git a/lib/ui.js b/lib/ui.js index 354a468..b8ecdd2 100644 --- a/lib/ui.js +++ b/lib/ui.js @@ -6,7 +6,7 @@ module.exports = function(data){ data.selectedWindow = data.statusWindow // the currently selected window // Get msgBox for given group/user NAME, create if not exists - data.getMsgBox = function(chat,switchto){ + data.getMsgBox = function(chat){ if(chat === undefined){ log('ERROR: asked for box for "undefined"!!') return data.msgBox[statusWindow] @@ -15,24 +15,24 @@ module.exports = function(data){ //log('Generating window: "'+chat+'"') data.msgBox[chat] = data.mkBox(chat) data.screen.append(data.msgBox[chat]) - data.getMessages(chat,data.msgBox[chat]) + //data.getMessages(chat,data.msgBox[chat]) } // else log('Getting window','"'+chat+'"') - if(switchto === true){ - data.switchToBox(chat) - } return data.msgBox[chat] } - data.switchToBox= function(boxname){ + data.switchToBox = function(boxname){ if(data.selectedWindow && data.msgBox[data.selectedWindow]) data.msgBox[data.selectedWindow].hide() data.selectedWindow = boxname; if(data.selectedWindow != data.statusWindow) data.cmdline.setLabel('to '+data.selectedWindow) - else + else { + data.markAsRead(data.selectedWindow) data.cmdline.setLabel('Command for Telecommander') + } var newb = data.getMsgBox(data.selectedWindow) newb.show() + data.screen.render() } data.screen = blessed.screen({ @@ -52,7 +52,7 @@ module.exports = function(data){ bg: 'white' } }, - selected: { bold: true }, + selected: { bold: true, fg: 'white' }, scrollbar: { fg: 'white', bg: 'white', track: { fg: 'grey', bg: 'grey' } @@ -63,6 +63,7 @@ module.exports = function(data){ // Contact list window data.chats = blessed.list({ keys: true, + tags: true, label: 'Conversations', left: 0, top:0, @@ -85,6 +86,7 @@ module.exports = function(data){ data.mkBox = function(txt){ var b = ChatBox({ keys: true, + tags: true, mouse: true, right: 0, label: { text: txt, side: 'left' }, @@ -106,6 +108,9 @@ module.exports = function(data){ b.key('enter',function(){ data.cmdline.focus() }) + b.on('scroll',function(){ + if(b.getScroll() === 0) data.getMessages(txt,b) + }) return b } @@ -143,7 +148,9 @@ module.exports = function(data){ data.screen.key('tab',function(){ data.screen.focusPush(data.chats) }) - + data.screen.key('0',function(){ + data.switchToBox(data.statusWindow) + }) data.command = function(cmd){ cmdl = cmd.split(' ') cmdname = cmdl[0] @@ -217,9 +224,9 @@ module.exports = function(data){ data.chats.on('select',function(selected){ //data.log('SELECT:',selected.content) if(selected === undefined) return - data.switchToBox(selected.content) - data.cmdline.focus() - data.screen.render() + var sel = data.escapeFromList(selected) + data.switchToBox(sel) + data.msgBox[data.selectedWindow].focus() }) /* data.cmdline.on('click',function(){ @@ -238,7 +245,7 @@ module.exports = function(data){ // What happens when the user submits a command in the prompt data.cmdline.on('submit',function(value){ - data.getMsgBox(data.statusWindow).pushLine('< '+value) + data.getMsgBox(data.statusWindow).add('< '+value) if(data.selectedWindow === data.statusWindow || data.nameToObj(data.selectedWindow) === undefined){ //log('Window:',selectedWindow,'Eval cmd:',value) data.command(value) diff --git a/lib/util.js b/lib/util.js index 396207f..bcf9306 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,3 +1,5 @@ +var blessed = require('blessed') + module.exports = function(data){ // Contacts holds all the contacts data data.contacts = { } @@ -15,7 +17,13 @@ module.exports = function(data){ data.contacts[u.id] = { user: u, id: u.id} var name = data.getName(u.id,'user') data.unameToUid[name] = u.id - if(!data.chats.getItem(name)) data.chats.addItem(name) + data.rebuildChatList() + /* + if(!data.chats.getItem(name)){ + data.chats.addItem(name) + data.screen.render() + } + */ } data.addGroup = function(group){ @@ -41,8 +49,47 @@ module.exports = function(data){ } else { data.groups[group.id] = { id: group.id, title: group.title, group: group } data.gnameToGid[group.title] = group.id - if(!data.chats.getItem(group.title)) data.chats.addItem(group.title) } + /* + if(!data.chats.getItem(group.title)){ + data.chats.addItem(group.title) + data.screen.render() + } + */ + data.rebuildChatList() + } + + data.rebuildChatList = function(){ + var list = [] + for(c in data.contacts) list.push(data.contacts[c]) + for(c in data.groups) list.push(data.groups[c]) + function cmpstr(a,b){ + return data.getName(a.id,a.title?'group':'user').localeCompare(data.getName(b.id,b.title?'group':'user')) + } + list.sort(function(a,b){ + if(a.toread > 0 && b.toread > 0){ + var diff = a.toread - b.toread + if(diff == 0) return cmpstr(a,b) + return diff + } + if(a.toread > 0) return -1 + if(b.toread > 0) return 1 + return cmpstr(a,b) + }) + data.chats.setItems(list.map(function(item){ + return data.getName(item.id,item.title?'group':'user',true) + })) + if(!data.chats.focused == data.screen.focused) data.chats.setScrollPerc(0) + //data.chats.select(data.selectedWindow) + data.screen.render() + } + + data.markAsRead = function(name){ + var obj = data.nameToObj(name) + if(obj === undefined) return + obj.toread = 0 + data.client.messages.readHistory(data.idToPeer(obj.id,obj.title?'group':'user'),0,0,true) + data.rebuildChatList() } // Updates the current state @@ -54,27 +101,39 @@ module.exports = function(data){ data.state.unreadCount = newstate.unread_count || data.state.unreadCount || 0 } - // process an update - data.onUpdate = function(upd){ - data.log('Got Update:',upd.toPrintable()) - } - - data.nameForUser = function(u){ - if(u.first_name === undefined && u.last_name === undefined && u.username === undefined){ - data.log('Zombie User: '+u) - return 'undefined' + data.getName = function(id,type,forChatList){ + var name,obj,toread + if(type === undefined) throw new Error('no type') + else if(id === data.user.id){ + obj = data.user + } else if(type === 'group' && data.groups[id]) { + obj = data.groups[id] + toread = obj.toread + } else if(type === 'user' && data.contacts[id]) { + obj = data.contacts[id].user + toread = data.contacts[id].toread + } else data.log('Failed to find name for',type,id) + if(obj === undefined){ + throw new Error("Can't find name for",type,id) + return } - return u.first_name + ' ' + u.last_name + (u.username?' (@'+u.username+')':'') + if(type === 'user'){ + // User + if(obj.first_name === undefined && obj.last_name === undefined && obj.username === undefined){ + data.log('Zombie User: '+obj) + return 'undefined' + } + name = obj.first_name + (obj.last_name?' '+obj.last_name:'') + (obj.username?' (@'+obj.username+')':'') + } else { + // Group + name = obj.title + } + if(forChatList && toread > 0) return '* '+name + return name } - data.getName = function(id,type){ - if(id === data.user.id) return data.nameForUser(data.user) - else if(type === undefined) throw new Error('no type') - else if(type === 'group' && data.groups[id]) - return data.groups[id].title - else if(type === 'user' && data.contacts[id]) - return data.nameForUser(data.contacts[id].user) - else data.log('Failed to find name for',type,id) + data.escapeFromList = function(txt){ + return blessed.stripTags(txt.text || txt.content || String(text)).replace('* ','') } data.nameToObj = function(name){ diff --git a/telecommander.js b/telecommander.js index a721d3f..c8eb234 100755 --- a/telecommander.js +++ b/telecommander.js @@ -172,8 +172,8 @@ data.whenReady = function(){ data.downloadData = function(){ data.log('Downloading data...') data.client.contacts.getContacts('',function(cont){ - data.chats.clearItems() - data.chats.add(data.statusWindow) + //data.chats.clearItems() + //data.chats.add(data.statusWindow) cont.users.list.forEach(data.addUser) }) @@ -195,7 +195,7 @@ data.downloadData = function(){ data.downloadUpdates = function(){ data.client.updates.getDifference(data.state.pts,data.state.date,data.state.qts,function(res){ if(!res.instanceOf('api.type.updates.DifferenceEmpty')){ - //log('Got Diff: ',res.toPrintable()) + //data.log('Got Diff: ',res.toPrintable()) if(res.state){ data.updateState(res.state) } @@ -205,19 +205,22 @@ data.downloadUpdates = function(){ for(c in res.users.list) data.addUser(res.users.list[c]) if(res.new_messages){ res.new_messages.list.forEach(function(msg){ - data.appendMsg(msg,undefined,false,true) + data.appendMsg(msg,undefined,false,false) }) } + data.rebuildChatList() } setTimeout(data.downloadUpdates,1000) }) } // Get message history with given name in the given box +// BROKEN, need to be rethinked data.getMessages = function(name,box){ if(!data.connected){ - return log('Uh cant get messages cuz not connected.....') + return // data.log('Uh cant get messages cuz not connected.....') } + if(data.downloadingMessages == true) return //log('Name to obj:',name) var obj = data.nameToObj(name) if(!obj || !obj.id){ @@ -225,9 +228,11 @@ data.getMessages = function(name,box){ } var type = obj.title?'group':'user' var peer = data.idToPeer(obj.id,type) - box.add('Downloading message history for '+name) + //box.add('Downloading message history for '+name) if(!peer) return log('Could not find peer:',name) - data.client.messages.getHistory(peer,0,-1,100,function(res){ + data.downloadingMessages = true + var oldnlines = box.getLines().length + data.client.messages.getHistory(peer,0,obj.oldest_message||0,10,function(res){ //log(res.toPrintable()) //log('Got history for: '+getName(peer.user_id||peer.chat_id,peer.chat_id?'group':'user')) if(!res.messages){ @@ -236,13 +241,13 @@ data.getMessages = function(name,box){ res.messages.list.sort(function(msg1,msg2){ return msg1.date - msg2.date }) - if(res.messages.list.length === 0) - return data.appendToUserBox('No messages.',res) + res.messages.list.reverse() res.messages.list.forEach(function(msg){ - //if(!msg.message) return log('Empty message!',msg.toPrintable()) - //log('Scheduling message: '+msg.toPrintable()) - data.appendMsg(msg) + data.appendMsg(msg,undefined,false,true) }) + if(oldnlines == 0) box.setScrollPerc(100) + //box.add(obj.oldest_message) + data.downloadingMessages = false }) } @@ -266,45 +271,53 @@ data.appendToUserBox = function(msg,context){ } // Writes given telegram.link "message" object to given boxId -data.appendMsg = function(msg,toBoxId,bare,smartmode){ - var box,param +data.appendMsg = function(msg,toBoxId,bare,prepend){ + var box,param,obj if(toBoxId != undefined){ box = toBoxId } else { if(msg.to_id.chat_id != undefined){ // Is a group param = data.getName(msg.to_id.chat_id,'group') + obj = data.groups[msg.to_id.chat_id] } else if(msg.from_id === msg.to_id.user_id || msg.from_id != data.user.id){ param = data.getName(msg.from_id,'user') + obj = data.contacts[msg.from_id] } else if(msg.to_id.user_id != undefined && msg.to_id.user_id != data.user.id) { // don't forget dat .user_id! don't need it in from_id... param = data.getName(msg.to_id.user_id,'user') + obj = data.contacts[msg.to_id.user_id] } - if(smartmode && !bare){ - // Smart mode doesn't append the message to the box if it doesn't exist - // because when created, the box will download message history - if(data.msgBox[param] === undefined) return; + // Increase unread count if necessary + if(data.selectedWindow != param || data.msgBox[param] === undefined){ + if(!obj.toread) obj.toread = 1 + else obj.toread++ } + // Update oldest message reference + if(!obj.oldest_message || parseInt(obj.oldest_message) > parseInt(msg.id)) + obj.oldest_message = parseInt(msg.id) box = data.getMsgBox(param) } if(bare) box.add(msg) else { - var from = msg.from_id - var date = moment.unix(msg.date).fromNow() - name = data.getName(from,'user') - var txt + var id = msg.from_id + var date = moment.unix(msg.date).format('DD-MM-YYYY H:mm') + name = data.getName(id,'user') + var txt = (name || id)+' {|} {grey-fg}'+date+'{/grey-fg}\n' if(msg.media){ if(msg.media.photo) - txt = ' <*> (Photo)' + txt += '{grey-fg}>>>{/grey-fg} (Photo)' else if(msg.media.audio) - txt = " <*> (Audio Message) "+msg.media.audio.duration+" seconds" - else if(msg.message) - txt = ' > '+msg.message - else txt = " <*> (Unsupported Message)" + txt += "{grey-fg}>>>{/grey-fg} (Audio Message) "+msg.media.audio.duration+" seconds" + else if(!msg.message) + txt += "{grey-fg}>>>{/grey-fg} (Unsupported Message)" } - box.add(date+' | '+(name || from)+txt) + if(msg.message) txt += '{grey-fg}>{/grey-fg} '+msg.message + if(prepend) box.prepend(txt) + else box.add(txt) } + return box } // - Entry Point -