From c1849a9d50be0951bc4b2a5c0f14dbde5a8340e0 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 30 Nov 2023 15:03:35 +0300 Subject: =?UTF-8?q?fixes=20#3985=20(Telegram:=20=D0=B8=D0=B7=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D1=82=D0=B0=D1=82=D1=83?= =?UTF-8?q?=D1=81=D0=B0=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B0?= =?UTF-8?q?=D0=B5=D1=82=D1=81=D1=8F=20=D0=BB=D0=B8=D1=88=D1=8C=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=81=D0=BB=D0=B5=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D1=83=D1=81=D0=BA=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/m_chat.h | 3 + protocols/Telegram/src/groupchat.cpp | 44 ++++-- protocols/Telegram/src/server.cpp | 5 +- src/mir_app/src/chat.h | 2 +- src/mir_app/src/chat_manager.cpp | 292 +++++++++++++++++++---------------- src/mir_app/src/chat_svc.cpp | 5 + src/mir_app/src/chat_tools.cpp | 1 + 7 files changed, 200 insertions(+), 152 deletions(-) diff --git a/include/m_chat.h b/include/m_chat.h index 4a05f7ea80..e747388245 100644 --- a/include/m_chat.h +++ b/include/m_chat.h @@ -338,6 +338,9 @@ MIR_APP_DLL(struct SESSION_INFO*) Chat_NewSession( // dwItemData - ON/OFF #define GC_EVENT_TYPING 0x1001 +// same as GC_EVENT_ADDSTATUS but wipes all another statuses before +#define GC_EVENT_SETSTATUS 0x1002 + // GC_EVENT_SETCONTACTSTATUS - sets status icon for contact // pszUID - Unique identifier of the one who receives a new status // dwItemData - (DWORD)ID_STATUS_* or zero to remove status icon diff --git a/protocols/Telegram/src/groupchat.cpp b/protocols/Telegram/src/groupchat.cpp index e0eec733c5..618f415922 100644 --- a/protocols/Telegram/src/groupchat.cpp +++ b/protocols/Telegram/src/groupchat.cpp @@ -17,6 +17,21 @@ along with this program. If not, see . #include "stdafx.h" +static const wchar_t* getRoleById(uint32_t ID) +{ + switch (ID) { + case TD::chatMemberStatusCreator::ID: + return TranslateT("Creator"); + + case TD::chatMemberStatusAdministrator::ID: + return TranslateT("Admin"); + + case TD::chatMemberStatusMember::ID: + default: + return TranslateT("Participant"); + } +} + void CTelegramProto::InitGroupChat(TG_USER *pUser, const TD::chat *pChat) { if (pUser->m_si) @@ -102,21 +117,6 @@ void CTelegramProto::GcAddMembers(TG_USER *pChat, const TD::arraystatus_->get_id()) { - case TD::chatMemberStatusCreator::ID: - pwszRole = TranslateT("Creator"); - break; - case TD::chatMemberStatusAdministrator::ID: - pwszRole = TranslateT("Admin"); - break; - case TD::chatMemberStatusMember::ID: - default: - pwszRole = TranslateT("Participant"); - break; - } - if (pMember->member_id_->get_id() != TD::messageSenderUser::ID) continue; @@ -130,7 +130,7 @@ void CTelegramProto::GcAddMembers(TG_USER *pChat, const TD::arraym_si, GC_EVENT_JOIN }; gce.pszUID.w = wszUserId; - gce.pszStatus.w = pwszRole; + gce.pszStatus.w = getRoleById(pMember->status_->get_id()); if (bSilent) gce.dwFlags = GCEF_SILENT; @@ -416,5 +416,15 @@ void CTelegramProto::ProcessSuperGroup(TD::updateSupergroup *pObj) pUser->wszNick = getName(pGroup->group->usernames_.get()); pUser->wszLastName.Format(TranslateT("%d member(s)"), pGroup->group->member_count_); } - else AddUser(tmp.id, true); + else { + auto *pChat = AddUser(tmp.id, true); + if (auto *si = pChat->m_si) { + CMStringW wszUserId(FORMAT, L"%lld", m_iOwnId); + + GCEVENT gce = { si, GC_EVENT_SETSTATUS }; + gce.pszUID.w = wszUserId; + gce.pszStatus.w = getRoleById(iStatusId); + Chat_Event(&gce); + } + } } diff --git a/protocols/Telegram/src/server.cpp b/protocols/Telegram/src/server.cpp index acf31c7e96..d9dde02216 100644 --- a/protocols/Telegram/src/server.cpp +++ b/protocols/Telegram/src/server.cpp @@ -916,9 +916,10 @@ void CTelegramProto::ProcessUser(TD::updateUser *pObj) auto storedId = getMStringA(pu->hContact, DBKEY_AVATAR_HASH); if (remoteId != storedId.c_str()) { if (!remoteId.empty()) { - if (pu) + if (pu) { pu->szAvatarHash = remoteId.c_str(); - setString(pu->hContact, DBKEY_AVATAR_HASH, remoteId.c_str()); + setString(pu->hContact, DBKEY_AVATAR_HASH, remoteId.c_str()); + } SendQuery(new TD::downloadFile(pSmall->id_, 5, 0, 0, false)); } else delSetting(pu->hContact, DBKEY_AVATAR_HASH); diff --git a/src/mir_app/src/chat.h b/src/mir_app/src/chat.h index 6248c15e8e..430c694e8c 100644 --- a/src/mir_app/src/chat.h +++ b/src/mir_app/src/chat.h @@ -72,8 +72,8 @@ MODULEINFO* MM_FindModule(const char *pszModule); LOGINFO* SM_AddEvent(SESSION_INFO *si, GCEVENT *gce, bool bIsHighlighted); BOOL SM_ChangeNick(SESSION_INFO *si, GCEVENT *gce); void SM_FreeSession(SESSION_INFO *si); -char* SM_GetUsers(SESSION_INFO *si); BOOL SM_GiveStatus(SESSION_INFO *si, const wchar_t *pszUID, const wchar_t *pszStatus); +BOOL SM_AssignStatus(SESSION_INFO *si, const wchar_t *pszUID, const wchar_t *pszStatus); void SM_RemoveAll(void); BOOL SM_RemoveUser(SESSION_INFO *si, const wchar_t *pszUID); BOOL SM_SetContactStatus(SESSION_INFO *si, const wchar_t *pszUID, uint16_t wStatus); diff --git a/src/mir_app/src/chat_manager.cpp b/src/mir_app/src/chat_manager.cpp index 284d51c559..613bbd3f48 100644 --- a/src/mir_app/src/chat_manager.cpp +++ b/src/mir_app/src/chat_manager.cpp @@ -153,6 +153,153 @@ MIR_APP_DLL(SESSION_INFO*) Chat_Find(const wchar_t *pszID, const char *pszModule return g_arSessions.find(tmp); } +///////////////////////////////////////////////////////////////////////////////////////// +// Chat user manager + +USERINFO* UM_AddUser(SESSION_INFO *si, const wchar_t *pszUID, const wchar_t *pszNick, uint16_t wStatus) +{ + if (!si || !pszUID || !pszNick) + return nullptr; + + mir_cslock lck(si->csLock); + auto *pUser = UM_FindUser(si, pszUID); + if (pUser == nullptr) { + pUser = new USERINFO(); + replaceStrW(pUser->pszUID, pszUID); + si->getUserList().insert(pUser); + } + + replaceStrW(pUser->pszNick, pszNick); + pUser->Status = wStatus; + return pUser; +} + +static int UM_CompareItem(const USERINFO *u1, const USERINFO *u2) +{ + uint16_t dw1 = u1->Status; + uint16_t dw2 = u2->Status; + + for (int i = 0; i < 8; i++) { + if ((dw1 & 1) && !(dw2 & 1)) + return -1; + if ((dw2 & 1) && !(dw1 & 1)) + return 1; + if ((dw1 & 1) && (dw2 & 1)) + break; + + dw1 = dw1 >> 1; + dw2 = dw2 >> 1; + } + return mir_wstrcmpi(u1->pszNick, u2->pszNick); +} + +static USERINFO* UM_GiveStatus(SESSION_INFO *si, const wchar_t *pszUID, uint16_t status) +{ + USERINFO *ui = UM_FindUser(si, pszUID); + if (ui == nullptr) + return nullptr; + + ui->Status |= status; + return ui; +} + +static USERINFO* UM_SetStatus(SESSION_INFO *si, const wchar_t *pszUID, uint16_t status) +{ + USERINFO *ui = UM_FindUser(si, pszUID); + if (ui == nullptr) + return nullptr; + + if (ui->Status == status) + return nullptr; + + ui->Status = status; + return ui; +} + +static USERINFO* UM_SetContactStatus(SESSION_INFO *si, const wchar_t *pszUID, uint16_t status) +{ + USERINFO *ui = UM_FindUser(si, pszUID); + if (ui == nullptr) + return nullptr; + + ui->ContactStatus = status; + return ui; +} + +BOOL UM_SetStatusEx(SESSION_INFO *si, const wchar_t *pszText, int flags) +{ + int bOnlyMe = (flags & GC_SSE_ONLYLISTED) != 0, bSetStatus = (flags & GC_SSE_ONLINE) != 0; + char cDelimiter = (flags & GC_SSE_TABDELIMITED) ? '\t' : ' '; + + if (bOnlyMe) { + USERINFO *ui = UM_FindUser(si, pszText); + if (ui == nullptr) + return FALSE; + + ui->iStatusEx = (bSetStatus) ? 1 : 0; + return TRUE; + } + + for (auto &ui : si->getUserList()) { + ui->iStatusEx = 0; + + if (pszText != nullptr) { + wchar_t *s = (wchar_t *)wcsstr(pszText, ui->pszUID); + if (s) { + ui->iStatusEx = 0; + if (s == pszText || s[-1] == cDelimiter) { + size_t len = mir_wstrlen(ui->pszUID); + if (s[len] == cDelimiter || s[len] == '\0') + ui->iStatusEx = bSetStatus ? 1 : 0; + } + } + } + } + return TRUE; +} + +static USERINFO *UM_TakeStatus(SESSION_INFO *si, const wchar_t *pszUID, uint16_t status) +{ + USERINFO *ui = UM_FindUser(si, pszUID); + if (ui == nullptr) + return nullptr; + + ui->Status &= ~status; + return ui; +} + +static wchar_t *UM_FindUserAutoComplete(SESSION_INFO *si, const wchar_t *pszOriginal, const wchar_t *pszCurrent) +{ + if (!si || !pszOriginal || !pszCurrent) + return nullptr; + + wchar_t *pszName = nullptr; + for (auto &ui : si->getUserList()) + if (ui->pszNick && mir_wstrstri(ui->pszNick, pszOriginal) == ui->pszNick) + if (mir_wstrcmpi(ui->pszNick, pszCurrent) > 0 && (!pszName || mir_wstrcmpi(ui->pszNick, pszName) < 0)) + pszName = ui->pszNick; + + return pszName; +} + +BOOL UM_RemoveAll(SESSION_INFO *si) +{ + if (!si) + return FALSE; + + if (!si->pParent) { + for (auto &ui : si->arUsers) { + mir_free(ui->pszUID); + mir_free(ui->pszNick); + } + si->arUsers.destroy(); + } + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Chat session manager + BOOL SM_SetOffline(const char *pszModule, SESSION_INFO *si) { if (si == nullptr) { @@ -254,7 +401,18 @@ BOOL SM_GiveStatus(SESSION_INFO *si, const wchar_t *pszUID, const wchar_t *pszSt if (si == nullptr) return FALSE; - USERINFO *ui = g_chatApi.UM_GiveStatus(si, pszUID, TM_StringToWord(si->pStatuses, pszStatus)); + USERINFO *ui = UM_GiveStatus(si, pszUID, TM_StringToWord(si->pStatuses, pszStatus)); + if (ui && si->pDlg) + si->pDlg->UpdateNickList(); + return TRUE; +} + +BOOL SM_AssignStatus(SESSION_INFO *si, const wchar_t *pszUID, const wchar_t *pszStatus) +{ + if (si == nullptr) + return FALSE; + + USERINFO *ui = UM_SetStatus(si, pszUID, TM_StringToWord(si->pStatuses, pszStatus)); if (ui && si->pDlg) si->pDlg->UpdateNickList(); return TRUE; @@ -265,7 +423,7 @@ BOOL SM_SetContactStatus(SESSION_INFO *si, const wchar_t *pszUID, uint16_t wStat if (si == nullptr) return FALSE; - USERINFO *ui = g_chatApi.UM_SetContactStatus(si, pszUID, wStatus); + USERINFO *ui = UM_SetContactStatus(si, pszUID, wStatus); if (ui && si->pDlg) si->pDlg->UpdateNickList(); return TRUE; @@ -570,136 +728,6 @@ void UM_SortKeys(SESSION_INFO *si) ///////////////////////////////////////////////////////////////////////////////////////// -USERINFO* UM_AddUser(SESSION_INFO *si, const wchar_t *pszUID, const wchar_t *pszNick, uint16_t wStatus) -{ - if (!si || !pszUID || !pszNick) - return nullptr; - - mir_cslock lck(si->csLock); - auto *pUser = UM_FindUser(si, pszUID); - if (pUser == nullptr) { - pUser = new USERINFO(); - replaceStrW(pUser->pszUID, pszUID); - si->getUserList().insert(pUser); - } - - replaceStrW(pUser->pszNick, pszNick); - pUser->Status = wStatus; - return pUser; -} - -static int UM_CompareItem(const USERINFO *u1, const USERINFO *u2) -{ - uint16_t dw1 = u1->Status; - uint16_t dw2 = u2->Status; - - for (int i = 0; i < 8; i++) { - if ((dw1 & 1) && !(dw2 & 1)) - return -1; - if ((dw2 & 1) && !(dw1 & 1)) - return 1; - if ((dw1 & 1) && (dw2 & 1)) - break; - - dw1 = dw1 >> 1; - dw2 = dw2 >> 1; - } - return mir_wstrcmpi(u1->pszNick, u2->pszNick); -} - -static USERINFO* UM_GiveStatus(SESSION_INFO *si, const wchar_t *pszUID, uint16_t status) -{ - USERINFO *ui = UM_FindUser(si, pszUID); - if (ui == nullptr) - return nullptr; - - ui->Status |= status; - return ui; -} - -static USERINFO* UM_SetContactStatus(SESSION_INFO *si, const wchar_t *pszUID, uint16_t status) -{ - USERINFO *ui = UM_FindUser(si, pszUID); - if (ui == nullptr) - return nullptr; - - ui->ContactStatus = status; - return ui; -} - -BOOL UM_SetStatusEx(SESSION_INFO *si, const wchar_t* pszText, int flags) -{ - int bOnlyMe = (flags & GC_SSE_ONLYLISTED) != 0, bSetStatus = (flags & GC_SSE_ONLINE) != 0; - char cDelimiter = (flags & GC_SSE_TABDELIMITED) ? '\t' : ' '; - - if (bOnlyMe) { - USERINFO *ui = UM_FindUser(si, pszText); - if (ui == nullptr) - return FALSE; - - ui->iStatusEx = (bSetStatus) ? 1 : 0; - return TRUE; - } - - for (auto &ui : si->getUserList()) { - ui->iStatusEx = 0; - - if (pszText != nullptr) { - wchar_t *s = (wchar_t *)wcsstr(pszText, ui->pszUID); - if (s) { - ui->iStatusEx = 0; - if (s == pszText || s[-1] == cDelimiter) { - size_t len = mir_wstrlen(ui->pszUID); - if (s[len] == cDelimiter || s[len] == '\0') - ui->iStatusEx = bSetStatus ? 1 : 0; - } - } - } - } - return TRUE; -} - -static USERINFO* UM_TakeStatus(SESSION_INFO *si, const wchar_t *pszUID, uint16_t status) -{ - USERINFO *ui = UM_FindUser(si, pszUID); - if (ui == nullptr) - return nullptr; - - ui->Status &= ~status; - return ui; -} - -static wchar_t* UM_FindUserAutoComplete(SESSION_INFO *si, const wchar_t* pszOriginal, const wchar_t* pszCurrent) -{ - if (!si || !pszOriginal || !pszCurrent) - return nullptr; - - wchar_t *pszName = nullptr; - for (auto &ui : si->getUserList()) - if (ui->pszNick && mir_wstrstri(ui->pszNick, pszOriginal) == ui->pszNick) - if (mir_wstrcmpi(ui->pszNick, pszCurrent) > 0 && (!pszName || mir_wstrcmpi(ui->pszNick, pszName) < 0)) - pszName = ui->pszNick; - - return pszName; -} - -BOOL UM_RemoveAll(SESSION_INFO *si) -{ - if (!si) - return FALSE; - - if (!si->pParent) { - for (auto &ui : si->arUsers) { - mir_free(ui->pszUID); - mir_free(ui->pszNick); - } - si->arUsers.destroy(); - } - return TRUE; -} - -///////////////////////////////////////////////////////////////////////////////////////// - static void CreateNick(const SESSION_INFO *, const LOGINFO *lin, CMStringW &wszNick) { if (lin->ptszNick) { diff --git a/src/mir_app/src/chat_svc.cpp b/src/mir_app/src/chat_svc.cpp index 006459273c..28bfcba762 100644 --- a/src/mir_app/src/chat_svc.cpp +++ b/src/mir_app/src/chat_svc.cpp @@ -494,6 +494,11 @@ static BOOL HandleChatEvent(GCEVENT &gce, int bManyFix) bIsHighlighted = g_chatApi.IsHighlighted(si, &gce); break; + case GC_EVENT_SETSTATUS: + SM_AssignStatus(si, gce.pszUID.w, gce.pszStatus.w); + bIsHighlighted = g_chatApi.IsHighlighted(si, &gce); + break; + case GC_EVENT_REMOVESTATUS: SM_TakeStatus(si, gce.pszUID.w, gce.pszStatus.w); bIsHighlighted = g_chatApi.IsHighlighted(si, &gce); diff --git a/src/mir_app/src/chat_tools.cpp b/src/mir_app/src/chat_tools.cpp index 4d532fa871..2692678a69 100644 --- a/src/mir_app/src/chat_tools.cpp +++ b/src/mir_app/src/chat_tools.cpp @@ -633,6 +633,7 @@ BOOL IsEventSupported(int eventType) case GC_EVENT_INFORMATION: case GC_EVENT_ACTION: case GC_EVENT_ADDSTATUS: + case GC_EVENT_SETSTATUS: case GC_EVENT_REMOVESTATUS: case GC_EVENT_SETCONTACTSTATUS: return TRUE; -- cgit v1.2.3