message: support 'personal' flag for messages

Add a new flag 'personal' for a message, which means that at least one of the
contact fields is personal.
This commit is contained in:
Dirk-Jan C. Binnema 2022-05-01 11:18:57 +03:00
parent a4f39819ee
commit ee4b3bda2d
5 changed files with 33 additions and 10 deletions

View File

@ -166,7 +166,7 @@ test_flag_info()
{ {
static_assert(flag_info('D')->flag == Flags::Draft); static_assert(flag_info('D')->flag == Flags::Draft);
static_assert(flag_info('l')->flag == Flags::MailingList); static_assert(flag_info('l')->flag == Flags::MailingList);
static_assert(!flag_info('q')); static_assert(!flag_info('y'));
static_assert(flag_info("trashed")->flag == Flags::Trashed); static_assert(flag_info("trashed")->flag == Flags::Trashed);
static_assert(flag_info("attach")->flag == Flags::HasAttachment); static_assert(flag_info("attach")->flag == Flags::HasAttachment);

View File

@ -63,11 +63,12 @@ enum struct Flags {
* other content flags * other content flags
*/ */
MailingList = 1 << 11, /**< A mailing-list message */ MailingList = 1 << 11, /**< A mailing-list message */
Personal = 1 << 12, /**< A personal message (i.e., at least one of the
* contact fields contains a personal address) */
/* /*
* <private> * <private>
*/ */
_final_ = 1 << 12 _final_ = 1 << 13
}; };
MU_ENABLE_BITOPS(Flags); MU_ENABLE_BITOPS(Flags);
@ -90,7 +91,9 @@ enum struct MessageFlagCategory {
struct MessageFlagInfo { struct MessageFlagInfo {
Flags flag; /**< The message flag */ Flags flag; /**< The message flag */
char shortcut; /**< Shortcut character */ char shortcut; /**< Shortcut character;
* tolower(shortcut) must be
* unique for all flags */
std::string_view name; /**< Name of the flag */ std::string_view name; /**< Name of the flag */
MessageFlagCategory category; /**< Flag category */ MessageFlagCategory category; /**< Flag category */
std::string_view description; /**< Description */ std::string_view description; /**< Description */
@ -109,7 +112,7 @@ struct MessageFlagInfo {
/** /**
* Array of all flag information. * Array of all flag information.
*/ */
constexpr std::array<MessageFlagInfo, 12> AllMessageFlagInfos = {{ constexpr std::array<MessageFlagInfo, 13> AllMessageFlagInfos = {{
MessageFlagInfo{Flags::Draft, 'D', "draft", MessageFlagCategory::Mailfile, MessageFlagInfo{Flags::Draft, 'D', "draft", MessageFlagCategory::Mailfile,
"Draft (in progress)" "Draft (in progress)"
}, },
@ -147,6 +150,9 @@ constexpr std::array<MessageFlagInfo, 12> AllMessageFlagInfos = {{
MessageFlagInfo{Flags::MailingList, 'l', "list", MessageFlagCategory::Content, MessageFlagInfo{Flags::MailingList, 'l', "list", MessageFlagCategory::Content,
"Mailing list message" "Mailing list message"
}, },
MessageFlagInfo{Flags::Personal, 'q', "personal", MessageFlagCategory::Content,
"Personal message"
},
}}; }};

View File

@ -221,9 +221,9 @@ ContactsCache::add(Contact&& contact)
void void
ContactsCache::add(Contacts&& contacts) ContactsCache::add(Contacts&& contacts, bool& personal)
{ {
const auto personal = seq_find_if(contacts,[&](auto&& c){ personal = seq_find_if(contacts,[&](auto&& c){
return is_personal(c.email); }) != contacts.cend(); return is_personal(c.email); }) != contacts.cend();
for (auto&& contact: contacts) { for (auto&& contact: contacts) {

View File

@ -66,8 +66,15 @@ public:
* any of the senders/recipients are considered "personal" * any of the senders/recipients are considered "personal"
* *
* @param contacts a Contact object sequence * @param contacts a Contact object sequence
* @param is_personal receives true if any of the contacts was personal;
* false otherwise
*/ */
void add(Contacts&& contacts); void add(Contacts&& contacts, bool& is_personal);
void add(Contacts&& contacts) {
bool _ignore;
add(std::move(contacts), _ignore);
}
/** /**
* Clear all contacts * Clear all contacts

View File

@ -344,14 +344,24 @@ Store::add_message(Message& msg, bool use_transaction)
if (auto&& res = msg.set_maildir(mdir.value()); !res) if (auto&& res = msg.set_maildir(mdir.value()); !res)
return Err(res.error()); return Err(res.error());
/* add contacts from this message to cache; this cache
* also determines whether those contacts are _personal_, i.e. match
* our personal addresses.
*
* if a message has any personal contacts, mark it as personal; do
* this by updating the message flags.
*/
bool is_personal{};
priv_->contacts_cache_.add(msg.all_contacts(), is_personal);
if (is_personal)
msg.set_flags(msg.flags() | Flags::Personal);
/* now, we're done with all the fields; generate the sexp string for this /* now, we're done with all the fields; generate the sexp string for this
* message */ * message */
msg.update_cached_sexp(); msg.update_cached_sexp();
std::lock_guard guard{priv_->lock_}; std::lock_guard guard{priv_->lock_};
priv_->contacts_cache_.add(msg.all_contacts());
const auto docid = xapian_try([&]{ const auto docid = xapian_try([&]{
if (use_transaction) if (use_transaction)