Skip to content

Commit

Permalink
New mail notifications from backend (maildir)
Browse files Browse the repository at this point in the history
  • Loading branch information
elshize authored and flatcap committed Apr 14, 2023
1 parent ba34856 commit 5dfc1a0
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 55 deletions.
4 changes: 4 additions & 0 deletions core/mailbox.c
Expand Up @@ -76,6 +76,10 @@ struct Mailbox *mailbox_new(void)
m->emails = mutt_mem_calloc(m->email_max, sizeof(struct Email *));
m->v2r = mutt_mem_calloc(m->email_max, sizeof(int));
m->gen = mailbox_gen();
#ifdef USE_DEVEL_NEW_MAIL
m->last_notified.tv_sec = 0;
m->last_notified.tv_nsec = 0;
#endif

return m;
}
Expand Down
9 changes: 6 additions & 3 deletions core/mailbox.h
Expand Up @@ -92,6 +92,9 @@ struct Mailbox
int msg_new; ///< Number of new messages
int msg_deleted; ///< Number of deleted messages
int msg_tagged; ///< How many messages are tagged?
#ifdef USE_DEVEL_NEW_MAIL
int msg_unnotified; ///< Number of messages we have not notified about
#endif

struct Email **emails; ///< Array of Emails
int email_max; ///< Number of pointers in emails
Expand All @@ -103,6 +106,9 @@ struct Mailbox
bool newly_created; ///< Mbox or mmdf just popped into existence
struct timespec mtime; ///< Time Mailbox was last changed
struct timespec last_visited; ///< Time of last exit from this mailbox
#ifdef USE_DEVEL_NEW_MAIL
struct timespec last_notified; ///< Time when the user was last notified about new messages.
#endif

const struct MxOps *mx_ops; ///< MXAPI callback functions

Expand Down Expand Up @@ -180,15 +186,12 @@ enum NotifyMailbox
NT_MAILBOX_NEW_MAIL, ///< New messages have been added
};

ARRAY_HEAD(EmailArray, struct Email *);

/**
* struct EventMailbox - An Event that happened to a Mailbox
*/
struct EventMailbox
{
struct Mailbox *mailbox; ///< The Mailbox this Event relates to
struct EmailArray emails; ///< List of emails associated with the event
};

void mailbox_changed (struct Mailbox *m, enum NotifyMailbox action);
Expand Down
36 changes: 36 additions & 0 deletions maildir/maildir.c
Expand Up @@ -46,10 +46,12 @@
#include <utime.h>
#include "private.h"
#include "mutt/lib.h"
#include "mutt/notify.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "lib.h"
#include "newmail/lib.h"
#include "progress/lib.h"
#include "copy.h"
#include "edata.h"
Expand Down Expand Up @@ -95,6 +97,10 @@ static void maildir_check_dir(struct Mailbox *m, const char *dir_name,
struct Buffer *msgpath = buf_pool_get();
buf_printf(path, "%s/%s", mailbox_path(m), dir_name);

#ifdef USE_DEVEL_NEW_MAIL
bool check_unnotified = check_new;
#endif

/* when $mail_check_recent is set, if the new/ directory hasn't been modified since
* the user last exited the m, then we know there is no recent mail. */
const bool c_mail_check_recent = cs_subset_bool(NeoMutt->sub, "mail_check_recent");
Expand Down Expand Up @@ -136,6 +142,22 @@ static void maildir_check_dir(struct Mailbox *m, const char *dir_name,
{
if (check_stats)
m->msg_unread++;

#ifdef USE_DEVEL_NEW_MAIL
if (check_unnotified)
{
struct timespec created;
buf_printf(msgpath, "%s/%s", buf_string(path), de->d_name);
stat(buf_string(msgpath), &st);
mutt_file_get_stat_timespec(&created, &st, MUTT_STAT_CTIME);
if (mutt_file_timespec_compare(&m->last_notified, &created) < 0)
{
mutt_debug(LL_DEBUG1, "Unnotified %s/%s\n", buf_string(path), de->d_name);
m->msg_unnotified++;
}
}
#endif

if (check_new)
{
if (c_mail_check_recent)
Expand Down Expand Up @@ -1361,6 +1383,9 @@ static enum MxStatus maildir_mbox_check_stats(struct Mailbox *m, uint8_t flags)
m->msg_count = 0;
m->msg_unread = 0;
m->msg_flagged = 0;
#ifdef USE_DEVEL_NEW_MAIL
m->msg_unnotified = 0;
#endif
}

maildir_check_dir(m, "new", check_new, check_stats);
Expand All @@ -1370,6 +1395,17 @@ static enum MxStatus maildir_mbox_check_stats(struct Mailbox *m, uint8_t flags)
if (check_new || check_stats)
maildir_check_dir(m, "cur", check_new, check_stats);

#ifdef USE_DEVEL_NEW_MAIL
if (check_stats && m->msg_unnotified > 0)
{
mutt_debug(LL_DEBUG1, "Unnotified = %d\n", m->msg_unnotified);
struct EventMailbox ev_m = { m };
notify_send(m->notify, NT_MAILBOX, NT_MAILBOX_NEW_MAIL, &ev_m);
clock_gettime(CLOCK_REALTIME, &m->last_notified);
mutt_debug(LL_DEBUG2, "resetting time\n");
}
#endif

return m->msg_new ? MX_STATUS_NEW_MAIL : MX_STATUS_OK;
}

Expand Down
35 changes: 0 additions & 35 deletions mx.c
Expand Up @@ -84,10 +84,6 @@
#include <xlocale.h>
#endif

#ifdef USE_DEVEL_NEW_MAIL
static time_t LastNotified = 0; ///< Time of last new mail notification.
#endif

static const struct Mapping MboxTypeMap[] = {
// clang-format off
{ "mbox", MUTT_MBOX, },
Expand Down Expand Up @@ -1125,24 +1121,6 @@ struct Message *mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpe
return msg;
}

/**
* find_new_emails - XXX
*/
void find_new_emails(const struct Mailbox *mailbox, time_t last_notified,
struct EmailArray *emails)
{
mutt_debug(LL_DEBUG1, "Mailbox: %s\n", mailbox_path(mailbox));
mutt_debug(LL_DEBUG1, "MSG COUNT: %d\n", mailbox->msg_count);
mutt_debug(LL_DEBUG1, "Unread: %d\n", mailbox->msg_unread);
for (int i = 0; i < mailbox->msg_count; i++)
{
struct Email *email = mailbox->emails[i];
mutt_debug(LL_DEBUG1, "msg(%d): %d\n", i, email);
// if (last_notified < mailbox->emails[i]->received)
// ARRAY_ADD(emails, mailbox->emails[i]);
}
}

/**
* mx_mbox_check - Check for new mail - Wrapper for MxOps::mbox_check()
* @param m Mailbox
Expand All @@ -1158,19 +1136,6 @@ enum MxStatus mx_mbox_check(struct Mailbox *m)
{
mailbox_changed(m, NT_MAILBOX_INVALID);
}
#ifdef USE_DEVEL_NEW_MAIL
if (rc == MX_STATUS_NEW_MAIL)
{
if (LastNotified > 0)
{
struct EventMailbox ev_m = { m, ARRAY_HEAD_INITIALIZER };
find_new_emails(m, LastNotified, &ev_m.emails);
if (!ARRAY_EMPTY(&ev_m.emails))
notify_send(m->notify, NT_MAILBOX, NT_MAILBOX_NEW_MAIL, &ev_m);
}
LastNotified = mutt_date_epoch();
}
#endif

return rc;
}
Expand Down
1 change: 1 addition & 0 deletions newmail/lib.h
Expand Up @@ -25,6 +25,7 @@

#include <stdint.h>
#include <stdio.h>
#include "mutt/lib.h"
#include "format_flags.h"

struct NotifyCallback;
Expand Down
11 changes: 6 additions & 5 deletions newmail/new_mail.c
Expand Up @@ -63,17 +63,19 @@ const char *new_mail_format_str(char *buf, size_t buflen, size_t col, int cols,
{
struct EventMailbox *ev_m = (struct EventMailbox *) data;
struct Mailbox *mailbox = ev_m->mailbox;
struct EmailArray *emails = &ev_m->emails;

switch (op)
{
case 'c':
snprintf(buf, buflen, "%ld", ARRAY_SIZE(emails));
case 'n':
snprintf(buf, buflen, "%d", mailbox->msg_unnotified);
break;
case 'N':
snprintf(buf, buflen, "%d", mailbox->msg_new);
break;
case 'f':
snprintf(buf, buflen, "%s", NONULL(mailbox_path(mailbox)));
break;
case 'n':
case 'F':
snprintf(buf, buflen, "%s", NONULL(mailbox->name));
break;
case 'u':
Expand All @@ -96,7 +98,6 @@ int handle_new_mail_event(const char *cmd, struct NotifyCallback *nc, Execute *e
mutt_expando_format(expanded_cmd, 1024, 0, 1024, cmd, new_mail_format_str,
(intptr_t) ev_m, MUTT_FORMAT_NO_FLAGS);
execute(expanded_cmd);
ARRAY_FREE(&ev_m->emails);
return 0;
}

Expand Down
20 changes: 9 additions & 11 deletions test/newmail/new_mail_format_str.c
Expand Up @@ -42,15 +42,15 @@ void test_new_mail_format_str(void)
mailbox->name = mutt_str_dup("MailBox");
mailbox->pathbuf = buf_make(16);
mailbox->msg_unread = 7;
mailbox->msg_unnotified = 2;
mailbox->msg_new = 3;
buf_strcpy(&mailbox->pathbuf, "/path");

struct EventMailbox ev_m = { mailbox, ARRAY_HEAD_INITIALIZER };
ARRAY_ADD(&ev_m.emails, email_new());
ARRAY_ADD(&ev_m.emails, email_new());
struct EventMailbox ev_m = { mailbox };

intptr_t data = (intptr_t) &ev_m;

new_mail_format_str((char *) buf, 64, col, cols, 'n', NULL, NULL, NULL, NULL, data, 0);
new_mail_format_str((char *) buf, 64, col, cols, 'F', NULL, NULL, NULL, NULL, data, 0);
TEST_CHECK(mutt_str_equal(buf, "MailBox"));
TEST_MSG("Check failed: %s != MailBox", buf);

Expand All @@ -62,15 +62,13 @@ void test_new_mail_format_str(void)
TEST_CHECK(mutt_str_equal(buf, "7"));
TEST_MSG("Check failed: %s != 7", buf);

new_mail_format_str((char *) buf, 64, col, cols, 'c', NULL, NULL, NULL, NULL, data, 0);
new_mail_format_str((char *) buf, 64, col, cols, 'n', NULL, NULL, NULL, NULL, data, 0);
TEST_CHECK(mutt_str_equal(buf, "2"));
TEST_MSG("Check failed: %s != 2", buf);

struct Email **email;
ARRAY_FOREACH(email, &ev_m.emails)
{
email_free(email);
}
ARRAY_FREE(&ev_m.emails);
new_mail_format_str((char *) buf, 64, col, cols, 'N', NULL, NULL, NULL, NULL, data, 0);
TEST_CHECK(mutt_str_equal(buf, "3"));
TEST_MSG("Check failed: %s != 3", buf);

mailbox_free(&mailbox);
}
2 changes: 1 addition & 1 deletion test/newmail/new_mail_observer.c
Expand Up @@ -48,7 +48,7 @@ void test_new_mail_observer(void)
notify_observer_add(notify, NT_MAILBOX, dummy_new_mail_observer, NULL);
struct Mailbox *mailbox = mailbox_new();
mailbox->name = mutt_str_dup("Mailbox");
struct EventMailbox event = { mailbox, ARRAY_HEAD_INITIALIZER };
struct EventMailbox event = { mailbox };

notify_send(notify, NT_MAILBOX, NT_MAILBOX_NEW_MAIL, NULL);
TEST_CHECK(message == NULL);
Expand Down

0 comments on commit 5dfc1a0

Please sign in to comment.