diff options
author | George Hazan <ghazan@miranda.im> | 2018-01-10 22:47:42 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2018-01-10 22:47:42 +0300 |
commit | 4e69c635f238cc951265e036ef74cef75b9a65c8 (patch) | |
tree | 4a8af2c5d841a0551b0c034339fc44ad202eca28 | |
parent | 8cad7d3baec2de5e117f115f89482b47ad124a18 (diff) |
Facebook: added custom reactions' icons to popups
-rw-r--r-- | protocols/FacebookRM/src/entities.h | 21 | ||||
-rw-r--r-- | protocols/FacebookRM/src/events.cpp | 17 | ||||
-rw-r--r-- | protocols/FacebookRM/src/json.cpp | 87 | ||||
-rw-r--r-- | protocols/FacebookRM/src/proto.cpp | 4 | ||||
-rw-r--r-- | protocols/FacebookRM/src/proto.h | 5 | ||||
-rw-r--r-- | protocols/FacebookRM/src/version.h | 4 |
6 files changed, 103 insertions, 35 deletions
diff --git a/protocols/FacebookRM/src/entities.h b/protocols/FacebookRM/src/entities.h index e1f9b69faa..57fe178249 100644 --- a/protocols/FacebookRM/src/entities.h +++ b/protocols/FacebookRM/src/entities.h @@ -129,23 +129,10 @@ struct facebook_notification std::string text; std::string link; std::string id; - const char *icon; - time_t time; - bool seen; - HWND hWndPopup; - - facebook_notification() - { - this->time = 0; - this->seen = false; - this->hWndPopup = nullptr; - this->icon = nullptr; - } - - void setIcon(const std::string& /*iconUrl*/) - { - icon = nullptr; - } + const char *icon = nullptr; + time_t time = 0; + bool seen = false; + HWND hWndPopup = nullptr; }; struct facebook_newsfeed diff --git a/protocols/FacebookRM/src/events.cpp b/protocols/FacebookRM/src/events.cpp index c6fae5dfee..f0f2d6abbb 100644 --- a/protocols/FacebookRM/src/events.cpp +++ b/protocols/FacebookRM/src/events.cpp @@ -28,7 +28,11 @@ HWND FacebookProto::NotifyEvent(wchar_t* title, wchar_t* text, MCONTACT contact, return nullptr; char name[256]; - + if (icon != nullptr) { + strncpy_s(name, icon, _TRUNCATE); + Skin_PlaySound("Notification"); + } + else switch (type) { case EVENT_CLIENT: mir_snprintf(name, "%s_%s", m_szModuleName, "Client"); @@ -65,22 +69,11 @@ HWND FacebookProto::NotifyEvent(wchar_t* title, wchar_t* text, MCONTACT contact, if (!getByte(FACEBOOK_KEY_SYSTRAY_NOTIFY, DEFAULT_SYSTRAY_NOTIFY)) { if (ServiceExists(MS_POPUP_ADDPOPUPCLASS)) { - - // TODO: if popup with particular ID is already showed, just update his content - // ... but f***ed up Popup Classes won't allow it now - they need to return hPopupWindow somehow - /* if (popup exists) { - if (PUChangeTextT(hWndPopup, info) > 0) // success - return; - }*/ - POPUPDATACLASS pd = { sizeof(pd) }; pd.pwszTitle = title; pd.pwszText = text; pd.pszClassName = name; pd.hContact = contact; - if (icon != nullptr) { - // pd.hIcon = IcoLib_GetIconByHandle(GetIconHandle(icon)); // FIXME: Uncomment when implemented in Popup+ and YAPP correctly - } if (url != nullptr || notification_id != nullptr) { popup_data *data = new popup_data(this); diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp index ee743ec2f4..af232b9bd6 100644 --- a/protocols/FacebookRM/src/json.cpp +++ b/protocols/FacebookRM/src/json.cpp @@ -22,6 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "stdafx.h" +LRESULT CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + void parseUser(const JSONNode &it, facebook_user *fbu) { fbu->user_id = it.name(); @@ -236,7 +238,7 @@ int FacebookProto::ParseNotifications(std::string *data, std::map< std::string, notification->link = url_.as_string(); notification->text = utils::text::html_entities_decode(utils::text::slashu_to_utf8(text_.as_string())); notification->time = utils::time::from_string(time_.as_string()); - notification->setIcon(icon_.as_string()); + notification->icon = ParseIcon(icon_.as_string()); // Write notification to chatroom UpdateNotificationsChatRoom(notification); @@ -431,6 +433,81 @@ bool FacebookProto::ProcessSpecialMessage(std::vector<facebook_message>* message return true; } +const char* FacebookProto::ParseIcon(const std::string &url) +{ + if (url.empty()) + return nullptr; + + auto itr = reactions.find(url); + if (itr == reactions.end()) { + UCHAR hash[MIR_SHA256_HASH_SIZE]; + mir_sha256_hash(url.c_str(), url.length(), hash); + + wchar_t wszHash[MIR_SHA256_HASH_SIZE * 2 + 10]; + bin2hexW(hash, sizeof(hash), wszHash); + + wchar_t wszFileName[MAX_PATH]; + mir_snwprintf(wszFileName, L"%s\\%s", VARSW(L"%miranda_avatarcache%"), m_tszUserName); + if (_waccess(wszFileName, 0)) + CreateDirectoryTreeW(wszFileName); + + wcscat_s(wszFileName, L"\\"); + wcscat_s(wszFileName, wszHash); + wcscat_s(wszFileName, L".ico"); + if (_waccess(wszFileName, 0)) { + NETLIBHTTPREQUEST req = { sizeof(req) }; + req.requestType = REQUEST_GET; + req.szUrl = (char*)url.c_str(); + req.flags = NLHRF_NODUMPHEADERS; + + NETLIBHTTPREQUEST *reply = Netlib_HttpTransaction(facy.handle_, &req); + if (reply != nullptr && reply->resultCode == HTTP_CODE_OK) { + IMGSRVC_MEMIO memio = { 0 }; + memio.iLen = reply->dataLength; + memio.pBuf = reply->pData; + memio.fif = FIF_UNKNOWN; /* detect */ + + HBITMAP hBmp = (HBITMAP)CallService(MS_IMG_LOADFROMMEM, (WPARAM)&memio); + if (hBmp != nullptr) { + IMGSRVC_INFO info = { sizeof(info) }; + info.wszName = wszFileName; + info.fif = FIF_ICO; + info.dwMask = IMGI_HBITMAP; + info.hbm = hBmp; + CallService(MS_IMG_SAVE, (WPARAM)&info, IMGL_WCHAR); + } + } + } + + HICON hIcon; + if (ExtractIconEx(wszFileName, 0, nullptr, &hIcon, 1) == 1) { + int idx = (int)reactions.size() + 1; + wchar_t desc[256]; + char name[256]; + mir_snwprintf(desc, L"%s/%s%d", m_tszUserName, TranslateT("Reaction"), idx); + mir_snprintf(name, "%s_%s%d", m_szModuleName, "Reaction", idx); + + POPUPCLASS ppc = { sizeof(ppc) }; + ppc.flags = PCF_TCHAR; + ppc.PluginWindowProc = PopupDlgProc; + ppc.lParam = APF_RETURN_HWND; + ppc.pwszDescription = desc; + ppc.pszName = name; + ppc.hIcon = hIcon; + ppc.colorBack = RGB(59, 89, 152); // Facebook's blue + ppc.colorText = RGB(255, 255, 255); // white + ppc.iSeconds = 0; + popupClasses.push_back(Popup_RegisterClass(&ppc)); + + mir_cslock lck(csReactions); + reactions.insert(std::make_pair(url, name)); + } + + itr = reactions.find(url); + } + + return (itr == reactions.end()) ? nullptr : itr->second.c_str(); +} int FacebookProto::ParseMessages(std::string *pData, std::vector<facebook_message>* messages, std::map< std::string, facebook_notification* >* notifications) { @@ -684,7 +761,7 @@ int FacebookProto::ParseMessages(std::string *pData, std::vector<facebook_messag notification->link = url.as_string(); notification->id = alert_id.as_string(); notification->time = timestamp; - notification->setIcon(icon_.as_string()); + notification->icon = ParseIcon(icon_.as_string()); // Fix notification ID std::string::size_type pos = notification->id.find(":"); @@ -738,6 +815,12 @@ int FacebookProto::ParseMessages(std::string *pData, std::vector<facebook_messag notification->id = alert_id; notification->time = utils::time::from_string(data["time"].as_string()); + const JSONNode &app_icon_ = data["app_icon"]["__html"]; + if (app_icon_) { + std::string url = app_icon_.as_string(); + notification->icon = ParseIcon(utils::text::source_get_value(&url, 3, "img class=\"img\"", "src=\"", "\"")); + } + // Write notification to chatroom UpdateNotificationsChatRoom(notification); diff --git a/protocols/FacebookRM/src/proto.cpp b/protocols/FacebookRM/src/proto.cpp index d64100165b..be0f917120 100644 --- a/protocols/FacebookRM/src/proto.cpp +++ b/protocols/FacebookRM/src/proto.cpp @@ -108,8 +108,8 @@ FacebookProto::FacebookProto(const char* proto_name, const wchar_t* username) : FacebookProto::~FacebookProto() { // Uninit popup classes - for (std::vector<HANDLE>::size_type i = 0; i < popupClasses.size(); i++) - Popup_UnregisterClass(popupClasses[i]); + for (auto &it : popupClasses) + Popup_UnregisterClass(it); popupClasses.clear(); Netlib_CloseHandle(m_hNetlibUser); diff --git a/protocols/FacebookRM/src/proto.h b/protocols/FacebookRM/src/proto.h index 7a004640e8..d5e3617546 100644 --- a/protocols/FacebookRM/src/proto.h +++ b/protocols/FacebookRM/src/proto.h @@ -45,6 +45,8 @@ class FacebookProto : public PROTO<FacebookProto> int ParseUnreadThreads(std::string*, std::vector< std::string >*); int ParseUserInfo(std::string* data, facebook_user* fbu); + const char* ParseIcon(const std::string &url); + public: FacebookProto(const char *proto_name, const wchar_t *username); ~FacebookProto(); @@ -276,6 +278,9 @@ public: std::string last_status_msg_; std::vector<MCONTACT> avatar_queue; + mir_cs csReactions; + std::map<std::string, std::string> reactions; + // Information providing HWND NotifyEvent(wchar_t* title, wchar_t* text, MCONTACT contact, EventType type, std::string *url = nullptr, std::string *notification_id = nullptr, const char *icon = nullptr); void ShowNotifications(); diff --git a/protocols/FacebookRM/src/version.h b/protocols/FacebookRM/src/version.h index 070b2bc311..130684e559 100644 --- a/protocols/FacebookRM/src/version.h +++ b/protocols/FacebookRM/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 4 -#define __RELEASE_NUM 0 -#define __BUILD_NUM 3 +#define __RELEASE_NUM 1 +#define __BUILD_NUM 1 #include <stdver.h> |