From ab91db2efac8f234c9a9968f93b54fd631974240 Mon Sep 17 00:00:00 2001 From: Deon George Date: Thu, 15 Dec 2022 23:28:25 +1100 Subject: [PATCH] Message reading navigation, enable tagging a specific message area --- frames_list.js | 2 +- frames_tag.js | 4 ++ load/control-echomail.js | 3 -- load/frame-ansi.js | 2 +- load/frame-page.js | 35 ++++++++++++--- load/funcs.js | 6 +-- load/msgbases.js | 92 +++++++++++++++++++++++++++++++++++++--- text/198a.tex | 2 +- 8 files changed, 125 insertions(+), 21 deletions(-) diff --git a/frames_list.js b/frames_list.js index 0573b8c..5510de2 100644 --- a/frames_list.js +++ b/frames_list.js @@ -1,6 +1,6 @@ load('load/string.js'); load('load/funcs.js'); - +load('ansitex/load/msgbases.js'); if (argv.length !== 1) { writeln('ERROR: Need a msgbase page prefix'); diff --git a/frames_tag.js b/frames_tag.js index 89417ad..b65bc4f 100644 --- a/frames_tag.js +++ b/frames_tag.js @@ -1,5 +1,6 @@ /** * Go through our messages and tag a frame id for messages without one. + * @note: May need to run jsexec with -m 32MB to overcome memory issues */ load('load/string.js'); @@ -7,6 +8,9 @@ load('ansitex/load/msgbases.js'); const ma = new MsgAreas() for (var i=0;i scan_ptr and it is the next message on the user's new mail list var newmsgs = area.newMsgsToMe(); + var next; log(LOG_DEBUG,'User has: '+newmsgs.length+' msgs to read to ME'); if (newmsgs.length) { - var next = newmsgs[0]; + next = newmsgs[1]; + log(LOG_DEBUG,'- NEXT is: '+next.tags+', this is: '+msg.tags); - //log(LOG_DEBUG,'- NEXT is: '+next.tags+', this is: '+msg.tags); if (next.tags === msg.tags) { log(LOG_DEBUG,'- Updating scan_ptr to: '+next.number); stats.scan_ptr = next.number; } + + // Last message + next = newmsgs[0]; + log(LOG_DEBUG,'- LAST TO ME is: '+next.tags); + if (next !== undefined) { + this.key[1] = area.page(next.tags); + } + + // Next new message + next = newmsgs[2]; + log(LOG_DEBUG,'- NEXT TO ME is: '+next.tags); + if (next !== undefined) + this.key[2] = area.page(next.tags); } // if this message is the next message, update last_read - var newmsgs = area.newMsgs(); + newmsgs = area.newMsgs(); log(LOG_DEBUG,'User has: '+newmsgs.length+' msgs to read'); if (newmsgs.length) { - var next = newmsgs[0]; + next = newmsgs[0]; + log(LOG_DEBUG,'- NEXT is: '+next.tags+', this is: '+msg.tags); - //log(LOG_DEBUG,'- NEXT is: '+next.tags+', this is: '+msg.tags); if (next.tags === msg.tags) { log(LOG_DEBUG,'- Updating last_read to: '+next.number); stats.last_read = next.number; } } + // Previous Message + x = area.MessagePrev(this.frame); + if (x) + this.key[4] = area.page(x.tags); + + // Next Message + x = area.MessageNext(this.frame); + if (x) + this.key[6] = area.page(x.tags); + log(LOG_DEBUG,'Built frame: ['+this.frame+']['+this.index+'] ('+this.page+')'); } diff --git a/load/funcs.js b/load/funcs.js index 937b87e..a47d05f 100644 --- a/load/funcs.js +++ b/load/funcs.js @@ -217,7 +217,7 @@ function atcode(field,length,pad,context) { var x = context.newMsgsToMe(); - result = x.length ? x.shift().date : ''; + result = x.length > 1 ? x[1].date : ''; break; case 'msg_area_msgtome_page': @@ -227,7 +227,7 @@ function atcode(field,length,pad,context) { } var x = context.newMsgsToMe(); - return x.length ? context.getMessagePage(x.shift().number) : null; + return x.length > 1 ? context.getMessagePage(x[1].number) : null; // Count of unread messages case 'msg_area_new': @@ -251,7 +251,7 @@ function atcode(field,length,pad,context) { break; } - result = ''+context.newMsgsToMe().length; + result = ''+(context.newMsgsToMe().length > 1 ? context.newMsgsToMe().length-1 : 0); break; // Is this message area in my new scan list diff --git a/load/msgbases.js b/load/msgbases.js index 8111f16..3631ff2 100644 --- a/load/msgbases.js +++ b/load/msgbases.js @@ -63,8 +63,12 @@ function MsgArea() { try { if (this.msgbase.open()) { - // @todo If there are more than 10,000, take only the last 10,000. - this.headers = this.msgbase.get_all_msg_headers(false,false) || []; + headers = this.msgbase.get_all_msg_headers(false,false) || []; + + // Just take the last MAX_MESSAGES + this.headers = Object.keys(headers).slice(-(MAX_PAGE_NUM+1)).map(function(key) { return headers[key]; }); + headers = undefined; + this.msgbase.close(); } else { @@ -76,8 +80,6 @@ function MsgArea() { log(LOG_ERROR,code+' cannot be opened:'+e.message); this.headers = []; } - - log(LOG_DEBUG,'msgbase:'+JSON.stringify(this.msgbase)); } }); @@ -166,7 +168,8 @@ function MsgArea() { } /** - * Unread messages + * Unread messages [1..] + * Array key 0 returns the last read message * * @returns {*[]} */ @@ -194,12 +197,21 @@ MsgArea.prototype.newMsgs = function() { MsgArea.prototype.newMsgsToMe = function() { var msgs = []; var stats = this.getUserStats(); + var last = null; //log(LOG_DEBUG,'Users scan_ptr pointer: '+JSON.stringify(stats.scan_ptr)); for(var x in this.list_tagged) { // Advance past our last scan_ptr - if (this.list_tagged[x].number <= stats.scan_ptr) + if (this.list_tagged[x].number <= stats.scan_ptr) { + if ((this.list_tagged[x].to === user.name) || (this.list_tagged[x].to === user.alias)) + last = x; + continue; + } + + // Add our previous to me message + if (msgs.length === 0) + msgs.push(last !== null ? this.list_tagged[last] : []); if ((this.list_tagged[x].to === user.name) || (this.list_tagged[x].to === user.alias)) msgs.push(this.list_tagged[x]); @@ -270,15 +282,77 @@ MsgArea.prototype.getUserStats = function() { return this.msgbase.cfg ? msg_area.grp_list[this.msgbase.cfg.grp_number].sub_list[msg_area.sub[this.msgbase.cfg.code].index] : []; } +MsgArea.prototype.MessageNext = function(page) { + var x = null; + + if (! page) + return undefined; + + var msgid = page.substr(7,4); + + for(x in this.list_tagged) { + if (this.list_tagged[x].tags === msgid) { + break; + } + + write(); // @todo This is needed for this to work? + } + + //log(LOG_DEBUG,'- Next Message is:'+JSON.stringify(this.list_tagged[(parseInt(x)+1)])+', msgid:'+msgid+', page:'+page+', x:'+x); + + /* + = Our next message is either + + x+1 if x < this.list_tagged.length + + x=0 if x == this.list_tagged.length (-1) + + null if this.list_tagged.length == null; (thus no messages) + */ + + return x === null ? null : this.list_tagged[(parseInt(x) === this.list_tagged.length-1) ? 0 : (parseInt(x)+1)]; +} + +MsgArea.prototype.MessagePrev = function(page) { + var prev = null; + var x = null; + + if (! page) + return undefined; + + var msgid = page.substr(7,4); + + for(x in this.list_tagged) { + if (this.list_tagged[x].tags === msgid) { + break; + + } else { + prev = x; + } + + write(); // @todo This is needed for this to work? + } + + /* + = Our previous message is either + + prev if a tag was found, unless + + prev is null, in which case it is this.list_tagged.length -1 + + null if x is still null (thus no messages) + */ + + // If prev is still null, then our last message must be the last one, unless x is null then there are no messages + return x === null ? null : this.list_tagged[(prev === null) ? this.list_tagged.length-1 : parseInt(prev)]; +} + /** * Tag messages with a frame number + * @note: May need to run jsexec with -m 32MB to overcome memory issues * * @returns {boolean} */ MsgArea.prototype.tag_msgs = function() { var msgs = this.list_untagged; - // See if we need to something + writeln("We have "+msgs.length+" messages to tag."); + + // See if we need to tag something if (! msgs.length) return; @@ -308,6 +382,10 @@ MsgArea.prototype.tag_msgs = function() { return true; } +MsgArea.prototype.page = function(msgid) { + return '1'+this.page_prefix+msgid; +} + MsgAreas.prototype.getArea = function(area) { log(LOG_DEBUG,'- AREA:'+JSON.stringify(area)); if (area === undefined) diff --git a/text/198a.tex b/text/198a.tex index a1fae6c..cff1dc4 100644 --- a/text/198a.tex +++ b/text/198a.tex @@ -1 +1 @@ -{"version":1,"frame":198,"index":"a","owner":1,"cost":0,"content":"G1swbRtbNzZDG1sxbS4bWzBtDQogG1szM20bWG1zZ19ncnBfbmFtZTs0MBtcG1szMEMbWzM3bRtbMW3awr/Cv7+zG1swbQ0KIBtbMzZtG1htc2dfYXJlYV9hcmVhdGFnOzQwG1wbWzMwQxtbMzdtsyCzwrSzsw0KIBtbMTszNm0bWG1zZ19hcmVhX2Rlc2M7NDAbXBtbMzBDG1sxOzM3bVN1bW1hcnkbWzBtDQobWzE7MzBtxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMSzxMTExMTExMTExMTExMTExMTExMTExMTExMTExBtbMG0NCiAbWERBVEVUSU1FOzI0G1wbWzI1QxtbMTszMG2zG1swbSAbWzFtTmV3IE1lc3NhZ2VzIHRvIFlvdRtbMG06IBtbMTszMW0bWG1zZ19hcmVhX25ld3RvbWU7LTUbXBtbMG0NChtbNTBDG1sxOzMwbbMbWzBtICAgICAbWzFtVW5yZWFkIE1lc3NhZ2VzG1swbTogG1sxOzMxbRtYbXNnX2FyZWFfbmV3Oy01G1wbWzBtDQogG1sxOzMybTEbWzM3bSBGaXJzdCB0byB5b3UgICAbWzM0bRtYbXNnX2FyZWFfbXNnb3RvbWVfZGF0ZTszMRtcG1swbSAbWzE7MzBtsxtbMG0gICAgICAbWzFtVG90YWwgTWVzc2FnZXMbWzBtOiAbWzE7MzFtG1htc2dfYXJlYV90b3RhbDstNRtcG1swbQ0KIBtbMTszMm0yG1swbSAbWzFtRmlyc3QgdW5yZWFkICAgG1sxOzM0bRtYbXNnX2FyZWFfbXNndW5yZWFkX2RhdGU7MzEbXBtbMG0gG1sxOzMwbbMbWzBtDQobWzUwQxtbMTszMG2zG1swbSAgICBQZW5kaW5nIE1lc3NhZ2VzOiAbWzMxbRtYbXNnX2FyZWFfcGVuZGluZzstNRtcG1szN20NCiAbWzE7MzJtMyAbWzM3bU9sZGVzdCBNZXNzYWdlIBtbMzRtG1htc2dfYXJlYV9tc2dvbGRlc3RfZGF0ZTszMRtcG1szN20gG1sxOzMwbbMbWzBtDQogG1sxOzMybTQgG1szN21MYXRlc3QgTWVzc2FnZSAbWzM0bRtYbXNnX2FyZWFfbXNnbmV3ZXN0X2RhdGU7MzEbXBtbMzdtIBtbMTszMG2zG1swbSAgICAgICAgICAbWzMybTkbWzBtIE5ldyBTY2FuOiAgIBtbMTszMm0bWG1zZ19hcmVhX25ld3NjYW47LTMbXBtbMG0NChtbNTBDG1sxOzMwbcEbWzBtDQogG1szMm01G1sxbSAbWzBtV3JpdGUgTmV3IE1lc3NhZ2UgICAgICAgICAgICAgICAgICAgICAgICAgG1sxOzQ0bdXNzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NzbgbWzBtDQogG1szMm02G1sxbSAbWzBtU2VhcmNoIGZvciBNZXNzYWdlICAgICAgICAgICAgICAgICAgICAgICAgG1sxOzQ0bbMbWzMzbSCvIE1lc3NhZ2UgUmVhZGluZyBOYXZpZ2F0aW9uIK4bWzA7MzM7NDRtIBtbMTszN22zG1swbQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgG1sxOzQ0bbMbWzMzbSAbWzMybRgbWzM2bSBTY3JvbGwgVVAgG1swOzQ0bSAgG1sxbbMbWzA7NDRtIBtbMTszMm0ZG1szNm0gU2Nyb2xsIERPV04bWzA7NDRtIBtbMTszM20gG1szN22zG1swbQ0KIBtbMzJtOBtbMzdtIEFyZWEgU3VtbWFyeSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIBtbMTs0NG2zG1szM20gG1swOzMyOzQ0bTQbWzE7MzZtIBtbMDszNjs0NG1QcmV2aW91cxtbMW0gIBtbMDs0NG0gIBtbMW2zG1swOzQ0bSAbWzMybTMbWzE7MzZtIBtbMDszNjs0NG1QcmV2IFRocmVhZBtbMzdtIBtbMTszM20gG1szN22zG1swbQ0KIBtbMTszMm0wG1swOzMybSAbWzE7MzdtQXJlYSBEZXNjcmlwdGlvbiAgICAgICAgICAgICAgICAgICAgICAgICAgG1sxOzQ0bbMbWzMzbSAbWzA7MzI7NDRtNhtbMTszNm0gG1swOzM2OzQ0bU5leHQbWzFtIBtbMDs0NG0gICAgICAgG1sxbbMbWzA7NDRtIBtbMzJtNxtbMzdtIBtbMzZtTmV4dCBUaHJlYWQbWzM3bSAbWzE7MzNtIBtbMzdtsxtbMG0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIBtbMTs0NG2zG1swOzQ0bSAbWzMybTUbWzM3bSAbWzM2bVdyaXRlIE5ldxtbMzdtICAgG1sxbbMbWzA7NDRtIBtbMzJtOBtbMzdtIBtbMzZtUmVwbHkbWzM3bSAgICAgICAbWzE7MzNtIBtbMzdtsxtbMG0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIBtbMTs0NG2zG1swOzQ0bSAbWzMybSMbWzM3bSAbWzM2bU1zZyBBdHRycyAgG1szN20gG1sxbbMbWzA7NDRtIBtbMTszMm0wG1szN20gG1sxOzM2bVJldHVybiBoZXJlG1szN20gG1sxOzMzbSAbWzM3bbMbWzBtDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAbWzE7NDRt1M3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NvhtbMG0NCg==","isPublic":0,"isAccessible":1,"type":"m","key":[null,null,null,null,null,null,null,null,null,null],"date":"2022-04-29T00:00:00.000Z"} +{"version":1,"frame":198,"index":"a","owner":1,"cost":0,"content":"G1swbRtbNzZDG1sxbS4bWzBtDQogG1szM20bWG1zZ19ncnBfbmFtZTs0MBtcG1szMEMbWzM3bRtbMW3awr/Cv7+zG1swbQ0KIBtbMzZtG1htc2dfYXJlYV9hcmVhdGFnOzQwG1wbWzMwQxtbMzdtsyCzwrSzsw0KIBtbMTszNm0bWG1zZ19hcmVhX2Rlc2M7NDAbXBtbMzBDG1sxOzM3bVN1bW1hcnkbWzBtDQobWzE7MzBtxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMSzxMTExMTExMTExMTExMTExMTExMTExMTExMTExBtbMG0NCiAbWERBVEVUSU1FOzI0G1wbWzI1QxtbMTszMG2zG1swbSAbWzFtTmV3IE1lc3NhZ2VzIHRvIFlvdRtbMG06IBtbMTszMW0bWG1zZ19hcmVhX25ld3RvbWU7LTUbXBtbMG0NChtbNTBDG1sxOzMwbbMbWzBtICAgICAbWzFtVW5yZWFkIE1lc3NhZ2VzG1swbTogG1sxOzMxbRtYbXNnX2FyZWFfbmV3Oy01G1wbWzBtDQogG1sxOzMybTEbWzM3bSBGaXJzdCB0byB5b3UgICAbWzM0bRtYbXNnX2FyZWFfbXNnb3RvbWVfZGF0ZTszMRtcG1swbSAbWzE7MzBtsxtbMG0gICAgICAbWzFtVG90YWwgTWVzc2FnZXMbWzBtOiAbWzE7MzFtG1htc2dfYXJlYV90b3RhbDstNRtcG1swbQ0KIBtbMTszMm0yG1swbSAbWzFtRmlyc3QgdW5yZWFkICAgG1sxOzM0bRtYbXNnX2FyZWFfbXNndW5yZWFkX2RhdGU7MzEbXBtbMG0gG1sxOzMwbbMbWzBtDQobWzUwQxtbMTszMG2zG1swbSAgICBQZW5kaW5nIE1lc3NhZ2VzOiAbWzMxbRtYbXNnX2FyZWFfcGVuZGluZzstNRtcG1szN20NCiAbWzE7MzJtMyAbWzM3bU9sZGVzdCBNZXNzYWdlIBtbMzRtG1htc2dfYXJlYV9tc2dvbGRlc3RfZGF0ZTszMRtcG1szN20gG1sxOzMwbbMbWzBtDQogG1sxOzMybTQgG1szN21MYXRlc3QgTWVzc2FnZSAbWzM0bRtYbXNnX2FyZWFfbXNnbmV3ZXN0X2RhdGU7MzEbXBtbMzdtIBtbMTszMG2zG1swbSAgICAgICAgICAbWzMybTkbWzBtIE5ldyBTY2FuOiAgIBtbMTszMm0bWG1zZ19hcmVhX25ld3NjYW47LTMbXBtbMG0NChtbNTBDG1sxOzMwbcEbWzBtDQogG1szMm01G1sxbSAbWzBtV3JpdGUgTmV3IE1lc3NhZ2UgICAgICAgICAgICAgICAgICAgICAgICAgG1sxOzQ0bdXNzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NzbgbWzBtDQogG1szMm02G1sxbSAbWzBtU2VhcmNoIGZvciBNZXNzYWdlICAgICAgICAgICAgICAgICAgICAgICAgG1sxOzQ0bbMbWzMzbSCvIE1lc3NhZ2UgUmVhZGluZyBOYXZpZ2F0aW9uIK4gG1sxOzM3bbMbWzBtDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAbWzE7NDRtsyAbWzMybRgbWzM2bSBTY3JvbGwgVVAgG1swOzQ0bSAgG1sxbbMbWzA7NDRtIBtbMTszMm0ZG1szNm0gU2Nyb2xsIERPV04bWzA7NDRtIBtbMTszM20gG1szN22zG1swbQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgG1sxOzQ0bbMgG1szMm0xG1szNm0gUHJldiBUbyBNZSAgG1sxOzMzbbMbWzA7NDRtIBtbMTszMm0yG1szNm0gTmV4dCBUbyBNZSAgG1szM20gG1szN22zG1swbQ0KIBtbMzJtOBtbMzdtIEFyZWEgU3VtbWFyeSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIBtbMTs0NG2zG1szM20gG1szMm00IBtbMzZtUHJldmlvdXMgICAgG1sxOzMzbbMbWzA7NDRtIBtbMzJtMxtbMTszNm0gG1swOzM2OzQ0bVByZXYgVGhyZWFkG1szN20gG1sxOzMzbSAbWzM3bbMbWzBtDQogG1sxOzMybTAbWzA7MzJtIBtbMTszN21BcmVhIERlc2NyaXB0aW9uICAgICAgICAgICAgICAgICAgICAgICAgICAbWzE7NDRtsxtbMzNtIBtbMzJtNhtbMzZtIE5leHQbWzFtIBtbMDs0NG0gICAgICAgG1sxbbMbWzA7NDRtIBtbMzJtNxtbMzdtIBtbMzZtTmV4dCBUaHJlYWQbWzM3bSAbWzE7MzNtIBtbMzdtsxtbMG0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIBtbMTs0NG2zG1swOzQ0bSAbWzMybTUbWzM3bSAbWzM2bVdyaXRlIE5ldxtbMzdtICAgG1sxbbMbWzA7NDRtIBtbMzJtOBtbMzdtIBtbMzZtUmVwbHkbWzM3bSAgICAgICAbWzE7MzNtIBtbMzdtsxtbMG0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIBtbMTs0NG2zG1swOzQ0bSAbWzMybSMbWzM3bSAbWzM2bU1zZyBBdHRycyAgG1szN20gG1sxbbMbWzA7NDRtIBtbMTszMm0wG1szN20gG1sxOzM2bVJldHVybiBoZXJlG1szN20gG1sxOzMzbSAbWzM3bbMbWzBtDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAbWzE7NDRt1M3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NvhtbMG0NCg==","isPublic":0,"isAccessible":1,"type":"m","key":[null,null,null,null,null,null,null,null,null,null],"date":"2022-04-29T00:00:00.000Z"}