Branch data Line data Source code
1 : : #include "NotificationBatcher.h"
2 : :
3 : : #include <QLoggingCategory>
4 : : #include <QStringList>
5 : :
6 [ + + + - : 18 : Q_LOGGING_CATEGORY(lcBatcher, "mailjd.notificationbatcher")
+ - - - ]
7 : :
8 : : namespace {
9 : : constexpr int kDefaultDebounceMs = 3000;
10 : : constexpr int kSummaryThreshold = 3; // >= this many mails → one summary
11 : : constexpr int kSummaryPreviewLines = 3;
12 : : } // namespace
13 : :
14 [ + - ]: 69 : NotificationBatcher::NotificationBatcher(QObject *parent) : QObject(parent) {
15 [ + - ]: 69 : m_debounce.setSingleShot(true);
16 [ + - ]: 69 : m_debounce.setInterval(kDefaultDebounceMs);
17 [ + - ]: 69 : connect(&m_debounce, &QTimer::timeout, this, &NotificationBatcher::flush);
18 : 69 : }
19 : :
20 : 11 : void NotificationBatcher::setDebounceMs(int ms) {
21 : 11 : m_debounce.setInterval(ms);
22 : 11 : }
23 : :
24 : 89 : void NotificationBatcher::addPending(const QString &from,
25 : : const QString &subject, qint64 uid,
26 : : qint64 folderId) {
27 : 89 : m_pending.append({from, subject, uid, folderId});
28 [ + + ]: 89 : if (m_suppressed)
29 : 37 : return; // buffered until the first INBOX sync completes
30 : 52 : m_debounce.start(); // restart: IMAP delivers headers in chunks
31 [ + - - - : 89 : }
- - ]
32 : :
33 : 12 : void NotificationBatcher::setSyncComplete(bool dropBuffered) {
34 : 12 : m_suppressed = false;
35 [ + + ]: 12 : if (dropBuffered) {
36 [ + - + - : 6 : qCInfo(lcBatcher) << "Initial mailbox load — dropping"
+ - + + ]
37 [ + - + - ]: 3 : << m_pending.size() << "buffered notifications";
38 : 3 : m_pending.clear();
39 : 3 : return;
40 : : }
41 [ + + ]: 9 : if (!m_pending.isEmpty())
42 : 1 : flush();
43 : : }
44 : :
45 : 15 : void NotificationBatcher::flush() {
46 [ - + ]: 15 : if (m_pending.isEmpty())
47 : 4 : return;
48 : 15 : const QList<PendingMail> batch = m_pending;
49 [ + - ]: 15 : m_pending.clear();
50 : :
51 [ + - + - : 30 : qCInfo(lcBatcher) << "Flushing" << batch.size() << "pending notifications";
+ - + - +
- + + ]
52 : :
53 [ + + ]: 15 : if (batch.size() < kSummaryThreshold) {
54 [ + + ]: 9 : for (const auto &m : batch)
55 [ + - ]: 5 : emit notifyIndividual(m.from, m.subject, m.uid, m.folderId);
56 : 4 : return;
57 : : }
58 : :
59 : : // Summary: first senders + subjects, then "…"
60 : 11 : QStringList lines;
61 [ + + ]: 44 : for (int i = 0; i < qMin(kSummaryPreviewLines, int(batch.size())); ++i)
62 [ + - + - ]: 33 : lines << QStringLiteral("%1 — %2").arg(batch[i].from, batch[i].subject);
63 [ + + ]: 11 : if (batch.size() > kSummaryPreviewLines)
64 [ + - ]: 8 : lines << QStringLiteral("…");
65 : :
66 : : // Newest mail = highest uid (UIDs are ascending per folder)
67 : 11 : const PendingMail *newest = &batch.first();
68 [ + + ]: 63 : for (const auto &m : batch)
69 [ + + ]: 52 : if (m.uid > newest->uid)
70 : 40 : newest = &m;
71 : :
72 [ + - + - ]: 11 : emit notifySummary(tr("%n new mails", "", int(batch.size())),
73 [ + - ]: 22 : lines.join(QLatin1Char('\n')), int(batch.size()),
74 : 11 : newest->folderId, newest->uid);
75 [ + + ]: 15 : }
|