MailJD nbsp;·nbsp; Test Dashboard nbsp;·nbsp; Coverage
LCOV - code coverage report
Current view: top level - service - NotificationBatcher.cpp (source / functions) Coverage Total Hit
Test: MailJD Coverage (Unit + E2E) Lines: 100.0 % 47 47
Test Date: 2026-06-21 21:10:19 Functions: 100.0 % 6 6
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 61.9 % 84 52

             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 : }
        

Generated by: LCOV version 2.0-1