Clean up some mess with flags, fix read/unread switching
parent
54f872e264
commit
0058d37543
|
@ -40,7 +40,7 @@ class ImapManager
|
|||
if (boxName && this.selected[connKey] != boxName)
|
||||
{
|
||||
// select different box
|
||||
await new Promise((r, e) => this.connections[connKey].openBox(boxName, true, r));
|
||||
await new Promise((r, e) => this.connections[connKey].openBox(boxName, false, r));
|
||||
this.selected[connKey] = boxName;
|
||||
}
|
||||
this.busy[connKey] = true;
|
||||
|
@ -79,7 +79,7 @@ class ImapManager
|
|||
|
||||
if (boxName)
|
||||
{
|
||||
await new Promise((r, e) => srv.openBox(boxName, true, r));
|
||||
await new Promise((r, e) => srv.openBox(boxName, false, r));
|
||||
this.selected[connKey] = boxName;
|
||||
}
|
||||
|
||||
|
@ -253,10 +253,7 @@ class ImapManager
|
|||
});
|
||||
await new Promise((r, e) => msg.once('end', r));
|
||||
msgrow.uid = attrs.uid;
|
||||
msgrow.flags = attrs.flags.map(f => f[0] == '\\' ? f.toLowerCase().replace(/^\\/, '') : f.replace(/^\$*/, '$'));
|
||||
let nf = msgrow.flags.filter(f => f != 'seen');
|
||||
nf = nf.length == msgrow.flags.length ? nf.concat(['unread']) : nf;
|
||||
msgrow.flags = nf.sort();
|
||||
msgrow.flags = attrs.flags.map(f => f[0] == '\\' ? f.toLowerCase().replace(/^\\/, '') : f.replace(/^\$*/, '$')).sort();
|
||||
return [ msgrow, attrs ];
|
||||
}
|
||||
}
|
||||
|
|
71
Syncer.js
71
Syncer.js
|
@ -283,9 +283,8 @@ class Syncer
|
|||
}
|
||||
else
|
||||
{
|
||||
// recent тут уже не будет
|
||||
let flags = m.flags.filter(f => f != 'recent').sort();
|
||||
if (fetchState.flags[m.uid].sort().join(',') != flags.join(','))
|
||||
let flags = this.transformFlags(m.flags);
|
||||
if (fetchState.flags[m.uid].join(',') != flags.join(','))
|
||||
{
|
||||
fetchState.updateFlags.push({ uid: m.uid, flags: toPgArray(flags) });
|
||||
}
|
||||
|
@ -293,7 +292,11 @@ class Syncer
|
|||
}
|
||||
}
|
||||
fetchState.synced += messages.length;
|
||||
//this.events.emit('sync', { state: 'progress', done: fetchState.synced, total: fetchState.total });
|
||||
if (fetchState.synced-(fetchState.prevSynced||0) >= fetchState.total/100)
|
||||
{
|
||||
this.events.emit('sync', { state: 'progress', done: fetchState.synced, total: fetchState.total });
|
||||
fetchState.prevSynced = fetchState.synced;
|
||||
}
|
||||
process.stderr.write('\rsynchronizing '+fetchState.synced);
|
||||
}
|
||||
|
||||
|
@ -474,6 +477,20 @@ class Syncer
|
|||
return msg;
|
||||
}
|
||||
|
||||
transformFlags(flags)
|
||||
{
|
||||
// the absence of 'seen' is transformed into the added 'unread' flag
|
||||
// 'unseen' is something that mail.ru adds by itself
|
||||
// 'unread' is removed to not mess up with our 'unread'
|
||||
flags = flags.filter(f => f != 'unseen' && f != 'recent' && f != 'unread');
|
||||
if (!flags.filter(f => f == 'seen').length)
|
||||
flags = [ ...flags, 'unread' ];
|
||||
else
|
||||
flags = flags.filter(f => f != 'seen');
|
||||
flags = flags.sort();
|
||||
return flags;
|
||||
}
|
||||
|
||||
extractAttachments(struct, attachments)
|
||||
{
|
||||
attachments = attachments || [];
|
||||
|
@ -547,7 +564,7 @@ class Syncer
|
|||
msgrow.inreplyto = header.inReplyTo && header.inReplyTo[0] || '';
|
||||
msgrow.time = header.date;
|
||||
msgrow.size = attrs.size;
|
||||
msgrow.flags = toPgArray(msgrow.flags.filter(f => f != 'recent'));
|
||||
msgrow.flags = toPgArray(this.transformFlags(msgrow.flags));
|
||||
msgrow.refs = toPgArray(header.references);
|
||||
for (let i in msgrow)
|
||||
if (typeof msgrow[i] == 'string')
|
||||
|
@ -644,7 +661,7 @@ class Syncer
|
|||
let rows = await SQL.select(
|
||||
this.pg, { m: 'messages', f: 'folders' },
|
||||
'f.account_id, m.folder_id, f.name folder_name, m.uid',
|
||||
{ id: msgIds, 'f.id=m.folder_id': [] },
|
||||
{ 'm.id': msgIds, 'f.id=m.folder_id': [] },
|
||||
{ order_by: 'm.folder_id, m.uid' }
|
||||
);
|
||||
if (!rows.length)
|
||||
|
@ -658,41 +675,63 @@ class Syncer
|
|||
}
|
||||
for (let i = 0; i < rows.length; i++)
|
||||
{
|
||||
uids.push(rows[i].uid);
|
||||
if (i == rows.length-1 || i > 0 && rows[i].folder_id != rows[i-1].folder_id)
|
||||
{
|
||||
let srv = await this.imap.getConnection(rows[i].account_id, rows[i].folder_name);
|
||||
await new Promise((r, j) => srv[action+'Flags'](uids, flags.map(f => '\\'+f.substr(0, 1).toUpperCase()+f.substr(1)), r));
|
||||
await new Promise((ok, no) => srv[action+'Flags'](
|
||||
uids,
|
||||
flags.map(f => '\\'+f.substr(0, 1).toUpperCase()+f.substr(1)),
|
||||
(err, res) => err ? no(err) : ok(res)
|
||||
));
|
||||
this.imap.releaseConnection(rows[i].account_id);
|
||||
uids = [];
|
||||
}
|
||||
else
|
||||
{
|
||||
uids.push(rows[i].uid);
|
||||
}
|
||||
}
|
||||
let upd = 'flags', bind = [];
|
||||
if (action == 'add')
|
||||
{
|
||||
for (let flag of flags)
|
||||
{
|
||||
upd = upd + ' || (case when flags @> array[?] then \'{}\' else array[?] end)';
|
||||
bind.push(flag, flag);
|
||||
if (flag == 'seen')
|
||||
{
|
||||
// instead of the 'seen' flag we store the absence of 'unread'
|
||||
upd = 'array_remove(' + upd + ', ?)';
|
||||
bind.push('unread');
|
||||
}
|
||||
else
|
||||
{
|
||||
upd = upd + ' || (case when flags @> array[?] then \'{}\' else array[?] end)';
|
||||
bind.push(flag, flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (action == 'del')
|
||||
{
|
||||
for (let flag of flags)
|
||||
{
|
||||
upd = 'array_remove('+upd+', ?)';
|
||||
bind.push(flag);
|
||||
if (flag == 'seen')
|
||||
{
|
||||
// instead of the absence of 'seen' flag we store 'unread'
|
||||
upd = upd + ' || (case when flags @> array[?] then \'{}\' else array[?] end)';
|
||||
bind.push('unread', 'unread');
|
||||
}
|
||||
else
|
||||
{
|
||||
upd = 'array_remove('+upd+', ?)';
|
||||
bind.push(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flags = flags.filter(f => f == 'seen').length > 0
|
||||
? flags.filter(f => f != 'seen')
|
||||
: [ ...flags, 'unread' ];
|
||||
upd = 'array[' + flags.map(f => '?').join(', ') + ']::text[]';
|
||||
bind = [ ...flags ];
|
||||
}
|
||||
await SQL.update(this.pg, 'messages', { ['flags = '+upd]: bind }, { id: msgIds });
|
||||
await SQL.update(this.pg, 'messages m', { ['flags = '+upd]: bind }, { 'm.id': msgIds });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
17
SyncerWeb.js
17
SyncerWeb.js
|
@ -77,11 +77,14 @@ class SyncerWeb
|
|||
'select id, name, email, settings->\'folders\' folderMap,'+
|
||||
' (select count(*) from messages m, folders f'+
|
||||
' where m.folder_id=f.id and f.account_id=a.id'+
|
||||
' and (flags @> array[\'pinned\',\'unread\'])) pinned_unread_count'+
|
||||
' and (flags @> array[\'flagged\',\'unread\'])) pinned_unread_count, '+
|
||||
' (select count(*) from messages m, folders f'+
|
||||
' where m.folder_id=f.id and f.account_id=a.id'+
|
||||
' and (flags @> array[\'flagged\'])) pinned_count'+
|
||||
' from accounts a'
|
||||
)).rows;
|
||||
const folders = (await this.pg.query(
|
||||
'select id, account_id, name,'+
|
||||
'select id, account_id, name, kind,'+
|
||||
' (select count(*) from messages m where m.folder_id=f.id) total_count,'+
|
||||
' (select count(*) from messages m where m.folder_id=f.id and (flags @> array[\'unread\'])) unread_count'+
|
||||
' from folders f order by account_id, name'
|
||||
|
@ -106,15 +109,11 @@ class SyncerWeb
|
|||
{
|
||||
p['m.folder_id'] = query.folderId;
|
||||
}
|
||||
else if (query.folderType == 'unread')
|
||||
{
|
||||
p['(flags @> array[\'unread\'])'] = [];
|
||||
}
|
||||
else if (query.folderType == 'pinned')
|
||||
{
|
||||
p['(flags @> array[\'flagged\'])'] = [];
|
||||
}
|
||||
else if (query.folderType == 'inbox')
|
||||
else if (query.folderType == 'inbox' || query.folderType == 'unread')
|
||||
{
|
||||
let folders = Object.keys(this.syncer.accounts)
|
||||
.map(id => [ id, this.syncer.accounts[id].settings.folders.spam ])
|
||||
|
@ -122,6 +121,10 @@ class SyncerWeb
|
|||
p['(f.account_id, f.name) NOT IN ('+folders.map(f => '(?, ?)').join(', ')+')'] =
|
||||
[].concat.apply([], folders);
|
||||
p['f.kind NOT IN (?, ?, ?)'] = [ 'sent', 'drafts', 'trash' ];
|
||||
if (query.folderType == 'unread')
|
||||
{
|
||||
p['(flags @> array[\'unread\'])'] = [];
|
||||
}
|
||||
}
|
||||
else if (query.folderType == 'sent')
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue