diff options
author | George Hazan <ghazan@miranda.im> | 2020-02-29 21:32:45 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2020-02-29 21:32:45 +0300 |
commit | f0173fd8343e7f1469b40ea8372f6b951846f63b (patch) | |
tree | 05a775d2c18d8eb43d7172bd4e13203d75e83e0a /plugins/MessageState | |
parent | 5792d59c3ed577096556b744a51bb375e59c325f (diff) |
MessageState: rewritten from scratch to work
Diffstat (limited to 'plugins/MessageState')
-rw-r--r-- | plugins/MessageState/src/clist_extra.cpp | 21 | ||||
-rw-r--r-- | plugins/MessageState/src/global.h | 39 | ||||
-rw-r--r-- | plugins/MessageState/src/messagestate.cpp | 125 | ||||
-rw-r--r-- | plugins/MessageState/src/services.cpp | 38 | ||||
-rw-r--r-- | plugins/MessageState/src/stdafx.h | 1 | ||||
-rw-r--r-- | plugins/MessageState/src/utils.cpp | 28 | ||||
-rw-r--r-- | plugins/MessageState/src/version.h | 6 |
7 files changed, 139 insertions, 119 deletions
diff --git a/plugins/MessageState/src/clist_extra.cpp b/plugins/MessageState/src/clist_extra.cpp deleted file mode 100644 index 01a0f52739..0000000000 --- a/plugins/MessageState/src/clist_extra.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "stdafx.h"
-
-HANDLE hExtraIcon = nullptr;
-
-int ExtraIconsApply(WPARAM hContact, LPARAM force)
-{
- if (hContact != NULL) {
- if (HasUnread(hContact) || force)
- ExtraIcon_SetIcon(hExtraIcon, hContact, Icons[ICON_EXTRA].hIcolib);
- else
- ExtraIcon_Clear(hExtraIcon, hContact);
- }
-
- return 0;
-}
-
-void InitClistExtraIcon()
-{
- hExtraIcon = ExtraIcon_RegisterIcolib("messagestate_unread", LPGEN("MessageState unread extra icon"), "clist_unread_icon");
- HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, ExtraIconsApply);
-}
diff --git a/plugins/MessageState/src/global.h b/plugins/MessageState/src/global.h index 9260116846..0413f2535d 100644 --- a/plugins/MessageState/src/global.h +++ b/plugins/MessageState/src/global.h @@ -1,32 +1,43 @@ #ifndef _GLOBAL_H_
#define _GLOBAL_H_
-enum SRMM_ICON_TYPE
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct ContactData
{
- ICON_HIDDEN = -1,
- ICON_UNREAD,
- ICON_READ,
- ICON_FAILED,
- ICON_NOSENT,
- ICON_EXTRA,
+ ContactData(MCONTACT _p1) :
+ hContact(_p1)
+ {}
+
+ MCONTACT hContact;
+
+ int type = -1, bHidden = true;
+ __time64_t dwLastReadTime = 0, dwLastSentTime = 0;
+
+ void __forceinline setSent(__time64_t _time)
+ {
+ dwLastSentTime = _time;
+ type = 0;
+ }
};
-#define DBKEY_MESSAGE_READ_TIME "LastMsgReadTime"
-#define DBKEY_MESSAGE_READ_TIME_TYPE "LastMsgReadTimeType"
+extern OBJLIST<ContactData> g_arContacts;
+
+ContactData* FindContact(MCONTACT);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
__forceinline bool CheckProtoSupport(const char *szProto)
{ return (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_READNOTIFY) != 0;
}
void InitServices();
-INT_PTR UpdateService(WPARAM, LPARAM);
-int IconsUpdate(MCONTACT);
-void SetSRMMIcon(MCONTACT hContact, SRMM_ICON_TYPE type, time_t time = 0);
+void IconsUpdate(MCONTACT);
+void SetSRMMIcon(MCONTACT hContact, int type, time_t time = 0);
time_t GetLastSentMessageTime(MCONTACT hContact);
int OnModulesLoaded(WPARAM, LPARAM);
bool HasUnread(MCONTACT hContact);
-int ExtraIconsApply(WPARAM hContact, LPARAM);
-void InitClistExtraIcon();
#endif //_GLOBAL_H_
\ No newline at end of file diff --git a/plugins/MessageState/src/messagestate.cpp b/plugins/MessageState/src/messagestate.cpp index 10735e977c..61a2885639 100644 --- a/plugins/MessageState/src/messagestate.cpp +++ b/plugins/MessageState/src/messagestate.cpp @@ -1,64 +1,66 @@ #include "stdafx.h"
-IconItem Icons[] =
-{
- { LPGEN("Unread message icon"), "unread_icon", IDI_UNREAD },
- { LPGEN("Read message icon"), "read_icon", IDI_READ },
- { LPGEN("Failed sending icon"), "fail_icon", IDI_FAIL },
- { LPGEN("Sending message icon"), "nosent_icon", IDI_NOSENT },
- { LPGEN("Unread clist extra icon"), "clist_unread_icon", IDI_EXTRA },
-};
-
-const wchar_t* Tooltips[] =
+static HANDLE hExtraIcon = nullptr;
+
+int ExtraIconsApply(WPARAM hContact, LPARAM force)
{
- LPGENW("Last message is not read"),
- LPGENW("Last message read"),
- LPGENW("Last message was not sent"),
- LPGENW("Sending...")
-};
+ if (hContact != 0) {
+ if (HasUnread(hContact) || force)
+ ExtraIcon_SetIcon(hExtraIcon, hContact, g_plugin.getIconHandle(IDI_EXTRA));
+ else
+ ExtraIcon_Clear(hExtraIcon, hContact);
+ }
+
+ return 0;
+}
-void SetSRMMIcon(MCONTACT hContact, SRMM_ICON_TYPE type, time_t time)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void SetSRMMIcon(MCONTACT hContact, int iconId, time_t time)
{
- MCONTACT hActualContact;
- if (db_mc_isMeta(hContact))
- hActualContact = db_mc_getSrmmSub(hContact);
- else
- hActualContact = hContact;
-
- if (type != ICON_HIDDEN) {
- const wchar_t *pwszToolTip;
- if (type == ICON_READ) {
- if (g_plugin.getDword(hActualContact, DBKEY_MESSAGE_READ_TIME_TYPE, -1) == MRD_TYPE_READTIME) {
- wchar_t buf[100];
- wcsftime(buf, _countof(buf), TranslateT("Last message read at %X %x"), localtime(&time));
- pwszToolTip = buf;
- }
- else pwszToolTip = TranslateT("Last message read (unknown time)");
+ auto *p = FindContact(hContact);
+
+ const wchar_t *pwszToolTip;
+ switch (iconId) {
+ case IDI_READ:
+ // if that contact was never marked as read
+ if (p->type != -1) {
+ wchar_t buf[100];
+ wcsftime(buf, _countof(buf), TranslateT("Last message read at %X %x"), localtime(&time));
+ pwszToolTip = buf;
}
- else pwszToolTip = TranslateW(Tooltips[type]);
-
- Srmm_ModifyIcon(hContact, MODULENAME, 1, IcoLib_GetIconByHandle(Icons[type].hIcolib), pwszToolTip);
+ else pwszToolTip = TranslateT("Last message read");
+ break;
+
+ case IDI_UNREAD: pwszToolTip = TranslateT("Last message is not read"); break;
+ case IDI_FAIL: pwszToolTip = TranslateT("Last message was not sent"); break;
+ case IDI_NOSENT: pwszToolTip = TranslateT("Sending..."); break;
+ default: pwszToolTip = nullptr;
}
- else Srmm_SetIconFlags(hContact, MODULENAME, 1, MBF_HIDDEN);
+
+ Srmm_ModifyIcon(hContact, MODULENAME, 1, g_plugin.getIcon(iconId), pwszToolTip);
}
-int IconsUpdate(MCONTACT hContact)
+void IconsUpdate(MCONTACT hContact)
{
- MCONTACT hActualContact;
- if (db_mc_isMeta(hContact))
- hActualContact = db_mc_getSrmmSub(hContact);
- else
- hActualContact = hContact;
-
- time_t readtime = g_plugin.getDword(hActualContact, DBKEY_MESSAGE_READ_TIME, 0);
- time_t lasttime = GetLastSentMessageTime(hActualContact);
- if (lasttime != -1 && readtime != 0)
- SetSRMMIcon(hContact, HasUnread(hActualContact) ? ICON_UNREAD : ICON_READ, readtime);
- else
- SetSRMMIcon(hContact, ICON_HIDDEN);
+ auto *p = FindContact(hContact);
+
+ // if we've did nothing with this contact, leave its icon hidden
+ if (p->type == -1)
+ return;
+
+ // if that's the first time we show an icon, unhide it first
+ if (p->bHidden) {
+ p->bHidden = false;
+ Srmm_SetIconFlags(hContact, MODULENAME, 1, 0);
+ }
+
+ SetSRMMIcon(hContact, p->type == MRD_TYPE_DELIVERED ? IDI_UNREAD : IDI_READ, p->dwLastReadTime);
ExtraIconsApply(hContact, 0);
- return 0;
+
+ if (db_mc_isSub(hContact))
+ IconsUpdate(db_mc_getMeta(hContact));
}
static int OnProtoAck(WPARAM, LPARAM lParam)
@@ -66,9 +68,9 @@ static int OnProtoAck(WPARAM, LPARAM lParam) ACKDATA *pAck = (ACKDATA *)lParam;
if (pAck && (pAck->type == ACKTYPE_MESSAGE || pAck->type == ACKTYPE_FILE) && CheckProtoSupport(pAck->szModule)) {
if (pAck->result == ACKRESULT_SUCCESS)
- SetSRMMIcon(pAck->hContact, ICON_UNREAD);
+ SetSRMMIcon(pAck->hContact, IDI_NOSENT);
else if (pAck->result == ACKRESULT_FAILED)
- SetSRMMIcon(pAck->hContact, ICON_FAILED);
+ SetSRMMIcon(pAck->hContact, IDI_FAIL);
ExtraIconsApply(pAck->hContact, 0);
}
@@ -78,8 +80,14 @@ static int OnProtoAck(WPARAM, LPARAM lParam) static int OnEventFilterAdd(WPARAM hContact, LPARAM lParam)
{
DBEVENTINFO *dbei = (DBEVENTINFO *)lParam;
- if ((dbei->flags & DBEF_SENT) && CheckProtoSupport(dbei->szModule) && db_get_b(hContact, "Tab_SRMsg", "no_ack", 0))
- SetSRMMIcon(hContact, ICON_NOSENT);
+ if ((dbei->flags & DBEF_SENT) && CheckProtoSupport(dbei->szModule)) {
+ __time64_t dwTime = _time64(0);
+ FindContact(hContact)->setSent(dwTime);
+ if (db_mc_isSub(hContact))
+ FindContact(db_mc_getMeta(hContact))->setSent(dwTime);
+
+ SetSRMMIcon(hContact, IDI_NOSENT);
+ }
return 0;
}
@@ -99,24 +107,19 @@ static int OnMetaChanged(WPARAM hContact, LPARAM) int OnModulesLoaded(WPARAM, LPARAM)
{
+ hExtraIcon = ExtraIcon_RegisterIcolib("messagestate_unread", LPGEN("MessageState unread extra icon"), "clist_unread_icon");
+
HookEvent(ME_PROTO_ACK, OnProtoAck);
HookEvent(ME_DB_EVENT_FILTER_ADD, OnEventFilterAdd);
HookEvent(ME_MC_DEFAULTTCHANGED, OnMetaChanged);
HookEvent(ME_MC_SUBCONTACTSCHANGED, OnMetaChanged);
HookEvent(ME_MSG_WINDOWEVENT, OnSrmmWindowOpened);
-
- g_plugin.registerIcon(MODULENAME, Icons);
+ HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, ExtraIconsApply);
StatusIconData sid = {};
sid.szModule = MODULENAME;
sid.flags = MBF_HIDDEN;
sid.dwId = 1;
Srmm_AddIcon(&sid, &g_plugin);
-
- InitClistExtraIcon();
-
- for (auto &hContact : Contacts())
- IconsUpdate(hContact);
-
return 0;
}
diff --git a/plugins/MessageState/src/services.cpp b/plugins/MessageState/src/services.cpp index 4e2706d1e5..8e7b6dbe17 100644 --- a/plugins/MessageState/src/services.cpp +++ b/plugins/MessageState/src/services.cpp @@ -1,19 +1,37 @@ #include "stdafx.h"
-HANDLE hUpdateService;
-
-void InitServices()
+static IconItem Icons[] =
{
- hUpdateService = CreateServiceFunction(MS_MESSAGESTATE_UPDATE, UpdateService);
-}
+ { LPGEN("Unread message icon"), "unread_icon", IDI_UNREAD },
+ { LPGEN("Read message icon"), "read_icon", IDI_READ },
+ { LPGEN("Failed sending icon"), "fail_icon", IDI_FAIL },
+ { LPGEN("Sending message icon"), "nosent_icon", IDI_NOSENT },
+ { LPGEN("Unread clist extra icon"), "clist_unread_icon", IDI_EXTRA },
+};
-INT_PTR UpdateService(WPARAM hContact, LPARAM lParam)
+static INT_PTR UpdateService(WPARAM hContact, LPARAM lParam)
{
- MessageReadData *mrd = (MessageReadData*)lParam;
- if (mrd->dw_lastTime > g_plugin.getDword(hContact, DBKEY_MESSAGE_READ_TIME, 0)) {
- g_plugin.setDword(hContact, DBKEY_MESSAGE_READ_TIME, mrd->dw_lastTime);
- g_plugin.setDword(hContact, DBKEY_MESSAGE_READ_TIME_TYPE, mrd->iTimeType);
+ auto *p = FindContact(hContact);
+
+ __time64_t currTime = _time64(0);
+ if (currTime > p->dwLastReadTime) {
+ p->dwLastReadTime = currTime;
+ p->type = lParam;
+
+ if (db_mc_isSub(hContact)) {
+ p = FindContact(db_mc_getMeta(hContact));
+ p->dwLastReadTime = currTime;
+ p->type = lParam;
+ }
+
IconsUpdate(hContact);
}
return 0;
}
+
+void InitServices()
+{
+ g_plugin.registerIcon(MODULENAME, Icons);
+
+ CreateServiceFunction(MS_MESSAGESTATE_UPDATE, UpdateService);
+}
diff --git a/plugins/MessageState/src/stdafx.h b/plugins/MessageState/src/stdafx.h index ce6df98224..8a3d16d073 100644 --- a/plugins/MessageState/src/stdafx.h +++ b/plugins/MessageState/src/stdafx.h @@ -28,4 +28,3 @@ struct CMPlugin : public PLUGIN<CMPlugin> int Load() override;
};
-extern IconItem Icons[];
diff --git a/plugins/MessageState/src/utils.cpp b/plugins/MessageState/src/utils.cpp index 9dd3110133..683e4f8a98 100644 --- a/plugins/MessageState/src/utils.cpp +++ b/plugins/MessageState/src/utils.cpp @@ -1,14 +1,23 @@ #include "stdafx.h"
+static mir_cs csContacts;
+OBJLIST<ContactData> g_arContacts(50, NumericKeySortT);
+
+// always returns an object, creates an empty one if missing
+ContactData* FindContact(MCONTACT hContact)
+{
+ mir_cslock lck(csContacts);
+
+ auto *p = g_arContacts.find((ContactData *)&hContact);
+ if (p == nullptr)
+ g_arContacts.insert(p = new ContactData(hContact));
+
+ return p;
+}
+
time_t GetLastSentMessageTime(MCONTACT hContact)
{
- for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent)) {
- DBEVENTINFO dbei = {};
- db_event_get(hDbEvent, &dbei);
- if (dbei.flags & DBEF_SENT)
- return dbei.timestamp;
- }
- return -1;
+ return FindContact(hContact)->dwLastSentTime;
}
bool HasUnread(MCONTACT hContact)
@@ -16,8 +25,9 @@ bool HasUnread(MCONTACT hContact) if (!CheckProtoSupport(Proto_GetBaseAccountName(hContact)))
return false;
- if (GetLastSentMessageTime(hContact) <= g_plugin.getDword(hContact, DBKEY_MESSAGE_READ_TIME, 0))
+ auto *p = FindContact(hContact);
+ if (p->dwLastSentTime <= p->dwLastReadTime)
return false;
- return g_plugin.getDword(hContact, DBKEY_MESSAGE_READ_TIME, 0) != 0;
+ return p->dwLastReadTime != 0;
}
diff --git a/plugins/MessageState/src/version.h b/plugins/MessageState/src/version.h index fced149a92..489f6ab568 100644 --- a/plugins/MessageState/src/version.h +++ b/plugins/MessageState/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0
-#define __MINOR_VERSION 0
-#define __RELEASE_NUM 1
-#define __BUILD_NUM 0
+#define __MINOR_VERSION 1
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 1
#include <stdver.h>
|