diff --git a/Telegram/PrepareWin.bat b/Telegram/PrepareWin.bat index 1b4532518..868329c42 100644 --- a/Telegram/PrepareWin.bat +++ b/Telegram/PrepareWin.bat @@ -1,11 +1,11 @@ @echo OFF set "AppVersionStrMajor=0.8" -set "AppVersion=8048" -set "AppVersionStrSmall=0.8.48" -set "AppVersionStr=0.8.48" -set "AppVersionStrFull=0.8.48.0" -set "DevChannel=0" +set "AppVersion=8049" +set "AppVersionStrSmall=0.8.49" +set "AppVersionStr=0.8.49" +set "AppVersionStrFull=0.8.49.0" +set "DevChannel=1" if %DevChannel% neq 0 goto preparedev diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings index b462bcd6d..b51067d5c 100644 --- a/Telegram/Resources/lang.strings +++ b/Telegram/Resources/lang.strings @@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_reconnecting_try_now" = "Try now"; "lng_status_service_notifications" = "service notifications"; +"lng_status_support" = "support"; "lng_status_bot" = "bot"; "lng_status_bot_reads_all" = "has access to messages"; "lng_status_bot_not_reads_all" = "has no access to messages"; @@ -185,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_desktop_notify" = "Desktop notifications"; "lng_settings_show_name" = "Show sender's name"; "lng_settings_show_preview" = "Show message preview"; +"lng_settings_use_windows" = "Use Windows notifications"; "lng_settings_sound_notify" = "Play sound"; "lng_notification_preview" = "You have a new message"; @@ -323,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_reset_one_sure" = "Do you want to terminate this session?"; "lng_settings_reset_button" = "Terminate"; "lng_settings_reset_done" = "Other sessions terminated"; +"lng_settings_ask_question" = "Ask a Question"; +"lng_settings_ask_sure" = "Please note that Telegram Support is done by volunteers. We try to respond as quickly as possible, but it may take a while.\n\nPlease take a look at the Telegram FAQ: it has important troubleshooting tips and answers to most questions."; +"lng_settings_faq_button" = "Go to FAQ"; +"lng_settings_ask_ok" = "Ask"; +"lng_settings_faq" = "Telegram FAQ"; "lng_settings_logout" = "Log Out"; "lng_sure_logout" = "Are you sure you want to log out?"; @@ -355,6 +362,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_profile_delete_conversation" = "Delete conversation"; "lng_profile_clear_and_exit" = "Delete and exit"; "lng_profile_search_messages" = "Search for messages"; +"lng_profile_block_user" = "Block user"; +"lng_profile_unblock_user" = "Unblock user"; +"lng_profile_block_bot" = "Stop and block bot"; +"lng_profile_unblock_bot" = "Unblock bot"; "lng_profile_send_message" = "Send Message"; "lng_profile_share_contact" = "Share Contact"; "lng_profile_invite_to_group" = "Add to Group"; @@ -475,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_message_with_from" = "[c]{from}:[/c] {message}"; "lng_from_you" = "You"; "lng_bot_description" = "What can this bot do?"; +"lng_unblock_button" = "Unblock"; "lng_bot_start" = "Start"; "lng_bot_choose_group" = "Choose Group"; diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index e2658c14c..bdc6e4276 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -972,6 +972,11 @@ btnSend: flatButton(btnDefFlat) { font: font(16px); overFont: font(16px); } +btnUnblock: flatButton(btnSend) { + color: #d15948; + overColor: #d15948; + downColor: #db6352; +} btnAttachDocument: iconedButton(btnDefIconed) { icon: sprite(218px, 68px, 24px, 24px); diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 75d8187c7..a0fe57772 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -199,6 +199,7 @@ void ApiWrap::gotUserFull(PeerData *peer, const MTPUserFull &result) { App::main()->gotNotifySetting(MTP_inputNotifyPeer(peer->input), d.vnotify_settings); peer->asUser()->setBotInfo(d.vbot_info); + peer->asUser()->blocked = d.vblocked.v ? UserIsBlocked : UserIsNotBlocked; _fullPeerRequests.remove(peer); App::clearPeerUpdated(peer); diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index ac3773b9e..1a31593ba 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -289,8 +289,10 @@ namespace App { } QString onlineText(UserData *user, int32 now, bool precise) { - if (isServiceUser(user->id)) { + if (isNotificationsUser(user->id)) { return lang(lng_status_service_notifications); + } else if (isServiceUser(user->id)) { + return lang(lng_status_support); } else if (user->botInfo) { return lang(lng_status_bot); } @@ -370,8 +372,8 @@ namespace App { PeerId peer(peerFromUser(d.vid.v)); data = App::user(peer); - data->input = MTP_inputPeerContact(d.vid); - data->inputUser = MTP_inputUserContact(d.vid); + data->input = MTP_inputPeerUser(d.vid, MTP_long(0)); + data->inputUser = MTP_inputUser(d.vid, MTP_long(0)); data->setName(lang(lng_deleted), QString(), QString(), QString()); data->setPhoto(MTP_userProfilePhotoEmpty()); data->access = UserNoAccess; @@ -389,12 +391,12 @@ namespace App { if (flags & MTPDuser_flag_self) { data->input = MTP_inputPeerSelf(); data->inputUser = MTP_inputUserSelf(); - } else if ((flags & (MTPDuser_flag_contact | MTPDuser_flag_mutual_contact)) || !d.has_access_hash()) { - data->input = MTP_inputPeerContact(d.vid); - data->inputUser = MTP_inputUserContact(d.vid); + } else if (!d.has_access_hash()) { + data->input = MTP_inputPeerUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access)); + data->inputUser = MTP_inputUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access)); } else { - data->input = MTP_inputPeerForeign(d.vid, d.vaccess_hash); - data->inputUser = MTP_inputUserForeign(d.vid, d.vaccess_hash); + data->input = MTP_inputPeerUser(d.vid, d.vaccess_hash); + data->inputUser = MTP_inputUser(d.vid, d.vaccess_hash); } if (flags & MTPDuser_flag_deleted) { data->setPhone(QString()); @@ -868,14 +870,8 @@ namespace App { if (user->contact > 0) { if (!wasContact) { App::main()->addNewContact(App::userFromPeer(user->id), false); - if (user->input.type() != mtpc_inputPeerSelf) user->input = MTP_inputPeerContact(userId); - if (user->inputUser.type() != mtpc_inputUserSelf) user->inputUser = MTP_inputUserContact(userId); } } else { - if (user->access && user->access != UserNoAccess) { - if (user->input.type() != mtpc_inputPeerSelf) user->input = MTP_inputPeerForeign(userId, MTP_long(user->access)); - if (user->inputUser.type() != mtpc_inputUserSelf) user->inputUser = MTP_inputUserForeign(userId, MTP_long(user->access)); - } if (user->contact < 0 && !user->phone.isEmpty() && App::userFromPeer(user->id) != MTP::authedId()) { user->contact = 0; } @@ -924,7 +920,7 @@ namespace App { return feedPhoto(photo.c_photo(), convert); } break; case mtpc_photoEmpty: { - return App::photoSet(photo.c_photoEmpty().vid.v, convert, 0, 0, 0, ImagePtr(), ImagePtr(), ImagePtr()); + return App::photoSet(photo.c_photoEmpty().vid.v, convert, 0, 0, ImagePtr(), ImagePtr(), ImagePtr()); } break; } return App::photo(0); @@ -968,7 +964,7 @@ namespace App { switch (photo.type()) { case mtpc_photo: { const MTPDphoto &ph(photo.c_photo()); - return App::photoSet(ph.vid.v, 0, ph.vaccess_hash.v, ph.vuser_id.v, ph.vdate.v, ImagePtr(*thumb, "JPG"), ImagePtr(*medium, "JPG"), ImagePtr(*full, "JPG")); + return App::photoSet(ph.vid.v, 0, ph.vaccess_hash.v, ph.vdate.v, ImagePtr(*thumb, "JPG"), ImagePtr(*medium, "JPG"), ImagePtr(*full, "JPG")); } break; case mtpc_photoEmpty: return App::photo(photo.c_photoEmpty().vid.v); } @@ -1023,13 +1019,13 @@ namespace App { } } if (thumb && medium && full) { - return App::photoSet(photo.vid.v, convert, photo.vaccess_hash.v, photo.vuser_id.v, photo.vdate.v, App::image(*thumb), App::image(*medium), App::image(*full)); + return App::photoSet(photo.vid.v, convert, photo.vaccess_hash.v, photo.vdate.v, App::image(*thumb), App::image(*medium), App::image(*full)); } - return App::photoSet(photo.vid.v, convert, 0, 0, 0, ImagePtr(), ImagePtr(), ImagePtr()); + return App::photoSet(photo.vid.v, convert, 0, 0, ImagePtr(), ImagePtr(), ImagePtr()); } VideoData *feedVideo(const MTPDvideo &video, VideoData *convert) { - return App::videoSet(video.vid.v, convert, video.vaccess_hash.v, video.vuser_id.v, video.vdate.v, video.vduration.v, video.vw.v, video.vh.v, App::image(video.vthumb), video.vdc_id.v, video.vsize.v); + return App::videoSet(video.vid.v, convert, video.vaccess_hash.v, video.vdate.v, video.vduration.v, video.vw.v, video.vh.v, App::image(video.vthumb), video.vdc_id.v, video.vsize.v); } AudioData *feedAudio(const MTPaudio &audio, AudioData *convert) { @@ -1038,14 +1034,14 @@ namespace App { return feedAudio(audio.c_audio(), convert); } break; case mtpc_audioEmpty: { - return App::audioSet(audio.c_audioEmpty().vid.v, convert, 0, 0, 0, QString(), 0, 0, 0); + return App::audioSet(audio.c_audioEmpty().vid.v, convert, 0, 0, QString(), 0, 0, 0); } break; } return App::audio(0); } AudioData *feedAudio(const MTPDaudio &audio, AudioData *convert) { - return App::audioSet(audio.vid.v, convert, audio.vaccess_hash.v, audio.vuser_id.v, audio.vdate.v, qs(audio.vmime_type), audio.vduration.v, audio.vdc_id.v, audio.vsize.v); + return App::audioSet(audio.vid.v, convert, audio.vaccess_hash.v, audio.vdate.v, qs(audio.vmime_type), audio.vduration.v, audio.vdc_id.v, audio.vsize.v); } DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb) { @@ -1172,7 +1168,7 @@ namespace App { return i.value(); } - PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 user, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) { + PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) { if (convert) { if (convert->id != photo) { PhotosData::iterator i = photosData.find(convert->id); @@ -1182,8 +1178,7 @@ namespace App { convert->id = photo; } convert->access = access; - if (!convert->user && !convert->date && (user || date)) { - convert->user = user; + if (!convert->date && date) { convert->date = date; convert->thumb = thumb; convert->medium = medium; @@ -1197,14 +1192,13 @@ namespace App { if (convert) { result = convert; } else { - result = new PhotoData(photo, access, user, date, thumb, medium, full); + result = new PhotoData(photo, access, date, thumb, medium, full); } photosData.insert(photo, result); } else { result = i.value(); - if (result != convert && !result->user && !result->date && (user || date)) { + if (result != convert && !result->date && date) { result->access = access; - result->user = user; result->date = date; result->thumb = thumb; result->medium = medium; @@ -1234,7 +1228,7 @@ namespace App { return i.value(); } - VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) { + VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) { if (convert) { if (convert->id != video) { VideosData::iterator i = videosData.find(convert->id); @@ -1245,8 +1239,7 @@ namespace App { convert->status = FileReady; } convert->access = access; - if (!convert->user && !convert->date && (user || date)) { - convert->user = user; + if (!convert->date && date) { convert->date = date; convert->duration = duration; convert->w = w; @@ -1262,14 +1255,13 @@ namespace App { if (convert) { result = convert; } else { - result = new VideoData(video, access, user, date, duration, w, h, thumb, dc, size); + result = new VideoData(video, access, date, duration, w, h, thumb, dc, size); } videosData.insert(video, result); } else { result = i.value(); - if (result != convert && !result->user && !result->date && (user || date)) { + if (result != convert && !result->date && date) { result->access = access; - result->user = user; result->date = date; result->duration = duration; result->w = w; @@ -1290,7 +1282,7 @@ namespace App { return i.value(); } - AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) { + AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) { if (convert) { if (convert->id != audio) { AudiosData::iterator i = audiosData.find(convert->id); @@ -1301,8 +1293,7 @@ namespace App { convert->status = FileReady; } convert->access = access; - if (!convert->user && !convert->date && (user || date)) { - convert->user = user; + if (!convert->date && date) { convert->date = date; convert->mime = mime; convert->duration = duration; @@ -1316,14 +1307,13 @@ namespace App { if (convert) { result = convert; } else { - result = new AudioData(audio, access, user, date, mime, duration, dc, size); + result = new AudioData(audio, access, date, mime, duration, dc, size); } audiosData.insert(audio, result); } else { result = i.value(); - if (result != convert && !result->user && !result->date && (user || date)) { + if (result != convert && !result->date && date) { result->access = access; - result->user = user; result->date = date; result->mime = mime; result->duration = duration; @@ -1547,7 +1537,7 @@ namespace App { photoSizes.push_back(MTP_photoSize(MTP_string("a"), uphoto.vphoto_small, MTP_int(160), MTP_int(160), MTP_int(0))); photoSizes.push_back(MTP_photoSize(MTP_string("c"), uphoto.vphoto_big, MTP_int(640), MTP_int(640), MTP_int(0))); - return MTP_photo(uphoto.vphoto_id, MTP_long(0), userId, date, MTP_geoPointEmpty(), MTP_vector(photoSizes)); + return MTP_photo(uphoto.vphoto_id, MTP_long(0), date, MTP_vector(photoSizes)); } return MTP_photoEmpty(MTP_long(0)); } diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 1033ef90d..a68c390c3 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -158,11 +158,11 @@ namespace App { ChatData *chat(int32 chat); QString peerName(const PeerData *peer, bool forDialogs = false); PhotoData *photo(const PhotoId &photo); - PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 user, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full); + PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full); VideoData *video(const VideoId &video); - VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size); + VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size); AudioData *audio(const AudioId &audio); - AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size); + AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size); DocumentData *document(const DocumentId &document); DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation); WebPageData *webPage(const WebPageId &webPage); diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index 83e1334c3..867e035fa 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -474,7 +474,7 @@ void Application::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId) PhotoId id = MTP::nonce(); - MTPPhoto photo(MTP_photo(MTP_long(id), MTP_long(0), MTP_int(MTP::authedId()), MTP_int(unixtime()), MTP_geoPointEmpty(), MTP_vector(photoSizes))); + MTPPhoto photo(MTP_photo(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_vector(photoSizes))); QString file, filename; int32 filesize = 0; @@ -658,8 +658,8 @@ void Application::checkMapVersion() { psRegisterCustomScheme(); if (Local::oldMapVersion()) { QString versionFeatures; - if (cDevVersion() && Local::oldMapVersion() < 8047) { - versionFeatures = QString::fromUtf8("\xe2\x80\x94 Search for messages in conversation\n\xe2\x80\x94 Clear messages history in groups\n\xe2\x80\x94 Contacts without messages are hidden from the conversations list");// .replace('@', qsl("@") + QChar(0x200D)); + if (cDevVersion() && Local::oldMapVersion() < 8049) { + versionFeatures = QString::fromUtf8("\xe2\x80\x94 Block users from user profile\n\xe2\x80\x94 Ask support team a question from Settings\n\xe2\x80\x94 Windows toast notifications support added");// .replace('@', qsl("@") + QChar(0x200D)); } else if (!cDevVersion() && Local::oldMapVersion() < 8048) { versionFeatures = lang(lng_new_version_text).trimmed(); } diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index 8231651ea..bd4ed0d01 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -56,19 +56,24 @@ void ConfirmBox::init(const QString &text) { _confirm.hide(); _cancel.hide(); - connect(&_close, SIGNAL(clicked()), this, SLOT(onClose())); + connect(&_close, SIGNAL(clicked()), this, SLOT(onCancel())); setMouseTracking(_text.hasLinks()); } else { _close.hide(); connect(&_confirm, SIGNAL(clicked()), this, SIGNAL(confirmed())); - connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + connect(&_cancel, SIGNAL(clicked()), this, SLOT(onCancel())); } prepare(); } +void ConfirmBox::onCancel() { + emit cancelPressed(); + onClose(); +} + void ConfirmBox::mouseMoveEvent(QMouseEvent *e) { _lastMousePos = e->globalPos(); updateHover(); diff --git a/Telegram/SourceFiles/boxes/confirmbox.h b/Telegram/SourceFiles/boxes/confirmbox.h index 2cbf4de9f..1a54c33ac 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.h +++ b/Telegram/SourceFiles/boxes/confirmbox.h @@ -35,10 +35,15 @@ public: void leaveEvent(QEvent *e); void updateLink(); +public slots: + + void onCancel(); + signals: void confirmed(); void cancelled(); + void cancelPressed(); protected: diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index fba2537d3..7caebfc95 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -17,9 +17,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -static const int32 AppVersion = 8048; -static const wchar_t *AppVersionStr = L"0.8.48"; -static const bool DevVersion = false; +static const int32 AppVersion = 8049; +static const wchar_t *AppVersionStr = L"0.8.49"; +static const bool DevVersion = true; static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)"; static const wchar_t *AppName = L"Telegram Desktop"; @@ -144,10 +144,14 @@ enum { ChoosePeerByDragTimeout = 1000, // 1 second mouse not moved to choose dialog when dragging a file }; -inline bool isServiceUser(uint64 id) { +inline bool isNotificationsUser(uint64 id) { return (id == 333000) || (id == ServiceUserId); } +inline bool isServiceUser(uint64 id) { + return !(id % 1000);// (id == 333000) || (id == ServiceUserId); +} + #ifdef Q_OS_WIN inline const GUID &cGUID() { static const GUID gGuid = { 0x87a94ab0, 0xe370, 0x4cde, { 0x98, 0xd3, 0xac, 0xc1, 0x10, 0xc5, 0x96, 0x7d } }; @@ -321,6 +325,7 @@ enum { MemoryForImageCache = 64 * 1024 * 1024, // after 64mb of unpacked images we try to clear some memory NotifyWindowsCount = 3, // 3 desktop notifies at the same time NotifySettingSaveTimeout = 1000, // wait 1 second before saving notify setting to server + NotifyDeletePhotoAfter = 60000, // delete notify photo after 1 minute UpdateChunk = 100 * 1024, // 100kb parts when downloading the update IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle diff --git a/Telegram/SourceFiles/gui/images.h b/Telegram/SourceFiles/gui/images.h index 8ebec1dc2..2d1e4a139 100644 --- a/Telegram/SourceFiles/gui/images.h +++ b/Telegram/SourceFiles/gui/images.h @@ -154,6 +154,10 @@ inline StorageKey storageKey(int32 dc, const uint64 &volume, int32 local) { inline StorageKey storageKey(const MTPDfileLocation &location) { return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v); } +inline StorageKey storageKey(const StorageImageLocation &location) { + return storageKey(location.dc, location.volume, location.local); +} + enum StorageFileType { StorageFileUnknown = 0xaa963b05, // mtpc_storage_fileUnknown StorageFileJpeg = 0x7efe0e, // mtpc_storage_fileJpeg diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 6e506cc1a..a26a190f0 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -75,7 +75,9 @@ HistoryList::HistoryList(HistoryWidget *historyWidget, ScrollArea *scroll, Histo _trippleClickTimer.setSingleShot(true); - if (botInfo && !botInfo->inited) App::api()->requestFullPeer(hist->peer); + if (botInfo && !botInfo->inited) { + App::api()->requestFullPeer(hist->peer); + } setMouseTracking(true); } @@ -2200,7 +2202,9 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) , _toHistoryEnd(this, st::historyToEnd) , _attachMention(this) , _send(this, lang(lng_send_button), st::btnSend) +, _unblock(this, lang(lng_unblock_button), st::btnUnblock) , _botStart(this, lang(lng_bot_start), st::btnSend) +, _unblockRequest(0) , _attachDocument(this, st::btnAttachDocument) , _attachPhoto(this, st::btnAttachPhoto) , _attachEmoji(this, st::btnAttachEmoji) @@ -2243,6 +2247,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) connect(&_toHistoryEnd, SIGNAL(clicked()), this, SLOT(onHistoryToEnd())); connect(&_replyForwardPreviewCancel, SIGNAL(clicked()), this, SLOT(onReplyForwardPreviewCancel())); connect(&_send, SIGNAL(clicked()), this, SLOT(onSend())); + connect(&_unblock, SIGNAL(clicked()), this, SLOT(onUnblock())); connect(&_botStart, SIGNAL(clicked()), this, SLOT(onBotStart())); connect(&_attachDocument, SIGNAL(clicked()), this, SLOT(onDocumentSelect())); connect(&_attachPhoto, SIGNAL(clicked()), this, SLOT(onPhotoSelect())); @@ -2305,6 +2310,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) _field.hide(); _field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width(), _send.height() - 2 * st::sendPadding); _send.hide(); + _unblock.hide(); _botStart.hide(); _attachDocument.hide(); @@ -2368,8 +2374,8 @@ void HistoryWidget::onTextChange() { } if (updateCmdStartShown()) { updateControlsVisibility(); -resizeEvent(0); -update(); + resizeEvent(0); + update(); } if (!_history || _synthedTextUpdate) return; @@ -2482,7 +2488,7 @@ void HistoryWidget::sendActionDone(const MTPBool &result, mtpRequestId req) { void HistoryWidget::activate() { if (_history) updateListSize(0, true); if (_list) { - if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) { + if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart() || isBlocked()) { _list->setFocus(); } else { _field.setFocus(); @@ -2776,6 +2782,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) { } _peer = peerId ? App::peer(peerId) : 0; + _unblockRequest = 0; _titlePeerText = QString(); _titlePeerTextWidth = 0; @@ -2890,6 +2897,7 @@ void HistoryWidget::updateControlsVisibility() { _scroll.hide(); _kbScroll.hide(); _send.hide(); + _unblock.hide(); _botStart.hide(); _attachMention.hide(); _field.hide(); @@ -2914,7 +2922,25 @@ void HistoryWidget::updateControlsVisibility() { } if ((_peer->chat && !_peer->asChat()->forbidden && !_peer->asChat()->left) || (!_peer->chat && _peer->asUser()->access != UserNoAccess)) { checkMentionDropdown(); - if (isBotStart()) { + if (isBlocked()) { + _botStart.hide(); + if (_unblock.isHidden()) { + _unblock.clearState(); + _unblock.show(); + _kbShown = false; + } + _send.hide(); + _field.hide(); + _attachEmoji.hide(); + _kbShow.hide(); + _kbHide.hide(); + _cmdStart.hide(); + _attachDocument.hide(); + _attachPhoto.hide(); + _kbScroll.hide(); + _replyForwardPreviewCancel.hide(); + } else if (isBotStart()) { + _unblock.hide(); if (_botStart.isHidden()) { _botStart.clearState(); _botStart.show(); @@ -2931,6 +2957,7 @@ void HistoryWidget::updateControlsVisibility() { _kbScroll.hide(); _replyForwardPreviewCancel.hide(); } else { + _unblock.hide(); _botStart.hide(); if (cHasAudioCapture() && _field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) { _send.hide(); @@ -3007,6 +3034,7 @@ void HistoryWidget::updateControlsVisibility() { } else { _attachMention.hide(); _send.hide(); + _unblock.hide(); _botStart.hide(); _attachDocument.hide(); _attachPhoto.hide(); @@ -3321,6 +3349,29 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) { if (!_keyboard.hasMarkup() && _keyboard.forceReply() && !_kbReplyTo) onKbToggle(); } +void HistoryWidget::onUnblock() { + if (_unblockRequest) return; + if (!_peer || _peer->chat || _peer->asUser()->blocked != UserIsBlocked) { + updateControlsVisibility(); + return; + } + + _unblockRequest = MTP::send(MTPcontacts_Unblock(_peer->asUser()->inputUser), rpcDone(&HistoryWidget::unblockDone, _peer), rpcFail(&HistoryWidget::unblockFail)); +} + +void HistoryWidget::unblockDone(PeerData *peer, const MTPBool &result) { + if (peer->chat) return; + _unblockRequest = 0; + peer->asUser()->blocked = UserIsNotBlocked; + emit App::main()->peerUpdated(peer); +} + +bool HistoryWidget::unblockFail(const RPCError &error) { + if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false; +// _unblockRequest = 0; + return false; +} + void HistoryWidget::onBotStart() { if (!_peer || _peer->chat || !_peer->asUser()->botInfo) { updateControlsVisibility(); @@ -3418,6 +3469,7 @@ void HistoryWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTo _field.hide(); _replyForwardPreviewCancel.hide(); _send.hide(); + _unblock.hide(); _botStart.hide(); a_coord = back ? anim::ivalue(-st::introSlideShift, 0) : anim::ivalue(st::introSlideShift, 0); a_alpha = anim::fvalue(0, 1); @@ -3470,7 +3522,7 @@ void HistoryWidget::animStop() { bool HistoryWidget::recordStep(float64 ms) { float64 dt = ms / st::btnSend.duration; bool res = true; - if (dt >= 1 || !_send.isHidden() || isBotStart()) { + if (dt >= 1 || !_send.isHidden() || isBotStart() || isBlocked()) { res = false; a_recordOver.finish(); a_recordDown.finish(); @@ -3787,10 +3839,14 @@ bool HistoryWidget::isBotStart() const { return !_peer->asUser()->botInfo->startToken.isEmpty() || (_history->isEmpty() && !_history->lastMsg); } +bool HistoryWidget::isBlocked() const { + return _peer && !_peer->chat && _peer->asUser()->blocked == UserIsBlocked; +} + bool HistoryWidget::updateCmdStartShown() { bool cmdStartShown = false; if (_history && _peer && ((_peer->chat && _peer->asChat()->botStatus > 0) || (!_peer->chat && _peer->asUser()->botInfo))) { - if (!isBotStart() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) { + if (!isBotStart() && !isBlocked() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) { if (_field.getLastText().isEmpty()) { cmdStartShown = true; } @@ -4069,6 +4125,7 @@ void HistoryWidget::onFieldResize() { _attachDocument.move(0, height() - kbh - _attachDocument.height()); _attachPhoto.move(_attachDocument.x(), _attachDocument.y()); _botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height()); + _unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height()); _send.move(width() - _send.width(), _attachDocument.y()); _attachEmoji.move(_send.x() - _attachEmoji.width(), height() - kbh - _attachEmoji.height()); _kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height()); @@ -4427,7 +4484,7 @@ void HistoryWidget::peerMessagesUpdated(PeerId peer) { if (_peer && _list && peer == _peer->id) { updateListSize(); updateBotKeyboard(); - if (!_scroll.isHidden() && _botStart.isHidden() == isBotStart()) { + if (!_scroll.isHidden() && !isBlocked() && _botStart.isHidden() == isBotStart()) { updateControlsVisibility(); resizeEvent(0); } @@ -4468,6 +4525,7 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) { _send.move(width() - _send.width(), _attachDocument.y()); _botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height()); + _unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height()); _attachEmoji.move(_send.x() - _attachEmoji.width(), height() - kbh - _attachEmoji.height()); _kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height()); _kbHide.move(_attachEmoji.x(), _attachEmoji.y()); @@ -4537,7 +4595,9 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown, } int32 newScrollHeight = height(); - if (isBotStart()) { + if (isBlocked()) { + newScrollHeight -= _unblock.height(); + } else if (isBotStart()) { newScrollHeight -= _botStart.height(); } else { if ((_peer->chat && !_peer->asChat()->forbidden && !_peer->asChat()->left) || (!_peer->chat && _peer->asUser()->access != UserNoAccess)) { @@ -4676,7 +4736,7 @@ void HistoryWidget::updateBotKeyboard() { bool hasMarkup = _keyboard.hasMarkup(), forceReply = _keyboard.forceReply() && !_replyTo; if (hasMarkup || forceReply) { if (_keyboard.singleUse() && _keyboard.hasMarkup() && _keyboard.forMsgId() == _history->lastKeyboardId && _history->lastKeyboardUsed) _kbWasHidden = true; - if (!isBotStart() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) { + if (!isBotStart() && !isBlocked() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) { if (!_showAnim.animating()) { if (hasMarkup) { _kbScroll.show(); @@ -5094,6 +5154,9 @@ void HistoryWidget::onFullPeerUpdated(PeerData *data) { updateControlsVisibility(); resizeEvent(0); update(); + } else if (!_scroll.isHidden() && _unblock.isHidden() == isBlocked()) { + updateControlsVisibility(); + resizeEvent(0); } if (newScrollTop != _scroll.scrollTop()) { if (_scroll.isVisible()) { @@ -5110,6 +5173,11 @@ void HistoryWidget::peerUpdated(PeerData *data) { if (!_showAnim.animating()) updateControlsVisibility(); if (data->chat && data->asChat()->count > 0 && data->asChat()->participants.isEmpty()) { App::api()->requestFullPeer(data); + } else if (!data->chat && data->asUser()->blocked == UserBlockUnknown) { + App::api()->requestFullPeer(data); + } else if (!_scroll.isHidden() && _unblock.isHidden() == isBlocked()) { + updateControlsVisibility(); + resizeEvent(0); } App::main()->updateOnlineDisplay(); } @@ -5225,7 +5293,7 @@ void HistoryWidget::updateTopBarSelection() { updateControlsVisibility(); updateListSize(); if (!App::wnd()->layerShown() && !App::passcoded()) { - if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) { + if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart() || isBlocked()) { _list->setFocus(); } else { _field.setFocus(); diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index e6535ccfe..0ce5c0c81 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -518,6 +518,7 @@ public slots: void onListScroll(); void onHistoryToEnd(); void onSend(bool ctrlShiftEnter = false, MsgId replyTo = -1); + void onUnblock(); void onBotStart(); void onPhotoSelect(); @@ -604,6 +605,9 @@ private: void addMessagesToFront(const QVector &messages); void addMessagesToBack(const QVector &messages); + void unblockDone(PeerData *peer, const MTPBool &result); + bool unblockFail(const RPCError &error); + void countHistoryShowFrom(); void updateToEndVisibility(); @@ -640,9 +644,11 @@ private: MentionsDropdown _attachMention; bool isBotStart() const; + bool isBlocked() const; bool updateCmdStartShown(); - FlatButton _send, _botStart; + FlatButton _send, _unblock, _botStart; + mtpRequestId _unblockRequest; IconedButton _attachDocument, _attachPhoto, _attachEmoji, _kbShow, _kbHide, _cmdStart; bool _cmdStartShown; MessageField _field; diff --git a/Telegram/SourceFiles/localimageloader.cpp b/Telegram/SourceFiles/localimageloader.cpp index 2e212aec6..4d7edf177 100644 --- a/Telegram/SourceFiles/localimageloader.cpp +++ b/Telegram/SourceFiles/localimageloader.cpp @@ -221,7 +221,7 @@ void LocalImageLoaderPrivate::prepareImages() { } if (!filesize) filesize = jpeg.size(); - photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_geoPointEmpty(), MTP_vector(photoSizes)); + photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_vector(photoSizes)); thumbId = id; } else if ((type == ToPrepareVideo || type == ToPrepareDocument) && !img.isNull() && !isSong) { @@ -254,7 +254,7 @@ void LocalImageLoaderPrivate::prepareImages() { if (type == ToPrepareDocument) { document = MTP_document(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(filesize), thumb, MTP_int(MTP::maindc()), MTP_vector(attributes)); } else if (type == ToPrepareAudio) { - audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc())); + audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc())); } { diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index 4f6103da4..0ca20aca2 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -19,6 +19,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "localstorage.h" #include "mainwidget.h" +#include "window.h" #include "lang.h" namespace { @@ -737,6 +738,15 @@ namespace { cSetDesktopNotify(v == 1); } break; + case dbiWindowsNotifications: { + qint32 v; + stream >> v; + if (!_checkStreamStatus(stream)) return false; + + cSetWindowsNotifications(v == 1); + cSetCustomNotifies((App::wnd() ? App::wnd()->psHasNativeNotifications() : true) && !cWindowsNotifications()); + } break; + case dbiWorkMode: { qint32 v; stream >> v; @@ -1269,7 +1279,7 @@ namespace { _writeMap(WriteMapFast); } - uint32 size = 12 * (sizeof(quint32) + sizeof(qint32)); + uint32 size = 13 * (sizeof(quint32) + sizeof(qint32)); size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath()); size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort)); size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64)); @@ -1285,6 +1295,7 @@ namespace { data.stream << quint32(dbiSoundNotify) << qint32(cSoundNotify()); data.stream << quint32(dbiDesktopNotify) << qint32(cDesktopNotify()); data.stream << quint32(dbiNotifyView) << qint32(cNotifyView()); + data.stream << quint32(dbiWindowsNotifications) << qint32(cWindowsNotifications()); data.stream << quint32(dbiAskDownloadPath) << qint32(cAskDownloadPath()); data.stream << quint32(dbiDownloadPath) << (cAskDownloadPath() ? QString() : cDownloadPath()); data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage()); @@ -2810,12 +2821,9 @@ namespace Local { if (App::userFromPeer(user->id) == MTP::authedId()) { user->input = MTP_inputPeerSelf(); user->inputUser = MTP_inputUserSelf(); - } else if (user->contact > 0 || !user->access) { - user->input = MTP_inputPeerContact(MTP_int(App::userFromPeer(user->id))); - user->inputUser = MTP_inputUserContact(MTP_int(App::userFromPeer(user->id))); } else { - user->input = MTP_inputPeerForeign(MTP_int(App::userFromPeer(user->id)), MTP_long(user->access)); - user->inputUser = MTP_inputUserForeign(MTP_int(App::userFromPeer(user->id)), MTP_long(user->access)); + user->input = MTP_inputPeerUser(MTP_int(App::userFromPeer(user->id)), MTP_long((user->access == UserNoAccess) ? 0 : user->access)); + user->inputUser = MTP_inputUser(MTP_int(App::userFromPeer(user->id)), MTP_long((user->access == UserNoAccess) ? 0 : user->access)); } user->photo = photoLoc.isNull() ? ImagePtr(userDefPhoto(user->colorIndex)) : ImagePtr(photoLoc); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 0013557e3..0b0760725 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -3040,8 +3040,7 @@ void MainWidget::gotNotifySetting(MTPInputNotifyPeer peer, const MTPPeerNotifySe switch (peer.c_inputNotifyPeer().vpeer.type()) { case mtpc_inputPeerEmpty: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(MTP_int(0))), settings); break; case mtpc_inputPeerSelf: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(MTP_int(MTP::authedId()))), settings); break; - case mtpc_inputPeerContact: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerContact().vuser_id)), settings); break; - case mtpc_inputPeerForeign: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerForeign().vuser_id)), settings); break; + case mtpc_inputPeerUser: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerUser().vuser_id)), settings); break; case mtpc_inputPeerChat: applyNotifySetting(MTP_notifyPeer(MTP_peerChat(peer.c_inputNotifyPeer().vpeer.c_inputPeerChat().vchat_id)), settings); break; } break; @@ -3650,6 +3649,10 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { case mtpc_updateUserBlocked: { const MTPDupdateUserBlocked &d(update.c_updateUserBlocked()); + if (UserData *user = App::userLoaded(d.vuser_id.v)) { + user->blocked = d.vblocked.v ? UserIsBlocked : UserIsNotBlocked; + App::markPeerUpdated(user); + } } break; case mtpc_updateNewAuthorization: { diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index f0739b97c..6baf5b562 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -775,18 +775,14 @@ void MediaView::displayPhoto(PhotoData *photo, HistoryItem *item) { _x = (width() - _w) / 2; _y = (height() - _h) / 2; _width = _w; - if (_photo->user == WebPageUserId && _msgid) { - if (HistoryItem *item = App::histItemById(_msgid)) { - if (dynamic_cast(item)) { - _from = static_cast(item)->fromForwarded(); - } else { - _from = item->from(); - } + if (_msgid && item) { + if (HistoryForwarded *fwd = item->toHistoryForwarded()) { + _from = fwd->fromForwarded(); } else { - _from = App::user(_photo->user); + _from = item->from(); } } else { - _from = App::user(_photo->user); + _from = _user; } updateControls(); _photo->full->load(); @@ -955,10 +951,10 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty } _x = (width() - _w) / 2; _y = (height() - _h) / 2; - if (HistoryForwarded *fwd = dynamic_cast(item)) { - _from = fwd->fromForwarded()->asUser(); + if (HistoryForwarded *fwd = item->toHistoryForwarded()) { + _from = fwd->fromForwarded(); } else { - _from = item->from()->asUser(); + _from = item->from(); } _full = 1; updateControls(); @@ -1850,7 +1846,7 @@ void MediaView::loadBack() { if (App::main()) App::main()->loadMediaBack(_history->peer, _overview); } else if (_user && _user->photosCount != 0) { int32 limit = (_index < MediaOverviewStartPerPage && _user->photos.size() > MediaOverviewStartPerPage) ? SearchPerPage : MediaOverviewStartPerPage; - _loadRequest = MTP::send(MTPphotos_GetUserPhotos(_user->inputUser, MTP_int(_user->photos.size()), MTP_int(0), MTP_int(limit)), rpcDone(&MediaView::userPhotosLoaded, _user)); + _loadRequest = MTP::send(MTPphotos_GetUserPhotos(_user->inputUser, MTP_int(_user->photos.size()), MTP_long(0), MTP_int(limit)), rpcDone(&MediaView::userPhotosLoaded, _user)); } } diff --git a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h index 950d5be3a..63b6c1fad 100644 --- a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h +++ b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h @@ -366,7 +366,7 @@ static const mtpTypeId mtpLayers[] = { mtpc_invokeWithLayer17, mtpc_invokeWithLayer18, }, mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]); -static const mtpPrime mtpCurrentLayer = 32; +static const mtpPrime mtpCurrentLayer = 33; template class MTPBoxed : public bareT { diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.cpp b/Telegram/SourceFiles/mtproto/mtpScheme.cpp index a79731ee7..457cd9470 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.cpp +++ b/Telegram/SourceFiles/mtproto/mtpScheme.cpp @@ -487,33 +487,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("{ inputPeerSelf }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - case mtpc_inputPeerContact: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ inputPeerContact"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - - case mtpc_inputPeerForeign: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ inputPeerForeign"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - case mtpc_inputPeerChat: if (stage) { to.add(",\n").addSpaces(lev); @@ -527,6 +500,20 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_inputPeerUser: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ inputPeerUser"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_inputUserEmpty: to.add("{ inputUserEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; @@ -535,24 +522,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("{ inputUserSelf }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - case mtpc_inputUserContact: + case mtpc_inputUser: if (stage) { to.add(",\n").addSpaces(lev); } else { - to.add("{ inputUserContact"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - - case mtpc_inputUserForeign: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ inputUserForeign"); + to.add("{ inputUser"); to.add("\n").addSpaces(lev); } switch (stage) { @@ -1662,10 +1636,8 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP switch (stage) { case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" geo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" sizes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" sizes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -1740,9 +1712,9 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP switch (stage) { case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 5: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 6: to.add(" thumb: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 7: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; @@ -2336,6 +2308,10 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("{ inputMessagesFilterAudioDocuments }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + case mtpc_inputMessagesFilterUrl: + to.add("{ inputMessagesFilterUrl }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); + break; + case mtpc_updateNewMessage: if (stage) { to.add(",\n").addSpaces(lev); @@ -3513,12 +3489,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP switch (stage) { case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 7: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 6: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -4389,6 +4364,23 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_help_appChangelogEmpty: + to.add("{ help_appChangelogEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); + break; + + case mtpc_help_appChangelog: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ help_appChangelog"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_req_pq: if (stage) { to.add(",\n").addSpaces(lev); @@ -5786,7 +5778,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP switch (stage) { case 0: to.add(" user_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 3: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } @@ -6201,6 +6193,22 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_help_getAppChangelog: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ help_getAppChangelog"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" device_model: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" system_version: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" app_version: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" lang_code: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_rpc_result: if (stage) { to.add(",\n").addSpaces(lev); diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.h b/Telegram/SourceFiles/mtproto/mtpScheme.h index 2cebf65f9..17d3f4a6f 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.h +++ b/Telegram/SourceFiles/mtproto/mtpScheme.h @@ -67,13 +67,9 @@ enum { mtpc_null = 0x56730bcc, mtpc_inputPeerEmpty = 0x7f3b18ea, mtpc_inputPeerSelf = 0x7da07ec9, - mtpc_inputPeerContact = 0x1023dbe8, - mtpc_inputPeerForeign = 0x9b447325, mtpc_inputPeerChat = 0x179be863, mtpc_inputUserEmpty = 0xb98886cf, mtpc_inputUserSelf = 0xf7c1b13f, - mtpc_inputUserContact = 0x86e94f65, - mtpc_inputUserForeign = 0x655e74ff, mtpc_inputPhoneContact = 0xf392b7f4, mtpc_inputFile = 0xf52ff27f, mtpc_inputMediaEmpty = 0x9664f57f, @@ -145,12 +141,12 @@ enum { mtpc_messageActionChatDeleteUser = 0xb2ae9b0c, mtpc_dialog = 0xc1dd804a, mtpc_photoEmpty = 0x2331b22d, - mtpc_photo = 0xc3838076, + mtpc_photo = 0xcded42fe, mtpc_photoSizeEmpty = 0xe17e23c, mtpc_photoSize = 0x77bfb61b, mtpc_photoCachedSize = 0xe9a734fa, mtpc_videoEmpty = 0xc10658a8, - mtpc_video = 0xee9f4a4d, + mtpc_video = 0xf72887d3, mtpc_geoPointEmpty = 0x1117dd5f, mtpc_geoPoint = 0x2049d70c, mtpc_auth_checkedPhone = 0x811ea28e, @@ -200,6 +196,7 @@ enum { mtpc_inputMessagesFilterDocument = 0x9eddf188, mtpc_inputMessagesFilterAudio = 0xcfc87522, mtpc_inputMessagesFilterAudioDocuments = 0x5afbf764, + mtpc_inputMessagesFilterUrl = 0x7ef0dd87, mtpc_updateNewMessage = 0x1f2b0afd, mtpc_updateMessageID = 0x4e90bfd6, mtpc_updateDeleteMessages = 0xa20db0e5, @@ -288,7 +285,7 @@ enum { mtpc_inputAudioFileLocation = 0x74dc404d, mtpc_inputDocumentFileLocation = 0x4e45abe9, mtpc_audioEmpty = 0x586988d8, - mtpc_audio = 0xc7ac6496, + mtpc_audio = 0xf9e35055, mtpc_documentEmpty = 0x36f8c871, mtpc_document = 0xf9a39f4f, mtpc_help_support = 0x17c6b5f6, @@ -388,6 +385,10 @@ enum { mtpc_replyKeyboardHide = 0xa03e5b85, mtpc_replyKeyboardForceReply = 0xf4108aa0, mtpc_replyKeyboardMarkup = 0x3502758c, + mtpc_inputPeerUser = 0x7b8e7de6, + mtpc_inputUser = 0xd8292816, + mtpc_help_appChangelogEmpty = 0xaf7e0394, + mtpc_help_appChangelog = 0x4668e6bd, mtpc_invokeAfterMsg = 0xcb9f372d, mtpc_invokeAfterMsgs = 0x3dc4b4f0, mtpc_auth_checkPhone = 0x6fe51dfb, @@ -453,7 +454,7 @@ enum { mtpc_help_getAppUpdate = 0xc812ac7e, mtpc_help_saveAppLog = 0x6f02f748, mtpc_help_getInviteText = 0xa4a95186, - mtpc_photos_getUserPhotos = 0xb7ee553c, + mtpc_photos_getUserPhotos = 0x91cd32a8, mtpc_messages_forwardMessage = 0x33963bf9, mtpc_messages_sendBroadcast = 0xbf73f4da, mtpc_geochats_getLocated = 0x7f192d8f, @@ -515,7 +516,8 @@ enum { mtpc_messages_getStickerSet = 0x2619a90e, mtpc_messages_installStickerSet = 0x7b30c3a6, mtpc_messages_uninstallStickerSet = 0xf96e55de, - mtpc_messages_startBot = 0x1b3e0ffc + mtpc_messages_startBot = 0x1b3e0ffc, + mtpc_help_getAppChangelog = 0x5bab7fb2 }; // Type forward declarations @@ -594,13 +596,11 @@ class MTPDerror; class MTPnull; class MTPinputPeer; -class MTPDinputPeerContact; -class MTPDinputPeerForeign; class MTPDinputPeerChat; +class MTPDinputPeerUser; class MTPinputUser; -class MTPDinputUserContact; -class MTPDinputUserForeign; +class MTPDinputUser; class MTPinputContact; class MTPDinputPhoneContact; @@ -1083,6 +1083,9 @@ class MTPDreplyKeyboardHide; class MTPDreplyKeyboardForceReply; class MTPDreplyKeyboardMarkup; +class MTPhelp_appChangelog; +class MTPDhelp_appChangelog; + // Boxed types definitions typedef MTPBoxed MTPResPQ; @@ -1234,6 +1237,7 @@ typedef MTPBoxed MTPBotInfo; typedef MTPBoxed MTPKeyboardButton; typedef MTPBoxed MTPKeyboardButtonRow; typedef MTPBoxed MTPReplyMarkup; +typedef MTPBoxed MTPhelp_AppChangelog; // Type classes definitions @@ -2070,30 +2074,6 @@ public: read(from, end, cons); } - MTPDinputPeerContact &_inputPeerContact() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_inputPeerContact) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerContact); - split(); - return *(MTPDinputPeerContact*)data; - } - const MTPDinputPeerContact &c_inputPeerContact() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_inputPeerContact) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerContact); - return *(const MTPDinputPeerContact*)data; - } - - MTPDinputPeerForeign &_inputPeerForeign() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_inputPeerForeign) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerForeign); - split(); - return *(MTPDinputPeerForeign*)data; - } - const MTPDinputPeerForeign &c_inputPeerForeign() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_inputPeerForeign) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerForeign); - return *(const MTPDinputPeerForeign*)data; - } - MTPDinputPeerChat &_inputPeerChat() { if (!data) throw mtpErrorUninitialized(); if (_type != mtpc_inputPeerChat) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerChat); @@ -2106,6 +2086,18 @@ public: return *(const MTPDinputPeerChat*)data; } + MTPDinputPeerUser &_inputPeerUser() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_inputPeerUser) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerUser); + split(); + return *(MTPDinputPeerUser*)data; + } + const MTPDinputPeerUser &c_inputPeerUser() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_inputPeerUser) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerUser); + return *(const MTPDinputPeerUser*)data; + } + uint32 innerLength() const; mtpTypeId type() const; void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); @@ -2115,15 +2107,13 @@ public: private: explicit MTPinputPeer(mtpTypeId type); - explicit MTPinputPeer(MTPDinputPeerContact *_data); - explicit MTPinputPeer(MTPDinputPeerForeign *_data); explicit MTPinputPeer(MTPDinputPeerChat *_data); + explicit MTPinputPeer(MTPDinputPeerUser *_data); friend MTPinputPeer MTP_inputPeerEmpty(); friend MTPinputPeer MTP_inputPeerSelf(); - friend MTPinputPeer MTP_inputPeerContact(MTPint _user_id); - friend MTPinputPeer MTP_inputPeerForeign(MTPint _user_id, const MTPlong &_access_hash); friend MTPinputPeer MTP_inputPeerChat(MTPint _chat_id); + friend MTPinputPeer MTP_inputPeerUser(MTPint _user_id, const MTPlong &_access_hash); mtpTypeId _type; }; @@ -2137,28 +2127,16 @@ public: read(from, end, cons); } - MTPDinputUserContact &_inputUserContact() { + MTPDinputUser &_inputUser() { if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_inputUserContact) throw mtpErrorWrongTypeId(_type, mtpc_inputUserContact); + if (_type != mtpc_inputUser) throw mtpErrorWrongTypeId(_type, mtpc_inputUser); split(); - return *(MTPDinputUserContact*)data; + return *(MTPDinputUser*)data; } - const MTPDinputUserContact &c_inputUserContact() const { + const MTPDinputUser &c_inputUser() const { if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_inputUserContact) throw mtpErrorWrongTypeId(_type, mtpc_inputUserContact); - return *(const MTPDinputUserContact*)data; - } - - MTPDinputUserForeign &_inputUserForeign() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_inputUserForeign) throw mtpErrorWrongTypeId(_type, mtpc_inputUserForeign); - split(); - return *(MTPDinputUserForeign*)data; - } - const MTPDinputUserForeign &c_inputUserForeign() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_inputUserForeign) throw mtpErrorWrongTypeId(_type, mtpc_inputUserForeign); - return *(const MTPDinputUserForeign*)data; + if (_type != mtpc_inputUser) throw mtpErrorWrongTypeId(_type, mtpc_inputUser); + return *(const MTPDinputUser*)data; } uint32 innerLength() const; @@ -2170,13 +2148,11 @@ public: private: explicit MTPinputUser(mtpTypeId type); - explicit MTPinputUser(MTPDinputUserContact *_data); - explicit MTPinputUser(MTPDinputUserForeign *_data); + explicit MTPinputUser(MTPDinputUser *_data); friend MTPinputUser MTP_inputUserEmpty(); friend MTPinputUser MTP_inputUserSelf(); - friend MTPinputUser MTP_inputUserContact(MTPint _user_id); - friend MTPinputUser MTP_inputUserForeign(MTPint _user_id, const MTPlong &_access_hash); + friend MTPinputUser MTP_inputUser(MTPint _user_id, const MTPlong &_access_hash); mtpTypeId _type; }; @@ -3709,7 +3685,7 @@ private: explicit MTPphoto(MTPDphoto *_data); friend MTPphoto MTP_photoEmpty(const MTPlong &_id); - friend MTPphoto MTP_photo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, const MTPGeoPoint &_geo, const MTPVector &_sizes); + friend MTPphoto MTP_photo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPVector &_sizes); mtpTypeId _type; }; @@ -3825,7 +3801,7 @@ private: explicit MTPvideo(MTPDvideo *_data); friend MTPvideo MTP_videoEmpty(const MTPlong &_id); - friend MTPvideo MTP_video(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h); + friend MTPvideo MTP_video(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h); mtpTypeId _type; }; @@ -4929,6 +4905,7 @@ private: friend MTPmessagesFilter MTP_inputMessagesFilterDocument(); friend MTPmessagesFilter MTP_inputMessagesFilterAudio(); friend MTPmessagesFilter MTP_inputMessagesFilterAudioDocuments(); + friend MTPmessagesFilter MTP_inputMessagesFilterUrl(); mtpTypeId _type; }; @@ -6539,7 +6516,7 @@ private: explicit MTPaudio(MTPDaudio *_data); friend MTPaudio MTP_audioEmpty(const MTPlong &_id); - friend MTPaudio MTP_audio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id); + friend MTPaudio MTP_audio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id); mtpTypeId _type; }; @@ -8050,6 +8027,44 @@ private: }; typedef MTPBoxed MTPReplyMarkup; +class MTPhelp_appChangelog : private mtpDataOwner { +public: + MTPhelp_appChangelog() : mtpDataOwner(0), _type(0) { + } + MTPhelp_appChangelog(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { + read(from, end, cons); + } + + MTPDhelp_appChangelog &_help_appChangelog() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_help_appChangelog) throw mtpErrorWrongTypeId(_type, mtpc_help_appChangelog); + split(); + return *(MTPDhelp_appChangelog*)data; + } + const MTPDhelp_appChangelog &c_help_appChangelog() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_help_appChangelog) throw mtpErrorWrongTypeId(_type, mtpc_help_appChangelog); + return *(const MTPDhelp_appChangelog*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPhelp_appChangelog(mtpTypeId type); + explicit MTPhelp_appChangelog(MTPDhelp_appChangelog *_data); + + friend MTPhelp_appChangelog MTP_help_appChangelogEmpty(); + friend MTPhelp_appChangelog MTP_help_appChangelog(const MTPstring &_text); + + mtpTypeId _type; +}; +typedef MTPBoxed MTPhelp_AppChangelog; + // Type constructors with data class MTPDresPQ : public mtpDataImpl { @@ -8383,27 +8398,6 @@ public: MTPstring vtext; }; -class MTPDinputPeerContact : public mtpDataImpl { -public: - MTPDinputPeerContact() { - } - MTPDinputPeerContact(MTPint _user_id) : vuser_id(_user_id) { - } - - MTPint vuser_id; -}; - -class MTPDinputPeerForeign : public mtpDataImpl { -public: - MTPDinputPeerForeign() { - } - MTPDinputPeerForeign(MTPint _user_id, const MTPlong &_access_hash) : vuser_id(_user_id), vaccess_hash(_access_hash) { - } - - MTPint vuser_id; - MTPlong vaccess_hash; -}; - class MTPDinputPeerChat : public mtpDataImpl { public: MTPDinputPeerChat() { @@ -8414,21 +8408,22 @@ public: MTPint vchat_id; }; -class MTPDinputUserContact : public mtpDataImpl { +class MTPDinputPeerUser : public mtpDataImpl { public: - MTPDinputUserContact() { + MTPDinputPeerUser() { } - MTPDinputUserContact(MTPint _user_id) : vuser_id(_user_id) { + MTPDinputPeerUser(MTPint _user_id, const MTPlong &_access_hash) : vuser_id(_user_id), vaccess_hash(_access_hash) { } MTPint vuser_id; + MTPlong vaccess_hash; }; -class MTPDinputUserForeign : public mtpDataImpl { +class MTPDinputUser : public mtpDataImpl { public: - MTPDinputUserForeign() { + MTPDinputUser() { } - MTPDinputUserForeign(MTPint _user_id, const MTPlong &_access_hash) : vuser_id(_user_id), vaccess_hash(_access_hash) { + MTPDinputUser(MTPint _user_id, const MTPlong &_access_hash) : vuser_id(_user_id), vaccess_hash(_access_hash) { } MTPint vuser_id; @@ -9255,14 +9250,12 @@ class MTPDphoto : public mtpDataImpl { public: MTPDphoto() { } - MTPDphoto(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, const MTPGeoPoint &_geo, const MTPVector &_sizes) : vid(_id), vaccess_hash(_access_hash), vuser_id(_user_id), vdate(_date), vgeo(_geo), vsizes(_sizes) { + MTPDphoto(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPVector &_sizes) : vid(_id), vaccess_hash(_access_hash), vdate(_date), vsizes(_sizes) { } MTPlong vid; MTPlong vaccess_hash; - MTPint vuser_id; MTPint vdate; - MTPGeoPoint vgeo; MTPVector vsizes; }; @@ -9318,14 +9311,14 @@ class MTPDvideo : public mtpDataImpl { public: MTPDvideo() { } - MTPDvideo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h) : vid(_id), vaccess_hash(_access_hash), vuser_id(_user_id), vdate(_date), vduration(_duration), vsize(_size), vthumb(_thumb), vdc_id(_dc_id), vw(_w), vh(_h) { + MTPDvideo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h) : vid(_id), vaccess_hash(_access_hash), vdate(_date), vduration(_duration), vmime_type(_mime_type), vsize(_size), vthumb(_thumb), vdc_id(_dc_id), vw(_w), vh(_h) { } MTPlong vid; MTPlong vaccess_hash; - MTPint vuser_id; MTPint vdate; MTPint vduration; + MTPstring vmime_type; MTPint vsize; MTPPhotoSize vthumb; MTPint vdc_id; @@ -10684,12 +10677,11 @@ class MTPDaudio : public mtpDataImpl { public: MTPDaudio() { } - MTPDaudio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id) : vid(_id), vaccess_hash(_access_hash), vuser_id(_user_id), vdate(_date), vduration(_duration), vmime_type(_mime_type), vsize(_size), vdc_id(_dc_id) { + MTPDaudio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id) : vid(_id), vaccess_hash(_access_hash), vdate(_date), vduration(_duration), vmime_type(_mime_type), vsize(_size), vdc_id(_dc_id) { } MTPlong vid; MTPlong vaccess_hash; - MTPint vuser_id; MTPint vdate; MTPint vduration; MTPstring vmime_type; @@ -11329,6 +11321,16 @@ public: MTPVector vrows; }; +class MTPDhelp_appChangelog : public mtpDataImpl { +public: + MTPDhelp_appChangelog() { + } + MTPDhelp_appChangelog(const MTPstring &_text) : vtext(_text) { + } + + MTPstring vtext; +}; + // RPC methods class MTPreq_pq { // RPC method 'req_pq' @@ -14429,7 +14431,7 @@ class MTPphotos_getUserPhotos { // RPC method 'photos.getUserPhotos' public: MTPInputUser vuser_id; MTPint voffset; - MTPint vmax_id; + MTPlong vmax_id; MTPint vlimit; MTPphotos_getUserPhotos() { @@ -14437,7 +14439,7 @@ public: MTPphotos_getUserPhotos(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_photos_getUserPhotos) { read(from, end, cons); } - MTPphotos_getUserPhotos(const MTPInputUser &_user_id, MTPint _offset, MTPint _max_id, MTPint _limit) : vuser_id(_user_id), voffset(_offset), vmax_id(_max_id), vlimit(_limit) { + MTPphotos_getUserPhotos(const MTPInputUser &_user_id, MTPint _offset, const MTPlong &_max_id, MTPint _limit) : vuser_id(_user_id), voffset(_offset), vmax_id(_max_id), vlimit(_limit) { } uint32 innerLength() const { @@ -14469,7 +14471,7 @@ public: } MTPphotos_GetUserPhotos(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { } - MTPphotos_GetUserPhotos(const MTPInputUser &_user_id, MTPint _offset, MTPint _max_id, MTPint _limit) : MTPBoxed(MTPphotos_getUserPhotos(_user_id, _offset, _max_id, _limit)) { + MTPphotos_GetUserPhotos(const MTPInputUser &_user_id, MTPint _offset, const MTPlong &_max_id, MTPint _limit) : MTPBoxed(MTPphotos_getUserPhotos(_user_id, _offset, _max_id, _limit)) { } }; @@ -17049,6 +17051,54 @@ public: } }; +class MTPhelp_getAppChangelog { // RPC method 'help.getAppChangelog' +public: + MTPstring vdevice_model; + MTPstring vsystem_version; + MTPstring vapp_version; + MTPstring vlang_code; + + MTPhelp_getAppChangelog() { + } + MTPhelp_getAppChangelog(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_getAppChangelog) { + read(from, end, cons); + } + MTPhelp_getAppChangelog(const MTPstring &_device_model, const MTPstring &_system_version, const MTPstring &_app_version, const MTPstring &_lang_code) : vdevice_model(_device_model), vsystem_version(_system_version), vapp_version(_app_version), vlang_code(_lang_code) { + } + + uint32 innerLength() const { + return vdevice_model.innerLength() + vsystem_version.innerLength() + vapp_version.innerLength() + vlang_code.innerLength(); + } + mtpTypeId type() const { + return mtpc_help_getAppChangelog; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_getAppChangelog) { + vdevice_model.read(from, end); + vsystem_version.read(from, end); + vapp_version.read(from, end); + vlang_code.read(from, end); + } + void write(mtpBuffer &to) const { + vdevice_model.write(to); + vsystem_version.write(to); + vapp_version.write(to); + vlang_code.write(to); + } + + typedef MTPhelp_AppChangelog ResponseType; +}; +class MTPhelp_GetAppChangelog : public MTPBoxed { +public: + MTPhelp_GetAppChangelog() { + } + MTPhelp_GetAppChangelog(const MTPhelp_getAppChangelog &v) : MTPBoxed(v) { + } + MTPhelp_GetAppChangelog(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPhelp_GetAppChangelog(const MTPstring &_device_model, const MTPstring &_system_version, const MTPstring &_app_version, const MTPstring &_lang_code) : MTPBoxed(MTPhelp_getAppChangelog(_device_model, _system_version, _app_version, _lang_code)) { + } +}; + // Inline methods definition inline MTPresPQ::MTPresPQ() : mtpDataOwner(new MTPDresPQ()) { @@ -17989,18 +18039,14 @@ inline MTPnull MTP_null() { inline uint32 MTPinputPeer::innerLength() const { switch (_type) { - case mtpc_inputPeerContact: { - const MTPDinputPeerContact &v(c_inputPeerContact()); - return v.vuser_id.innerLength(); - } - case mtpc_inputPeerForeign: { - const MTPDinputPeerForeign &v(c_inputPeerForeign()); - return v.vuser_id.innerLength() + v.vaccess_hash.innerLength(); - } case mtpc_inputPeerChat: { const MTPDinputPeerChat &v(c_inputPeerChat()); return v.vchat_id.innerLength(); } + case mtpc_inputPeerUser: { + const MTPDinputPeerUser &v(c_inputPeerUser()); + return v.vuser_id.innerLength() + v.vaccess_hash.innerLength(); + } } return 0; } @@ -18013,82 +18059,63 @@ inline void MTPinputPeer::read(const mtpPrime *&from, const mtpPrime *end, mtpTy switch (cons) { case mtpc_inputPeerEmpty: _type = cons; break; case mtpc_inputPeerSelf: _type = cons; break; - case mtpc_inputPeerContact: _type = cons; { - if (!data) setData(new MTPDinputPeerContact()); - MTPDinputPeerContact &v(_inputPeerContact()); - v.vuser_id.read(from, end); - } break; - case mtpc_inputPeerForeign: _type = cons; { - if (!data) setData(new MTPDinputPeerForeign()); - MTPDinputPeerForeign &v(_inputPeerForeign()); - v.vuser_id.read(from, end); - v.vaccess_hash.read(from, end); - } break; case mtpc_inputPeerChat: _type = cons; { if (!data) setData(new MTPDinputPeerChat()); MTPDinputPeerChat &v(_inputPeerChat()); v.vchat_id.read(from, end); } break; + case mtpc_inputPeerUser: _type = cons; { + if (!data) setData(new MTPDinputPeerUser()); + MTPDinputPeerUser &v(_inputPeerUser()); + v.vuser_id.read(from, end); + v.vaccess_hash.read(from, end); + } break; default: throw mtpErrorUnexpected(cons, "MTPinputPeer"); } } inline void MTPinputPeer::write(mtpBuffer &to) const { switch (_type) { - case mtpc_inputPeerContact: { - const MTPDinputPeerContact &v(c_inputPeerContact()); - v.vuser_id.write(to); - } break; - case mtpc_inputPeerForeign: { - const MTPDinputPeerForeign &v(c_inputPeerForeign()); - v.vuser_id.write(to); - v.vaccess_hash.write(to); - } break; case mtpc_inputPeerChat: { const MTPDinputPeerChat &v(c_inputPeerChat()); v.vchat_id.write(to); } break; + case mtpc_inputPeerUser: { + const MTPDinputPeerUser &v(c_inputPeerUser()); + v.vuser_id.write(to); + v.vaccess_hash.write(to); + } break; } } inline MTPinputPeer::MTPinputPeer(mtpTypeId type) : mtpDataOwner(0), _type(type) { switch (type) { case mtpc_inputPeerEmpty: break; case mtpc_inputPeerSelf: break; - case mtpc_inputPeerContact: setData(new MTPDinputPeerContact()); break; - case mtpc_inputPeerForeign: setData(new MTPDinputPeerForeign()); break; case mtpc_inputPeerChat: setData(new MTPDinputPeerChat()); break; + case mtpc_inputPeerUser: setData(new MTPDinputPeerUser()); break; default: throw mtpErrorBadTypeId(type, "MTPinputPeer"); } } -inline MTPinputPeer::MTPinputPeer(MTPDinputPeerContact *_data) : mtpDataOwner(_data), _type(mtpc_inputPeerContact) { -} -inline MTPinputPeer::MTPinputPeer(MTPDinputPeerForeign *_data) : mtpDataOwner(_data), _type(mtpc_inputPeerForeign) { -} inline MTPinputPeer::MTPinputPeer(MTPDinputPeerChat *_data) : mtpDataOwner(_data), _type(mtpc_inputPeerChat) { } +inline MTPinputPeer::MTPinputPeer(MTPDinputPeerUser *_data) : mtpDataOwner(_data), _type(mtpc_inputPeerUser) { +} inline MTPinputPeer MTP_inputPeerEmpty() { return MTPinputPeer(mtpc_inputPeerEmpty); } inline MTPinputPeer MTP_inputPeerSelf() { return MTPinputPeer(mtpc_inputPeerSelf); } -inline MTPinputPeer MTP_inputPeerContact(MTPint _user_id) { - return MTPinputPeer(new MTPDinputPeerContact(_user_id)); -} -inline MTPinputPeer MTP_inputPeerForeign(MTPint _user_id, const MTPlong &_access_hash) { - return MTPinputPeer(new MTPDinputPeerForeign(_user_id, _access_hash)); -} inline MTPinputPeer MTP_inputPeerChat(MTPint _chat_id) { return MTPinputPeer(new MTPDinputPeerChat(_chat_id)); } +inline MTPinputPeer MTP_inputPeerUser(MTPint _user_id, const MTPlong &_access_hash) { + return MTPinputPeer(new MTPDinputPeerUser(_user_id, _access_hash)); +} inline uint32 MTPinputUser::innerLength() const { switch (_type) { - case mtpc_inputUserContact: { - const MTPDinputUserContact &v(c_inputUserContact()); - return v.vuser_id.innerLength(); - } - case mtpc_inputUserForeign: { - const MTPDinputUserForeign &v(c_inputUserForeign()); + case mtpc_inputUser: { + const MTPDinputUser &v(c_inputUser()); return v.vuser_id.innerLength() + v.vaccess_hash.innerLength(); } } @@ -18103,14 +18130,9 @@ inline void MTPinputUser::read(const mtpPrime *&from, const mtpPrime *end, mtpTy switch (cons) { case mtpc_inputUserEmpty: _type = cons; break; case mtpc_inputUserSelf: _type = cons; break; - case mtpc_inputUserContact: _type = cons; { - if (!data) setData(new MTPDinputUserContact()); - MTPDinputUserContact &v(_inputUserContact()); - v.vuser_id.read(from, end); - } break; - case mtpc_inputUserForeign: _type = cons; { - if (!data) setData(new MTPDinputUserForeign()); - MTPDinputUserForeign &v(_inputUserForeign()); + case mtpc_inputUser: _type = cons; { + if (!data) setData(new MTPDinputUser()); + MTPDinputUser &v(_inputUser()); v.vuser_id.read(from, end); v.vaccess_hash.read(from, end); } break; @@ -18119,12 +18141,8 @@ inline void MTPinputUser::read(const mtpPrime *&from, const mtpPrime *end, mtpTy } inline void MTPinputUser::write(mtpBuffer &to) const { switch (_type) { - case mtpc_inputUserContact: { - const MTPDinputUserContact &v(c_inputUserContact()); - v.vuser_id.write(to); - } break; - case mtpc_inputUserForeign: { - const MTPDinputUserForeign &v(c_inputUserForeign()); + case mtpc_inputUser: { + const MTPDinputUser &v(c_inputUser()); v.vuser_id.write(to); v.vaccess_hash.write(to); } break; @@ -18134,14 +18152,11 @@ inline MTPinputUser::MTPinputUser(mtpTypeId type) : mtpDataOwner(0), _type(type) switch (type) { case mtpc_inputUserEmpty: break; case mtpc_inputUserSelf: break; - case mtpc_inputUserContact: setData(new MTPDinputUserContact()); break; - case mtpc_inputUserForeign: setData(new MTPDinputUserForeign()); break; + case mtpc_inputUser: setData(new MTPDinputUser()); break; default: throw mtpErrorBadTypeId(type, "MTPinputUser"); } } -inline MTPinputUser::MTPinputUser(MTPDinputUserContact *_data) : mtpDataOwner(_data), _type(mtpc_inputUserContact) { -} -inline MTPinputUser::MTPinputUser(MTPDinputUserForeign *_data) : mtpDataOwner(_data), _type(mtpc_inputUserForeign) { +inline MTPinputUser::MTPinputUser(MTPDinputUser *_data) : mtpDataOwner(_data), _type(mtpc_inputUser) { } inline MTPinputUser MTP_inputUserEmpty() { return MTPinputUser(mtpc_inputUserEmpty); @@ -18149,11 +18164,8 @@ inline MTPinputUser MTP_inputUserEmpty() { inline MTPinputUser MTP_inputUserSelf() { return MTPinputUser(mtpc_inputUserSelf); } -inline MTPinputUser MTP_inputUserContact(MTPint _user_id) { - return MTPinputUser(new MTPDinputUserContact(_user_id)); -} -inline MTPinputUser MTP_inputUserForeign(MTPint _user_id, const MTPlong &_access_hash) { - return MTPinputUser(new MTPDinputUserForeign(_user_id, _access_hash)); +inline MTPinputUser MTP_inputUser(MTPint _user_id, const MTPlong &_access_hash) { + return MTPinputUser(new MTPDinputUser(_user_id, _access_hash)); } inline MTPinputContact::MTPinputContact() : mtpDataOwner(new MTPDinputPhoneContact()) { @@ -20319,7 +20331,7 @@ inline uint32 MTPphoto::innerLength() const { } case mtpc_photo: { const MTPDphoto &v(c_photo()); - return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vuser_id.innerLength() + v.vdate.innerLength() + v.vgeo.innerLength() + v.vsizes.innerLength(); + return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vdate.innerLength() + v.vsizes.innerLength(); } } return 0; @@ -20341,9 +20353,7 @@ inline void MTPphoto::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId MTPDphoto &v(_photo()); v.vid.read(from, end); v.vaccess_hash.read(from, end); - v.vuser_id.read(from, end); v.vdate.read(from, end); - v.vgeo.read(from, end); v.vsizes.read(from, end); } break; default: throw mtpErrorUnexpected(cons, "MTPphoto"); @@ -20359,9 +20369,7 @@ inline void MTPphoto::write(mtpBuffer &to) const { const MTPDphoto &v(c_photo()); v.vid.write(to); v.vaccess_hash.write(to); - v.vuser_id.write(to); v.vdate.write(to); - v.vgeo.write(to); v.vsizes.write(to); } break; } @@ -20380,8 +20388,8 @@ inline MTPphoto::MTPphoto(MTPDphoto *_data) : mtpDataOwner(_data), _type(mtpc_ph inline MTPphoto MTP_photoEmpty(const MTPlong &_id) { return MTPphoto(new MTPDphotoEmpty(_id)); } -inline MTPphoto MTP_photo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, const MTPGeoPoint &_geo, const MTPVector &_sizes) { - return MTPphoto(new MTPDphoto(_id, _access_hash, _user_id, _date, _geo, _sizes)); +inline MTPphoto MTP_photo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPVector &_sizes) { + return MTPphoto(new MTPDphoto(_id, _access_hash, _date, _sizes)); } inline uint32 MTPphotoSize::innerLength() const { @@ -20490,7 +20498,7 @@ inline uint32 MTPvideo::innerLength() const { } case mtpc_video: { const MTPDvideo &v(c_video()); - return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vuser_id.innerLength() + v.vdate.innerLength() + v.vduration.innerLength() + v.vsize.innerLength() + v.vthumb.innerLength() + v.vdc_id.innerLength() + v.vw.innerLength() + v.vh.innerLength(); + return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vdate.innerLength() + v.vduration.innerLength() + v.vmime_type.innerLength() + v.vsize.innerLength() + v.vthumb.innerLength() + v.vdc_id.innerLength() + v.vw.innerLength() + v.vh.innerLength(); } } return 0; @@ -20512,9 +20520,9 @@ inline void MTPvideo::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId MTPDvideo &v(_video()); v.vid.read(from, end); v.vaccess_hash.read(from, end); - v.vuser_id.read(from, end); v.vdate.read(from, end); v.vduration.read(from, end); + v.vmime_type.read(from, end); v.vsize.read(from, end); v.vthumb.read(from, end); v.vdc_id.read(from, end); @@ -20534,9 +20542,9 @@ inline void MTPvideo::write(mtpBuffer &to) const { const MTPDvideo &v(c_video()); v.vid.write(to); v.vaccess_hash.write(to); - v.vuser_id.write(to); v.vdate.write(to); v.vduration.write(to); + v.vmime_type.write(to); v.vsize.write(to); v.vthumb.write(to); v.vdc_id.write(to); @@ -20559,8 +20567,8 @@ inline MTPvideo::MTPvideo(MTPDvideo *_data) : mtpDataOwner(_data), _type(mtpc_vi inline MTPvideo MTP_videoEmpty(const MTPlong &_id) { return MTPvideo(new MTPDvideoEmpty(_id)); } -inline MTPvideo MTP_video(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h) { - return MTPvideo(new MTPDvideo(_id, _access_hash, _user_id, _date, _duration, _size, _thumb, _dc_id, _w, _h)); +inline MTPvideo MTP_video(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h) { + return MTPvideo(new MTPDvideo(_id, _access_hash, _date, _duration, _mime_type, _size, _thumb, _dc_id, _w, _h)); } inline uint32 MTPgeoPoint::innerLength() const { @@ -21852,6 +21860,7 @@ inline void MTPmessagesFilter::read(const mtpPrime *&from, const mtpPrime *end, case mtpc_inputMessagesFilterDocument: _type = cons; break; case mtpc_inputMessagesFilterAudio: _type = cons; break; case mtpc_inputMessagesFilterAudioDocuments: _type = cons; break; + case mtpc_inputMessagesFilterUrl: _type = cons; break; default: throw mtpErrorUnexpected(cons, "MTPmessagesFilter"); } } @@ -21869,6 +21878,7 @@ inline MTPmessagesFilter::MTPmessagesFilter(mtpTypeId type) : _type(type) { case mtpc_inputMessagesFilterDocument: break; case mtpc_inputMessagesFilterAudio: break; case mtpc_inputMessagesFilterAudioDocuments: break; + case mtpc_inputMessagesFilterUrl: break; default: throw mtpErrorBadTypeId(type, "MTPmessagesFilter"); } } @@ -21896,6 +21906,9 @@ inline MTPmessagesFilter MTP_inputMessagesFilterAudio() { inline MTPmessagesFilter MTP_inputMessagesFilterAudioDocuments() { return MTPmessagesFilter(mtpc_inputMessagesFilterAudioDocuments); } +inline MTPmessagesFilter MTP_inputMessagesFilterUrl() { + return MTPmessagesFilter(mtpc_inputMessagesFilterUrl); +} inline uint32 MTPupdate::innerLength() const { switch (_type) { @@ -24147,7 +24160,7 @@ inline uint32 MTPaudio::innerLength() const { } case mtpc_audio: { const MTPDaudio &v(c_audio()); - return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vuser_id.innerLength() + v.vdate.innerLength() + v.vduration.innerLength() + v.vmime_type.innerLength() + v.vsize.innerLength() + v.vdc_id.innerLength(); + return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vdate.innerLength() + v.vduration.innerLength() + v.vmime_type.innerLength() + v.vsize.innerLength() + v.vdc_id.innerLength(); } } return 0; @@ -24169,7 +24182,6 @@ inline void MTPaudio::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId MTPDaudio &v(_audio()); v.vid.read(from, end); v.vaccess_hash.read(from, end); - v.vuser_id.read(from, end); v.vdate.read(from, end); v.vduration.read(from, end); v.vmime_type.read(from, end); @@ -24189,7 +24201,6 @@ inline void MTPaudio::write(mtpBuffer &to) const { const MTPDaudio &v(c_audio()); v.vid.write(to); v.vaccess_hash.write(to); - v.vuser_id.write(to); v.vdate.write(to); v.vduration.write(to); v.vmime_type.write(to); @@ -24212,8 +24223,8 @@ inline MTPaudio::MTPaudio(MTPDaudio *_data) : mtpDataOwner(_data), _type(mtpc_au inline MTPaudio MTP_audioEmpty(const MTPlong &_id) { return MTPaudio(new MTPDaudioEmpty(_id)); } -inline MTPaudio MTP_audio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id) { - return MTPaudio(new MTPDaudio(_id, _access_hash, _user_id, _date, _duration, _mime_type, _size, _dc_id)); +inline MTPaudio MTP_audio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id) { + return MTPaudio(new MTPDaudio(_id, _access_hash, _date, _duration, _mime_type, _size, _dc_id)); } inline uint32 MTPdocument::innerLength() const { @@ -26072,6 +26083,55 @@ inline MTPreplyMarkup MTP_replyKeyboardMarkup(MTPint _flags, const MTPVector = Photo; +photo#cded42fe id:long access_hash:long date:int sizes:Vector = Photo; photoSizeEmpty#e17e23c type:string = PhotoSize; photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize; photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize; videoEmpty#c10658a8 id:long = Video; -video#ee9f4a4d id:long access_hash:long user_id:int date:int duration:int size:int thumb:PhotoSize dc_id:int w:int h:int = Video; +video#f72887d3 id:long access_hash:long date:int duration:int mime_type:string size:int thumb:PhotoSize dc_id:int w:int h:int = Video; geoPointEmpty#1117dd5f = GeoPoint; geoPoint#2049d70c long:double lat:double = GeoPoint; @@ -325,6 +321,7 @@ inputMessagesFilterPhotoVideoDocuments#d95e73bb = MessagesFilter; inputMessagesFilterDocument#9eddf188 = MessagesFilter; inputMessagesFilterAudio#cfc87522 = MessagesFilter; inputMessagesFilterAudioDocuments#5afbf764 = MessagesFilter; +inputMessagesFilterUrl#7ef0dd87 = MessagesFilter; updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update; updateMessageID#4e90bfd6 id:int random_id:long = Update; @@ -454,7 +451,7 @@ inputAudioFileLocation#74dc404d id:long access_hash:long = InputFileLocation; inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation; audioEmpty#586988d8 id:long = Audio; -audio#c7ac6496 id:long access_hash:long user_id:int date:int duration:int mime_type:string size:int dc_id:int = Audio; +audio#f9e35055 id:long access_hash:long date:int duration:int mime_type:string size:int dc_id:int = Audio; documentEmpty#36f8c871 id:long = Document; document#f9a39f4f id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector = Document; @@ -607,6 +604,13 @@ replyKeyboardHide#a03e5b85 flags:# = ReplyMarkup; replyKeyboardForceReply#f4108aa0 flags:# = ReplyMarkup; replyKeyboardMarkup#3502758c flags:# rows:Vector = ReplyMarkup; +inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer; + +inputUser#d8292816 user_id:int access_hash:long = InputUser; + +help.appChangelogEmpty#af7e0394 = help.AppChangelog; +help.appChangelog#4668e6bd text:string = help.AppChangelog; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -685,7 +689,7 @@ help.getAppUpdate#c812ac7e device_model:string system_version:string app_version help.saveAppLog#6f02f748 events:Vector = Bool; help.getInviteText#a4a95186 lang_code:string = help.InviteText; -photos.getUserPhotos#b7ee553c user_id:InputUser offset:int max_id:int limit:int = photos.Photos; +photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos; messages.forwardMessage#33963bf9 peer:InputPeer id:int random_id:long = Updates; messages.sendBroadcast#bf73f4da contacts:Vector random_id:Vector message:string media:InputMedia = Updates; @@ -770,3 +774,5 @@ messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet messages.installStickerSet#7b30c3a6 stickerset:InputStickerSet disabled:Bool = Bool; messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool; messages.startBot#1b3e0ffc bot:InputUser chat_id:int random_id:long start_param:string = Updates; + +help.getAppChangelog#5bab7fb2 device_model:string system_version:string app_version:string lang_code:string = help.AppChangelog; diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp index 30743e737..e6cf819e2 100644 --- a/Telegram/SourceFiles/profilewidget.cpp +++ b/Telegram/SourceFiles/profilewidget.cpp @@ -56,11 +56,6 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee // settings _enableNotifications(this, lang(lng_profile_enable_notifications)), - // actions - _searchInPeer(this, lang(lng_profile_search_messages)), - _clearHistory(this, lang(lng_profile_clear_history)), - _deleteConversation(this, lang(_peer->chat ? lng_profile_clear_and_exit : lng_profile_delete_conversation)), - // shared media _allMediaTypes(false), _mediaShowAll(this, lang(lng_profile_show_all_types)), @@ -69,6 +64,14 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee _mediaDocuments(this, QString()), _mediaAudios(this, QString()), + // actions + _searchInPeer(this, lang(lng_profile_search_messages)), + _clearHistory(this, lang(lng_profile_clear_history)), + _deleteConversation(this, lang(_peer->chat ? lng_profile_clear_and_exit : lng_profile_delete_conversation)), + _wasBlocked(_peerUser ? _peerUser->blocked : UserBlockUnknown), + _blockRequest(0), + _blockUser(this, lang((_peerUser && _peerUser->botInfo) ? lng_profile_block_bot : lng_profile_block_user), st::btnRedLink), + // participants _pHeight(st::profileListPhotoSize + st::profileListPadding.height() * 2), _kickWidth(st::linkFont->m.width(lang(lng_profile_kick))), @@ -80,12 +83,15 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee connect(App::api(), SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*))); if (_peerUser) { + if (_peerUser->blocked == UserIsBlocked) { + _blockUser.setText(lang(_peerUser->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user)); + } _phoneText = App::formatPhone(_peerUser->phone); PhotoData *userPhoto = (_peerUser->photoId && _peerUser->photoId != UnknownPeerPhotoId) ? App::photo(_peerUser->photoId) : 0; if (userPhoto && userPhoto->date) { _photoLink = TextLinkPtr(new PhotoLink(userPhoto, _peer)); } - if ((_peerUser->botInfo && !_peerUser->botInfo->inited) || (_peerUser->photoId == UnknownPeerPhotoId) || (_peerUser->photoId && !userPhoto->date)) { + if ((_peerUser->botInfo && !_peerUser->botInfo->inited) || (_peerUser->photoId == UnknownPeerPhotoId) || (_peerUser->photoId && !userPhoto->date) || (_peerUser->blocked == UserBlockUnknown)) { App::api()->requestFullPeer(_peer); } } else { @@ -153,11 +159,6 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee // settings connect(&_enableNotifications, SIGNAL(clicked()), this, SLOT(onEnableNotifications())); - // actions - connect(&_searchInPeer, SIGNAL(clicked()), this, SLOT(onSearchInPeer())); - connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory())); - connect(&_deleteConversation, SIGNAL(clicked()), this, SLOT(onDeleteConversation())); - // shared media connect(&_mediaShowAll, SIGNAL(clicked()), this, SLOT(onMediaShowAll())); connect(&_mediaPhotos, SIGNAL(clicked()), this, SLOT(onMediaPhotos())); @@ -170,6 +171,12 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee _mediaLinks[OverviewAudios] = &_mediaAudios; App::main()->preloadOverviews(_peer); + // actions + connect(&_searchInPeer, SIGNAL(clicked()), this, SLOT(onSearchInPeer())); + connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory())); + connect(&_deleteConversation, SIGNAL(clicked()), this, SLOT(onDeleteConversation())); + connect(&_blockUser, SIGNAL(clicked()), this, SLOT(onBlockUser())); + App::contextItem(0); resizeEvent(0); @@ -281,6 +288,28 @@ void ProfileInner::onDeleteConversationSure() { } } +void ProfileInner::onBlockUser() { + if (!_peerUser || _blockRequest) return; + if (_peerUser->blocked == UserIsBlocked) { + _blockRequest = MTP::send(MTPcontacts_Unblock(_peerUser->inputUser), rpcDone(&ProfileInner::blockDone, false), rpcFail(&ProfileInner::blockFail)); + } else { + _blockRequest = MTP::send(MTPcontacts_Block(_peerUser->inputUser), rpcDone(&ProfileInner::blockDone, true), rpcFail(&ProfileInner::blockFail)); + } +} + +void ProfileInner::blockDone(bool blocked, const MTPBool &result) { + _blockRequest = 0; + if (!_peerUser) return; + _peerUser->blocked = blocked ? UserIsBlocked : UserIsNotBlocked; + emit App::main()->peerUpdated(_peerUser); +} + +bool ProfileInner::blockFail(const RPCError &error) { + if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false; + //_blockRequest = 0; + return false; +} + void ProfileInner::onAddParticipant() { App::wnd()->showLayer(new ContactsBox(_peerChat)); } @@ -410,6 +439,10 @@ void ProfileInner::peerUpdated(PeerData *data) { if (_peerUser) { _phoneText = App::formatPhone(_peerUser->phone); if (_peerUser->photoId && _peerUser->photoId != UnknownPeerPhotoId) photo = App::photo(_peerUser->photoId); + if (_wasBlocked != _peerUser->blocked) { + _wasBlocked = _peerUser->blocked; + _blockUser.setText(lang((_peerUser->blocked == UserIsBlocked) ? (_peerUser->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user) : (_peerUser->botInfo ? lng_profile_block_bot : lng_profile_block_user))); + } } else { if (_peerChat->photoId && _peerChat->photoId != UnknownPeerPhotoId) photo = App::photo(_peerChat->photoId); } @@ -595,14 +628,6 @@ void ProfileInner::paintEvent(QPaintEvent *e) { top += _enableNotifications.height(); - // actions - p.setFont(st::profileHeaderFont->f); - p.setPen(st::profileHeaderColor->p); - p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section)); - top += st::profileHeaderSkip; - - top += _searchInPeer.height() + st::setLittleSkip + _clearHistory.height() + st::setLittleSkip + _deleteConversation.height(); - // shared media p.setFont(st::profileHeaderFont->f); p.setPen(st::profileHeaderColor->p); @@ -644,6 +669,15 @@ void ProfileInner::paintEvent(QPaintEvent *e) { top += _mediaLinks[OverviewPhotos]->height(); } + // actions + p.setFont(st::profileHeaderFont->f); + p.setPen(st::profileHeaderColor->p); + p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section)); + top += st::profileHeaderSkip; + + top += _searchInPeer.height() + st::setLittleSkip + _clearHistory.height() + st::setLittleSkip + _deleteConversation.height(); + if (_peerUser && _peerUser->id != MTP::authedId()) top += st::setSectionSkip + _blockUser.height(); + // participants if (_peerChat && (_peerChat->count > 0 || !_participants.isEmpty())) { QString sectionHeader = lang(_participants.isEmpty() ? lng_profile_loading : lng_profile_participants_section); @@ -741,7 +775,7 @@ void ProfileInner::updateSelected() { update(QRect(_left, _aboutTop, _width, _aboutHeight)); } - int32 partfrom = _mediaAudios.y() + _mediaAudios.height() + st::profileHeaderSkip; + int32 partfrom = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip; int32 newSelected = (lp.x() >= _left - st::profileListPadding.width() && lp.x() < _left + _width + st::profileListPadding.width() && lp.y() >= partfrom) ? (lp.y() - partfrom) / _pHeight : -1; UserData *newKickOver = 0; @@ -889,12 +923,6 @@ void ProfileInner::resizeEvent(QResizeEvent *e) { top += st::profileHeaderSkip; _enableNotifications.move(_left, top); top += _enableNotifications.height(); - // actions - top += st::profileHeaderSkip; - _searchInPeer.move(_left, top); top += _searchInPeer.height() + st::setLittleSkip; - _clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip; - _deleteConversation.move(_left, top); top += _deleteConversation.height(); - // shared media top += st::profileHeaderSkip; @@ -914,6 +942,16 @@ void ProfileInner::resizeEvent(QResizeEvent *e) { } top += _mediaLinks[OverviewPhotos]->height(); + // actions + top += st::profileHeaderSkip; + _searchInPeer.move(_left, top); top += _searchInPeer.height() + st::setLittleSkip; + _clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip; + _deleteConversation.move(_left, top); top += _deleteConversation.height(); + if (_peerUser && _peerUser->id != MTP::authedId()) { + top += st::setSectionSkip; + _blockUser.move(_left, top); top += _blockUser.height(); + } + // participants if (_peerChat && (_peerChat->count > 0 || !_participants.isEmpty())) { top += st::profileHeaderSkip; @@ -1047,7 +1085,7 @@ void ProfileInner::showAll() { _addParticipant.hide(); } } - _enableNotifications.show(); + _blockUser.hide(); } else { _uploadPhoto.hide(); _cancelPhoto.hide(); @@ -1066,9 +1104,14 @@ void ProfileInner::showAll() { _shareContact.show(); _inviteToGroup.hide(); } - _enableNotifications.show(); _clearHistory.show(); + if (_peerUser->id != MTP::authedId()) { + _blockUser.show(); + } else { + _blockUser.hide(); + } } + _enableNotifications.show(); updateNotifySettings(); // shared media @@ -1111,15 +1154,13 @@ void ProfileInner::showAll() { reorderParticipants(); int32 h; if (_peerUser) { - h = _mediaShowAll.y() + _mediaShowAll.height() + st::profileHeaderSkip; - if (_mediaShowAll.isHidden()) { - for (int i = 0; i < OverviewCount; ++i) { - if (i == OverviewAudioDocuments) continue; - if (!_mediaLinks[i]->isHidden()) h += _mediaLinks[i]->height() + st::setLittleSkip; - } + if (_peerUser->id == MTP::authedId()) { + h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip; + } else { + h = _blockUser.y() + _blockUser.height() + st::profileHeaderSkip; } } else { - h = _mediaAudios.y() + _mediaAudios.height() + st::profileHeaderSkip; + h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip; if (!_participants.isEmpty()) { h += st::profileHeaderSkip + _participants.size() * _pHeight; } else if (_peerChat->count > 0) { diff --git a/Telegram/SourceFiles/profilewidget.h b/Telegram/SourceFiles/profilewidget.h index 94765769d..5c742d31f 100644 --- a/Telegram/SourceFiles/profilewidget.h +++ b/Telegram/SourceFiles/profilewidget.h @@ -75,6 +75,7 @@ public slots: void onClearHistorySure(); void onDeleteConversation(); void onDeleteConversationSure(); + void onBlockUser(); void onAddParticipant(); void onUpdatePhoto(); @@ -146,15 +147,18 @@ private: // settings FlatCheckbox _enableNotifications; - // actions - LinkButton _searchInPeer, _clearHistory, _deleteConversation; - // shared media bool _allMediaTypes; LinkButton _mediaShowAll, _mediaPhotos, _mediaVideos, _mediaDocuments, _mediaAudios; LinkButton *_mediaLinks[OverviewCount]; QString overviewLinkText(int32 type, int32 count); + // actions + LinkButton _searchInPeer, _clearHistory, _deleteConversation; + UserBlockedStatus _wasBlocked; + mtpRequestId _blockRequest; + LinkButton _blockUser; + // participants int32 _pHeight; int32 _kickWidth, _selectedRow, _lastPreload; @@ -176,6 +180,9 @@ private: QString _onlineText; ContextMenu *_menu; + void blockDone(bool blocked, const MTPBool &result); + bool blockFail(const RPCError &error); + }; class ProfileWidget : public QWidget, public RPCSender, public Animated { diff --git a/Telegram/SourceFiles/pspecific_linux.h b/Telegram/SourceFiles/pspecific_linux.h index 580fefcec..a4de7f9ba 100644 --- a/Telegram/SourceFiles/pspecific_linux.h +++ b/Telegram/SourceFiles/pspecific_linux.h @@ -68,6 +68,10 @@ public: void psUpdateCounter(); + bool psHasNativeNotifications() { + return false; + } + virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0; ~PsMainWindow(); diff --git a/Telegram/SourceFiles/pspecific_mac.h b/Telegram/SourceFiles/pspecific_mac.h index 5dcda2877..a9807a175 100644 --- a/Telegram/SourceFiles/pspecific_mac.h +++ b/Telegram/SourceFiles/pspecific_mac.h @@ -83,6 +83,10 @@ public: void psUpdateCounter(); + bool psHasNativeNotifications() { + return !(QSysInfo::macVersion() < QSysInfo::MV_10_8); + } + virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0; ~PsMainWindow(); diff --git a/Telegram/SourceFiles/pspecific_wnd.cpp b/Telegram/SourceFiles/pspecific_wnd.cpp index a7ad89a93..d8dd244c7 100644 --- a/Telegram/SourceFiles/pspecific_wnd.cpp +++ b/Telegram/SourceFiles/pspecific_wnd.cpp @@ -24,6 +24,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "localstorage.h" +#include "passcodewidget.h" + #include #include #include @@ -33,11 +35,29 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include #include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + #include #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) < (b) ? (b) : (a)) +#include + #ifndef DCX_USESTYLE #define DCX_USESTYLE 0x00010000 #endif @@ -48,9 +68,15 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #define WM_NCPOINTERUP 0x0243 #endif -#include -#pragma comment (lib,"Gdiplus.lib") -#pragma comment (lib,"Msimg32.lib") +const WCHAR AppUserModelId[] = L"Telegram.TelegramDesktop"; + +static const PROPERTYKEY pkey_AppUserModel_ID = { { 0x9F4C2855, 0x9F79, 0x4B39, { 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 } }, 5 }; +static const PROPERTYKEY pkey_AppUserModel_StartPinOption = { { 0x9F4C2855, 0x9F79, 0x4B39, { 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 } }, 12 }; + +using namespace Microsoft::WRL; +using namespace ABI::Windows::UI::Notifications; +using namespace ABI::Windows::Data::Xml::Dom; +using namespace Windows::Foundation; namespace { QStringList _initLogs; @@ -61,6 +87,7 @@ namespace { bool useOpenAs = false; bool useWtsapi = false; bool useShellapi = false; + bool useToast = false; bool themeInited = false; bool finished = true; int menuShown = 0, menuHidden = 0; @@ -70,7 +97,27 @@ namespace { bool sessionLoggedOff = false; UINT tbCreatedMsgId = 0; - ITaskbarList3 *tbListInterface = 0; + + ComPtr taskbarList; + + ComPtr toastNotificationManager; + ComPtr toastNotifier; + ComPtr toastNotificationFactory; + struct ToastNotificationPtr { + ToastNotificationPtr() { + } + ToastNotificationPtr(const ComPtr &ptr) : p(ptr) { + } + ComPtr p; + }; + typedef QMap > ToastNotifications; + ToastNotifications toastNotifications; + struct ToastImage { + uint64 until; + QString path; + }; + typedef QMap ToastImages; + ToastImages toastImages; HWND createTaskbarHider() { HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); @@ -245,9 +292,7 @@ namespace { destroy(); return false; } -// if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS8) { - SetWindowLong(hwnds[i], GWL_HWNDPARENT, (LONG)hwnd); -// } + SetWindowLong(hwnds[i], GWL_HWNDPARENT, (LONG)hwnd); dcs[i] = CreateCompatibleDC(screenDC); if (!dcs[i]) { @@ -629,9 +674,6 @@ namespace { typedef HRESULT (FAR STDAPICALLTYPE *f_shCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv); f_shCreateItemFromParsingName shCreateItemFromParsingName = 0; - typedef HRESULT (FAR STDAPICALLTYPE *f_shLoadIndirectString)(LPCWSTR pszSource, LPWSTR pszOutBuf, UINT cchOutBuf, void **ppvReserved); - f_shLoadIndirectString shLoadIndirectString = 0; - typedef BOOL (FAR STDAPICALLTYPE *f_wtsRegisterSessionNotification)(HWND hWnd, DWORD dwFlags); f_wtsRegisterSessionNotification wtsRegisterSessionNotification = 0; @@ -640,6 +682,21 @@ namespace { typedef HRESULT (FAR STDAPICALLTYPE *f_shQueryUserNotificationState)(QUERY_USER_NOTIFICATION_STATE *pquns); f_shQueryUserNotificationState shQueryUserNotificationState = 0; + + typedef HRESULT (FAR STDAPICALLTYPE *f_setCurrentProcessExplicitAppUserModelID)(__in PCWSTR AppID); + f_setCurrentProcessExplicitAppUserModelID setCurrentProcessExplicitAppUserModelID = 0; + + typedef HRESULT (FAR STDAPICALLTYPE *f_roGetActivationFactory)(_In_ HSTRING activatableClassId, _In_ REFIID iid, _COM_Outptr_ void ** factory); + f_roGetActivationFactory roGetActivationFactory = 0; + + typedef HRESULT (FAR STDAPICALLTYPE *f_windowsCreateStringReference)(_In_reads_opt_(length + 1) PCWSTR sourceString, UINT32 length, _Out_ HSTRING_HEADER * hstringHeader, _Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING * string); + f_windowsCreateStringReference windowsCreateStringReference = 0; + + typedef HRESULT (FAR STDAPICALLTYPE *f_windowsDeleteString)(_In_opt_ HSTRING string); + f_windowsDeleteString windowsDeleteString = 0; + + typedef HRESULT (FAR STDAPICALLTYPE *f_propVariantToString)(_In_ REFPROPVARIANT propvar, _Out_writes_(cch) PWSTR psz, _In_ UINT cch); + f_propVariantToString propVariantToString = 0; template bool loadFunction(HINSTANCE dll, LPCSTR name, TFunction &func) { @@ -657,6 +714,7 @@ namespace { setupUx(); setupShell(); setupWtsapi(); + setupCombase(); } void setupUx() { HINSTANCE procId = LoadLibrary(L"UXTHEME.DLL"); @@ -669,19 +727,24 @@ namespace { setupOpenWith(procId); setupOpenAs(procId); setupShellapi(procId); + setupAppUserModel(procId); } void setupOpenWith(HINSTANCE procId) { if (!loadFunction(procId, "SHAssocEnumHandlers", shAssocEnumHandlers)) return; if (!loadFunction(procId, "SHCreateItemFromParsingName", shCreateItemFromParsingName)) return; useOpenWith = true; - - HINSTANCE otherProcId = LoadLibrary(L"SHLWAPI.DLL"); - if (otherProcId) loadFunction(otherProcId, "SHLoadIndirectString", shLoadIndirectString); } void setupOpenAs(HINSTANCE procId) { if (!loadFunction(procId, "SHOpenWithDialog", shOpenWithDialog) && !loadFunction(procId, "OpenAs_RunDLLW", openAs_RunDLL)) return; useOpenAs = true; } + void setupShellapi(HINSTANCE procId) { + if (!loadFunction(procId, "SHQueryUserNotificationState", shQueryUserNotificationState)) return; + useShellapi = true; + } + void setupAppUserModel(HINSTANCE procId) { + if (!loadFunction(procId, "SetCurrentProcessExplicitAppUserModelID", setCurrentProcessExplicitAppUserModelID)) return; + } void setupWtsapi() { HINSTANCE procId = LoadLibrary(L"WTSAPI32.DLL"); @@ -689,9 +752,24 @@ namespace { if (!loadFunction(procId, "WTSUnRegisterSessionNotification", wtsUnRegisterSessionNotification)) return; useWtsapi = true; } - void setupShellapi(HINSTANCE procId) { - if (!loadFunction(procId, "SHQueryUserNotificationState", shQueryUserNotificationState)) return; - useShellapi = true; + void setupCombase() { + if (!setCurrentProcessExplicitAppUserModelID) return; + + HINSTANCE procId = LoadLibrary(L"COMBASE.DLL"); + setupToast(procId); + } + void setupToast(HINSTANCE procId) { + if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS8) return; + if (!loadFunction(procId, "RoGetActivationFactory", roGetActivationFactory)) return; + + HINSTANCE otherProcId = LoadLibrary(L"api-ms-win-core-winrt-string-l1-1-0.dll"); + if (!loadFunction(otherProcId, "WindowsCreateStringReference", windowsCreateStringReference)) return; + if (!loadFunction(otherProcId, "WindowsDeleteString", windowsDeleteString)) return; + + HINSTANCE otherOtherProcId = LoadLibrary(L"PROPSYS.DLL"); + if (!loadFunction(otherOtherProcId, "PropVariantToString", propVariantToString)) return; + + useToast = true; } }; _PsInitializer _psInitializer; @@ -718,8 +796,9 @@ namespace { bool mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result) { if (tbCreatedMsgId && msg == tbCreatedMsgId) { - if (CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, IID_ITaskbarList3, (void**)&tbListInterface) != S_OK) { - tbListInterface = 0; + HRESULT hr = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&taskbarList)); + if (!SUCCEEDED(hr)) { + taskbarList.Reset(); } } switch (msg) { @@ -915,12 +994,41 @@ namespace { PsMainWindow::PsMainWindow(QWidget *parent) : QMainWindow(parent), ps_hWnd(0), ps_menu(0), icon256(qsl(":/gui/art/icon256.png")), iconbig256(qsl(":/gui/art/iconbig256.png")), wndIcon(QPixmap::fromImage(icon256, Qt::ColorOnly)), ps_iconBig(0), ps_iconSmall(0), ps_iconOverlay(0), trayIcon(0), trayIconMenu(0), posInited(false), ps_tbHider_hWnd(createTaskbarHider()) { tbCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated"); + connect(&ps_cleanNotifyPhotosTimer, SIGNAL(timeout()), this, SLOT(psCleanNotifyPhotos())); } void PsMainWindow::psShowTrayMenu() { trayIconMenu->popup(QCursor::pos()); } +void PsMainWindow::psCleanNotifyPhotosIn(int32 dt) { + if (dt < 0) { + if (ps_cleanNotifyPhotosTimer.isActive() && ps_cleanNotifyPhotosTimer.remainingTime() <= -dt) return; + dt = -dt; + } + ps_cleanNotifyPhotosTimer.start(dt); +} + +void PsMainWindow::psCleanNotifyPhotos() { + uint64 ms = getms(true), minuntil = 0; + for (ToastImages::iterator i = toastImages.begin(); i != toastImages.end();) { + if (!i->until) { + ++i; + continue; + } + if (i->until <= ms) { + QFile(i->path).remove(); + i = toastImages.erase(i); + } else { + if (!minuntil || minuntil > i->until) { + minuntil = i->until; + } + ++i; + } + } + if (minuntil) psCleanNotifyPhotosIn(int32(minuntil - ms)); +} + void PsMainWindow::psRefreshTaskbarIcon() { QWidget *w = new QWidget(this); w->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); @@ -1008,8 +1116,8 @@ void PsMainWindow::psUpdateCounter() { QIcon iconSmall, iconBig; iconSmall.addPixmap(QPixmap::fromImage(iconWithCounter(16, counter, bg, true), Qt::ColorOnly)); iconSmall.addPixmap(QPixmap::fromImage(iconWithCounter(32, counter, bg, true), Qt::ColorOnly)); - iconBig.addPixmap(QPixmap::fromImage(iconWithCounter(32, tbListInterface ? 0 : counter, bg, false), Qt::ColorOnly)); - iconBig.addPixmap(QPixmap::fromImage(iconWithCounter(64, tbListInterface ? 0 : counter, bg, false), Qt::ColorOnly)); + iconBig.addPixmap(QPixmap::fromImage(iconWithCounter(32, taskbarList.Get() ? 0 : counter, bg, false), Qt::ColorOnly)); + iconBig.addPixmap(QPixmap::fromImage(iconWithCounter(64, taskbarList.Get() ? 0 : counter, bg, false), Qt::ColorOnly)); if (trayIcon) { trayIcon->setIcon(iconSmall); } @@ -1020,7 +1128,7 @@ void PsMainWindow::psUpdateCounter() { ps_iconBig = _qt_createHIcon(iconBig, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); SendMessage(ps_hWnd, WM_SETICON, 0, (LPARAM)ps_iconSmall); SendMessage(ps_hWnd, WM_SETICON, 1, (LPARAM)(ps_iconBig ? ps_iconBig : ps_iconSmall)); - if (tbListInterface) { + if (taskbarList.Get()) { if (counter > 0) { QIcon iconOverlay; iconOverlay.addPixmap(QPixmap::fromImage(iconWithCounter(-16, counter, bg, false), Qt::ColorOnly)); @@ -1028,9 +1136,7 @@ void PsMainWindow::psUpdateCounter() { ps_iconOverlay = _qt_createHIcon(iconOverlay, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); } QString description = counter > 0 ? QString("%1 unread messages").arg(counter) : qsl("No unread messages"); - static WCHAR descriptionArr[1024]; - description.toWCharArray(descriptionArr); - tbListInterface->SetOverlayIcon(ps_hWnd, ps_iconOverlay, descriptionArr); + taskbarList->SetOverlayIcon(ps_hWnd, ps_iconOverlay, description.toStdWString().c_str()); } SetWindowPos(ps_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); } @@ -1089,6 +1195,10 @@ void PsMainWindow::psInitSize() { setGeometry(geom); } +bool InitToastManager(); +bool CreateToast(PeerData *peer, int32 msgId, bool showpix, const QString &title, const QString &subtitle, const QString &msg); +void CleanupAppUserModelIdShortcut(); + void PsMainWindow::psInitFrameless() { psUpdatedPositionTimer.setSingleShot(true); connect(&psUpdatedPositionTimer, SIGNAL(timeout()), this, SLOT(psSavePosition())); @@ -1105,6 +1215,9 @@ void PsMainWindow::psInitFrameless() { } // RegisterApplicationRestart(NULL, 0); + if (!InitToastManager()) { + useToast = false; + } psInitSysMenu(); } @@ -1151,8 +1264,18 @@ void PsMainWindow::psUpdatedPosition() { psUpdatedPositionTimer.start(SaveWindowPositionTimeout); } +bool PsMainWindow::psHasNativeNotifications() { + return useToast; +} + Q_DECLARE_METATYPE(QMargins); void PsMainWindow::psFirstShow() { + if (useToast) { + cSetCustomNotifies(!cWindowsNotifications()); + } else { + cSetCustomNotifies(true); + } + _psShadowWindows.init(_shActive); finished = false; @@ -1328,6 +1451,13 @@ PsMainWindow::~PsMainWindow() { } } + if (taskbarList) taskbarList.Reset(); + + toastNotifications.clear(); + if (toastNotificationManager) toastNotificationManager.Reset(); + if (toastNotifier) toastNotifier.Reset(); + if (toastNotificationFactory) toastNotificationFactory.Reset(); + finished = true; if (ps_menu) DestroyMenu(ps_menu); psDestroyIcons(); @@ -1367,12 +1497,40 @@ void PsMainWindow::psActivateNotify(NotifyWindow *w) { } void PsMainWindow::psClearNotifies(PeerId peerId) { + if (!toastNotifier) return; + + if (peerId) { + ToastNotifications::iterator i = toastNotifications.find(peerId); + if (i != toastNotifications.cend()) { + QMap temp = i.value(); + toastNotifications.erase(i); + + for (QMap::const_iterator j = temp.cbegin(), e = temp.cend(); j != e; ++j) { + toastNotifier->Hide(j->p.Get()); + } + } + } else { + ToastNotifications temp = toastNotifications; + toastNotifications.clear(); + + for (ToastNotifications::const_iterator i = temp.cbegin(), end = temp.cend(); i != end; ++i) { + for (QMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) { + toastNotifier->Hide(j->p.Get()); + } + } + } } void PsMainWindow::psNotifyShown(NotifyWindow *w) { } void PsMainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) { + QString title = (!App::passcoded() && cNotifyView() <= dbinvShowName) ? item->history()->peer->name : qsl("Telegram Desktop"); + QString subtitle = (!App::passcoded() && cNotifyView() <= dbinvShowName) ? item->notificationHeader() : QString(); + bool showpix = (!App::passcoded() && cNotifyView() <= dbinvShowName); + QString msg = (!App::passcoded() && cNotifyView() <= dbinvShowPreview) ? (fwdCount < 2 ? item->notificationText() : lng_forward_messages(lt_count, fwdCount)) : lang(lng_notification_preview); + + CreateToast(item->history()->peer, item->id, showpix, title, subtitle, msg); } PsApplication::PsApplication(int &argc, char **argv) : QApplication(argc, argv) { @@ -1704,6 +1862,7 @@ void psDoCleanup() { try { psAutoStart(false, true); psSendToMenu(false, true); + CleanupAppUserModelIdShortcut(); } catch (...) { } } @@ -1822,7 +1981,7 @@ namespace { HBITMAP _iconToBitmap(LPWSTR icon, int iconindex) { if (!icon) return 0; WCHAR tmpIcon[4096]; - if (icon[0] == L'@' && shLoadIndirectString && SUCCEEDED(shLoadIndirectString(icon, tmpIcon, 4096, 0))) { + if (icon[0] == L'@' && SUCCEEDED(SHLoadIndirectString(icon, tmpIcon, 4096, 0))) { icon = tmpIcon; } int32 w = GetSystemMetrics(SM_CXSMICON), h = GetSystemMetrics(SM_CYSMICON); @@ -1983,6 +2142,7 @@ void psStart() { } void psFinish() { + psDeleteDir(cWorkingDir() + qsl("tdata/temp")); } namespace { @@ -2038,10 +2198,12 @@ namespace { } void psRegisterCustomScheme() { + + DEBUG_LOG(("App Info: Checking custom scheme 'tg'..")); HKEY rkey; - QString exe = QDir::toNativeSeparators(QDir(cExeDir()).absolutePath() + '/' + QString::fromWCharArray(AppFile) + qsl(".exe")); + QString exe = QDir::toNativeSeparators(cExeDir() + cExeName()); if (!_psOpenRegKey(L"Software\\Classes\\tg", &rkey)) return; if (!_psSetKeyValue(rkey, L"URL Protocol", QString())) return; @@ -2084,9 +2246,9 @@ void psExecTelegram() { if (cTestMode()) targs += qsl(" -testmode"); if (cDataFile() != qsl("data")) targs += qsl(" -key \"") + cDataFile() + '"'; - QString telegram(QDir::toNativeSeparators(cExeDir() + QString::fromWCharArray(AppFile) + qsl(".exe"))), wdir(QDir::toNativeSeparators(cWorkingDir())); + QString telegram(QDir::toNativeSeparators(cExeDir() + cExeName())), wdir(QDir::toNativeSeparators(cWorkingDir())); - DEBUG_LOG(("Application Info: executing %1 %2").arg(cExeDir() + QString::fromWCharArray(AppFile) + qsl(".exe")).arg(targs)); + DEBUG_LOG(("Application Info: executing %1 %2").arg(cExeDir() + cExeName()).arg(targs)); HINSTANCE r = ShellExecute(0, 0, telegram.toStdWString().c_str(), targs.toStdWString().c_str(), wdir.isEmpty() ? 0 : wdir.toStdWString().c_str(), SW_SHOWNORMAL); if (long(r) < 32) { DEBUG_LOG(("Application Error: failed to execute %1, working directory: '%2', result: %3").arg(telegram).arg(wdir).arg(long(r))); @@ -2095,38 +2257,49 @@ void psExecTelegram() { void _manageAppLnk(bool create, bool silent, int path_csidl, const wchar_t *args, const wchar_t *description) { WCHAR startupFolder[MAX_PATH]; - HRESULT hres = SHGetFolderPath(0, path_csidl, 0, SHGFP_TYPE_CURRENT, startupFolder); - if (SUCCEEDED(hres)) { + HRESULT hr = SHGetFolderPath(0, path_csidl, 0, SHGFP_TYPE_CURRENT, startupFolder); + if (SUCCEEDED(hr)) { QString lnk = QString::fromWCharArray(startupFolder) + '\\' + QString::fromWCharArray(AppFile) + qsl(".lnk"); if (create) { - IShellLink* psl; - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); - if (SUCCEEDED(hres)) { - IPersistFile* ppf; + ComPtr shellLink; + hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)); + if (SUCCEEDED(hr)) { + ComPtr persistFile; - QString exe = QDir::toNativeSeparators(QDir(cExeDir()).absolutePath() + '/' + QString::fromWCharArray(AppFile) + qsl(".exe")), dir = QDir::toNativeSeparators(QDir(cWorkingDir()).absolutePath()); - psl->SetArguments(args); - psl->SetPath(exe.toStdWString().c_str()); - psl->SetWorkingDirectory(dir.toStdWString().c_str()); - psl->SetDescription(description); + QString exe = QDir::toNativeSeparators(cExeDir() + cExeName()), dir = QDir::toNativeSeparators(QDir(cWorkingDir()).absolutePath()); + shellLink->SetArguments(args); + shellLink->SetPath(exe.toStdWString().c_str()); + shellLink->SetWorkingDirectory(dir.toStdWString().c_str()); + shellLink->SetDescription(description); - hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); - - if (SUCCEEDED(hres)) { - hres = ppf->Save(lnk.toStdWString().c_str(), TRUE); - ppf->Release(); - } else { - if (!silent) LOG(("App Error: could not create interface IID_IPersistFile %1").arg(hres)); + ComPtr propertyStore; + hr = shellLink.As(&propertyStore); + if (SUCCEEDED(hr)) { + PROPVARIANT appIdPropVar; + hr = InitPropVariantFromString(AppUserModelId, &appIdPropVar); + if (SUCCEEDED(hr)) { + hr = propertyStore->SetValue(pkey_AppUserModel_ID, appIdPropVar); + PropVariantClear(&appIdPropVar); + if (SUCCEEDED(hr)) { + hr = propertyStore->Commit(); + } + } + } + + hr = shellLink.As(&persistFile); + if (SUCCEEDED(hr)) { + hr = persistFile->Save(lnk.toStdWString().c_str(), TRUE); + } else { + if (!silent) LOG(("App Error: could not create interface IID_IPersistFile %1").arg(hr)); } - psl->Release(); } else { - if (!silent) LOG(("App Error: could not create instance of IID_IShellLink %1").arg(hres)); + if (!silent) LOG(("App Error: could not create instance of IID_IShellLink %1").arg(hr)); } } else { QFile::remove(lnk); } } else { - if (!silent) LOG(("App Error: could not get CSIDL %1 folder %2").arg(path_csidl).arg(hres)); + if (!silent) LOG(("App Error: could not get CSIDL %1 folder %2").arg(path_csidl).arg(hr)); } } @@ -2247,3 +2420,562 @@ LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) { return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH; } #endif + +class StringReferenceWrapper { +public: + + StringReferenceWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() { + HRESULT hr = windowsCreateStringReference(stringRef, length, &_header, &_hstring); + if (!SUCCEEDED(hr)) { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); + } + } + + ~StringReferenceWrapper() { + windowsDeleteString(_hstring); + } + + template + StringReferenceWrapper(_In_reads_(N) wchar_t const (&stringRef)[N]) throw() { + UINT32 length = N - 1; + HRESULT hr = windowsCreateStringReference(stringRef, length, &_header, &_hstring); + if (!SUCCEEDED(hr)) { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); + } + } + + template + StringReferenceWrapper(_In_reads_(_) wchar_t(&stringRef)[_]) throw() { + UINT32 length; + HRESULT hr = SizeTToUInt32(wcslen(stringRef), &length); + if (!SUCCEEDED(hr)) { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); + } + + windowsCreateStringReference(stringRef, length, &_header, &_hstring); + } + + HSTRING Get() const throw() { + return _hstring; + } + +private: + HSTRING _hstring; + HSTRING_HEADER _header; + +}; + +HRESULT SetNodeValueString(_In_ HSTRING inputString, _In_ IXmlNode *node, _In_ IXmlDocument *xml) { + ComPtr inputText; + + HRESULT hr = xml->CreateTextNode(inputString, &inputText); + if (!SUCCEEDED(hr)) return hr; + ComPtr inputTextNode; + + hr = inputText.As(&inputTextNode); + if (!SUCCEEDED(hr)) return hr; + + ComPtr pAppendedChild; + return node->AppendChild(inputTextNode.Get(), &pAppendedChild); +} + +HRESULT SetAudioSilent(_In_ IXmlDocument *toastXml) { + ComPtr nodeList; + HRESULT hr = toastXml->GetElementsByTagName(StringReferenceWrapper(L"audio").Get(), &nodeList); + if (!SUCCEEDED(hr)) return hr; + + ComPtr audioNode; + hr = nodeList->Item(0, &audioNode); + if (!SUCCEEDED(hr)) return hr; + + if (audioNode) { + ComPtr audioElement; + hr = audioNode.As(&audioElement); + if (!SUCCEEDED(hr)) return hr; + + hr = audioElement->SetAttribute(StringReferenceWrapper(L"silent").Get(), StringReferenceWrapper(L"true").Get()); + if (!SUCCEEDED(hr)) return hr; + } else { + ComPtr audioElement; + hr = toastXml->CreateElement(StringReferenceWrapper(L"audio").Get(), &audioElement); + if (!SUCCEEDED(hr)) return hr; + + hr = audioElement->SetAttribute(StringReferenceWrapper(L"silent").Get(), StringReferenceWrapper(L"true").Get()); + if (!SUCCEEDED(hr)) return hr; + + ComPtr audioNode; + hr = audioElement.As(&audioNode); + if (!SUCCEEDED(hr)) return hr; + + ComPtr nodeList; + hr = toastXml->GetElementsByTagName(StringReferenceWrapper(L"toast").Get(), &nodeList); + if (!SUCCEEDED(hr)) return hr; + + ComPtr toastNode; + hr = nodeList->Item(0, &toastNode); + if (!SUCCEEDED(hr)) return hr; + + ComPtr appendedNode; + hr = toastNode->AppendChild(audioNode.Get(), &appendedNode); + } + return hr; +} + +HRESULT SetImageSrc(_In_z_ const wchar_t *imagePath, _In_ IXmlDocument *toastXml) { + wchar_t imageSrc[MAX_PATH] = L"file:///"; + HRESULT hr = StringCchCat(imageSrc, ARRAYSIZE(imageSrc), imagePath); + if (!SUCCEEDED(hr)) return hr; + + ComPtr nodeList; + hr = toastXml->GetElementsByTagName(StringReferenceWrapper(L"image").Get(), &nodeList); + if (!SUCCEEDED(hr)) return hr; + + ComPtr imageNode; + hr = nodeList->Item(0, &imageNode); + if (!SUCCEEDED(hr)) return hr; + + ComPtr attributes; + hr = imageNode->get_Attributes(&attributes); + if (!SUCCEEDED(hr)) return hr; + + ComPtr srcAttribute; + hr = attributes->GetNamedItem(StringReferenceWrapper(L"src").Get(), &srcAttribute); + if (!SUCCEEDED(hr)) return hr; + + return SetNodeValueString(StringReferenceWrapper(imageSrc).Get(), srcAttribute.Get(), toastXml); +} + +typedef ABI::Windows::Foundation::ITypedEventHandler DesktopToastActivatedEventHandler; +typedef ABI::Windows::Foundation::ITypedEventHandler DesktopToastDismissedEventHandler; +typedef ABI::Windows::Foundation::ITypedEventHandler DesktopToastFailedEventHandler; + +class ToastEventHandler : public Implements { +public: + ToastEventHandler::ToastEventHandler(uint64 peer, int32 msg) : _ref(1), _peerId(peer), _msgId(msg) { + } + ~ToastEventHandler() { + } + + // DesktopToastActivatedEventHandler + IFACEMETHODIMP Invoke(_In_ IToastNotification *sender, _In_ IInspectable* args) { + ToastNotifications::iterator i = toastNotifications.find(_peerId); + if (i != toastNotifications.cend()) { + i.value().remove(_msgId); + if (i.value().isEmpty()) { + toastNotifications.erase(i); + } + } + if (App::wnd()) { + History *history = App::history(PeerId(_peerId)); + + App::wnd()->showFromTray(); + if (App::passcoded()) { + App::wnd()->passcodeWidget()->setInnerFocus(); + App::wnd()->notifyClear(); + } else { + App::wnd()->hideSettings(); + bool tomsg = history->peer->chat && (_msgId > 0); + if (tomsg) { + HistoryItem *item = App::histItemById(_msgId); + if (!item || !item->notifyByFrom()) { + tomsg = false; + } + } + App::main()->showPeerHistory(history->peer->id, tomsg ? _msgId : ShowAtUnreadMsgId); + App::wnd()->notifyClear(history); + } + SetForegroundWindow(App::wnd()->psHwnd()); + } + return S_OK; + } + + // DesktopToastDismissedEventHandler + IFACEMETHODIMP Invoke(_In_ IToastNotification *sender, _In_ IToastDismissedEventArgs *e) { + ToastDismissalReason tdr; + if (SUCCEEDED(e->get_Reason(&tdr))) { + switch (tdr) { + case ToastDismissalReason_ApplicationHidden: + break; + case ToastDismissalReason_UserCanceled: + case ToastDismissalReason_TimedOut: + default: + ToastNotifications::iterator i = toastNotifications.find(_peerId); + if (i != toastNotifications.cend()) { + i.value().remove(_msgId); + if (i.value().isEmpty()) { + toastNotifications.erase(i); + } + } + break; + } + } + return S_OK; + } + + // DesktopToastFailedEventHandler + IFACEMETHODIMP Invoke(_In_ IToastNotification *sender, _In_ IToastFailedEventArgs *e) { + ToastNotifications::iterator i = toastNotifications.find(_peerId); + if (i != toastNotifications.cend()) { + i.value().remove(_msgId); + if (i.value().isEmpty()) { + toastNotifications.erase(i); + } + } + return S_OK; + } + + // IUnknown + IFACEMETHODIMP_(ULONG) AddRef() { + return InterlockedIncrement(&_ref); + } + + IFACEMETHODIMP_(ULONG) Release() { + ULONG l = InterlockedDecrement(&_ref); + if (l == 0) delete this; + return l; + } + + IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _COM_Outptr_ void **ppv) { + if (IsEqualIID(riid, IID_IUnknown)) + *ppv = static_cast(static_cast(this)); + else if (IsEqualIID(riid, __uuidof(DesktopToastActivatedEventHandler))) + *ppv = static_cast(this); + else if (IsEqualIID(riid, __uuidof(DesktopToastDismissedEventHandler))) + *ppv = static_cast(this); + else if (IsEqualIID(riid, __uuidof(DesktopToastFailedEventHandler))) + *ppv = static_cast(this); + else *ppv = nullptr; + + if (*ppv) { + reinterpret_cast(*ppv)->AddRef(); + return S_OK; + } + + return E_NOINTERFACE; + } + +private: + ULONG _ref; + uint64 _peerId; + int32 _msgId; +}; + +template +_Check_return_ __inline HRESULT _1_GetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ T** factory) { + return roGetActivationFactory(activatableClassId, IID_INS_ARGS(factory)); +} + +template +inline HRESULT wrap_GetActivationFactory(_In_ HSTRING activatableClassId, _Inout_ Details::ComPtrRef factory) throw() { + return _1_GetActivationFactory(activatableClassId, factory.ReleaseAndGetAddressOf()); +} + +QString toastImage(const StorageKey &key, PeerData *peer) { + uint64 ms = getms(true); + ToastImages::iterator i = toastImages.find(key); + if (i != toastImages.cend()) { + if (i->until) { + i->until = ms + NotifyDeletePhotoAfter; + if (App::wnd()) App::wnd()->psCleanNotifyPhotosIn(-NotifyDeletePhotoAfter); + } + } else { + ToastImage v; + if (key.first) { + v.until = ms + NotifyDeletePhotoAfter; + if (App::wnd()) App::wnd()->psCleanNotifyPhotosIn(-NotifyDeletePhotoAfter); + } else { + v.until = 0; + } + v.path = cWorkingDir() + qsl("tdata/temp/") + QString::number(MTP::nonce(), 16) + qsl(".png"); + if (peer->photo->loaded() && (key.first || key.second)) { + peer->photo->pix().save(v.path, "PNG"); + } else if (!key.first && key.second) { + (peer->chat ? chatDefPhoto : userDefPhoto)(peer->colorIndex)->pix().save(v.path, "PNG"); + } else { + QFile(":/gui/art/iconbig256.png").copy(v.path); + } + i = toastImages.insert(key, v); + } + return i->path; +} + +bool CreateToast(PeerData *peer, int32 msgId, bool showpix, const QString &title, const QString &subtitle, const QString &msg) { + if (!useToast || !toastNotificationManager || !toastNotifier || !toastNotificationFactory) return false; + + ComPtr toastXml; + bool withSubtitle = !subtitle.isEmpty(); + + HRESULT hr = toastNotificationManager->GetTemplateContent(withSubtitle ? ToastTemplateType_ToastImageAndText04 : ToastTemplateType_ToastImageAndText02, &toastXml); + if (!SUCCEEDED(hr)) return false; + + hr = SetAudioSilent(toastXml.Get()); + if (!SUCCEEDED(hr)) return false; + + StorageKey key; + QString imagePath; + if (showpix) { + if (peer->photoLoc.isNull() || !peer->photo->loaded()) { + key = StorageKey(0, (peer->chat ? 0x2000 : 0x1000) | peer->colorIndex); + } else { + key = storageKey(peer->photoLoc); + } + } else { + key = StorageKey(0, 0); + } + QString image = toastImage(key, peer); + std::wstring wimage = QDir::toNativeSeparators(image).toStdWString(); + + hr = SetImageSrc(wimage.c_str(), toastXml.Get()); + if (!SUCCEEDED(hr)) return false; + + ComPtr nodeList; + hr = toastXml->GetElementsByTagName(StringReferenceWrapper(L"text").Get(), &nodeList); + if (!SUCCEEDED(hr)) return false; + + UINT32 nodeListLength; + hr = nodeList->get_Length(&nodeListLength); + if (!SUCCEEDED(hr)) return false; + + if (nodeListLength < (withSubtitle ? 3 : 2)) return false; + + { + ComPtr textNode; + hr = nodeList->Item(0, &textNode); + if (!SUCCEEDED(hr)) return false; + + std::wstring wtitle = title.toStdWString(); + hr = SetNodeValueString(StringReferenceWrapper(wtitle.data(), wtitle.size()).Get(), textNode.Get(), toastXml.Get()); + if (!SUCCEEDED(hr)) return false; + } + if (withSubtitle) { + ComPtr textNode; + hr = nodeList->Item(1, &textNode); + if (!SUCCEEDED(hr)) return false; + + std::wstring wsubtitle = subtitle.toStdWString(); + hr = SetNodeValueString(StringReferenceWrapper(wsubtitle.data(), wsubtitle.size()).Get(), textNode.Get(), toastXml.Get()); + if (!SUCCEEDED(hr)) return false; + } + { + ComPtr textNode; + hr = nodeList->Item(withSubtitle ? 2 : 1, &textNode); + if (!SUCCEEDED(hr)) return false; + + std::wstring wmsg = msg.toStdWString(); + hr = SetNodeValueString(StringReferenceWrapper(wmsg.data(), wmsg.size()).Get(), textNode.Get(), toastXml.Get()); + if (!SUCCEEDED(hr)) return false; + } + + ComPtr toast; + hr = toastNotificationFactory->CreateToastNotification(toastXml.Get(), &toast); + if (!SUCCEEDED(hr)) return false; + + EventRegistrationToken activatedToken, dismissedToken, failedToken; + ComPtr eventHandler(new ToastEventHandler(peer->id, msgId)); + + hr = toast->add_Activated(eventHandler.Get(), &activatedToken); + if (!SUCCEEDED(hr)) return false; + + hr = toast->add_Dismissed(eventHandler.Get(), &dismissedToken); + if (!SUCCEEDED(hr)) return false; + + hr = toast->add_Failed(eventHandler.Get(), &failedToken); + if (!SUCCEEDED(hr)) return false; + + ToastNotifications::iterator i = toastNotifications.find(peer->id); + if (i == toastNotifications.cend()) { + i = toastNotifications.insert(peer->id, QMap()); + } else { + QMap::iterator j = i->find(msgId); + if (j != i->cend()) { + toastNotifier->Hide(j->p.Get()); + i->erase(j); + if (i->isEmpty()) { + toastNotifications.erase(i); + } + } + } + hr = toastNotifier->Show(toast.Get()); + if (!SUCCEEDED(hr)) { + if (i->isEmpty()) toastNotifications.erase(i); + return false; + } + i->insert(msgId, toast); + + return true; +} + +QString systemShortcutPath() { + static const int maxFileLen = MAX_PATH * 10; + WCHAR wstrPath[maxFileLen]; + if (GetEnvironmentVariable(L"APPDATA", wstrPath, maxFileLen)) { + QDir appData(QString::fromStdWString(std::wstring(wstrPath))); + return appData.absolutePath() + qsl("/Microsoft/Windows/Start Menu/Programs/"); + } + return QString(); +} + +void CleanupAppUserModelIdShortcut() { + static const int maxFileLen = MAX_PATH * 10; + + QString path = systemShortcutPath() + qsl("Telegram.lnk"); + std::wstring p = QDir::toNativeSeparators(path).toStdWString(); + + DWORD attributes = GetFileAttributes(p.c_str()); + if (attributes >= 0xFFFFFFF) return; // file does not exist + + ComPtr shellLink; + HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)); + if (!SUCCEEDED(hr)) return; + + ComPtr persistFile; + hr = shellLink.As(&persistFile); + if (!SUCCEEDED(hr)) return; + + hr = persistFile->Load(p.c_str(), STGM_READWRITE); + if (!SUCCEEDED(hr)) return; + + WCHAR szGotPath[MAX_PATH]; + WIN32_FIND_DATA wfd; + hr = shellLink->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATA*)&wfd, SLGP_SHORTPATH); + if (!SUCCEEDED(hr)) return; + + if (QDir::toNativeSeparators(cExeDir() + cExeName()).toStdWString() == szGotPath) { + QFile().remove(path); + } +} + +bool ValidateAppUserModelIdShortcutAt(const QString &path) { + static const int maxFileLen = MAX_PATH * 10; + + std::wstring p = QDir::toNativeSeparators(path).toStdWString(); + + DWORD attributes = GetFileAttributes(p.c_str()); + if (attributes >= 0xFFFFFFF) return false; // file does not exist + + ComPtr shellLink; + HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)); + if (!SUCCEEDED(hr)) return false; + + ComPtr persistFile; + hr = shellLink.As(&persistFile); + if (!SUCCEEDED(hr)) return false; + + hr = persistFile->Load(p.c_str(), STGM_READWRITE); + if (!SUCCEEDED(hr)) return false; + + ComPtr propertyStore; + hr = shellLink.As(&propertyStore); + if (!SUCCEEDED(hr)) return false; + + PROPVARIANT appIdPropVar; + hr = propertyStore->GetValue(pkey_AppUserModel_ID, &appIdPropVar); + if (!SUCCEEDED(hr)) return false; + + WCHAR already[MAX_PATH]; + hr = propVariantToString(appIdPropVar, already, MAX_PATH); + if (SUCCEEDED(hr)) { + if (std::wstring(AppUserModelId) == already) { + PropVariantClear(&appIdPropVar); + return true; + } + } + if (appIdPropVar.vt != VT_EMPTY) { + PropVariantClear(&appIdPropVar); + return false; + } + PropVariantClear(&appIdPropVar); + + hr = InitPropVariantFromString(AppUserModelId, &appIdPropVar); + if (!SUCCEEDED(hr)) return false; + + hr = propertyStore->SetValue(pkey_AppUserModel_ID, appIdPropVar); + PropVariantClear(&appIdPropVar); + if (!SUCCEEDED(hr)) return false; + + hr = propertyStore->Commit(); + if (!SUCCEEDED(hr)) return false; + + if (persistFile->IsDirty() == S_OK) { + persistFile->Save(p.c_str(), TRUE); + } + + return true; +} + +bool ValidateAppUserModelIdShortcut() { + if (!useToast) return false; + + QString path = systemShortcutPath(); + if (path.isEmpty()) return false; + + if (ValidateAppUserModelIdShortcutAt(path + qsl("Telegram Desktop/Telegram.lnk"))) return true; + if (ValidateAppUserModelIdShortcutAt(path + qsl("Telegram Win (Unofficial)/Telegram.lnk"))) return true; + + path += qsl("Telegram.lnk"); + if (ValidateAppUserModelIdShortcutAt(path)) return true; + + ComPtr shellLink; + HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)); + if (!SUCCEEDED(hr)) return false; + + hr = shellLink->SetPath(QDir::toNativeSeparators(cExeDir() + cExeName()).toStdWString().c_str()); + if (!SUCCEEDED(hr)) return false; + + hr = shellLink->SetArguments(L""); + if (!SUCCEEDED(hr)) return false; + + hr = shellLink->SetWorkingDirectory(QDir::toNativeSeparators(QDir(cWorkingDir()).absolutePath()).toStdWString().c_str()); + if (!SUCCEEDED(hr)) return false; + + ComPtr propertyStore; + hr = shellLink.As(&propertyStore); + if (!SUCCEEDED(hr)) return false; + + PROPVARIANT appIdPropVar; + hr = InitPropVariantFromString(AppUserModelId, &appIdPropVar); + if (!SUCCEEDED(hr)) return false; + + hr = propertyStore->SetValue(pkey_AppUserModel_ID, appIdPropVar); + PropVariantClear(&appIdPropVar); + if (!SUCCEEDED(hr)) return false; + + PROPVARIANT startPinPropVar; + hr = InitPropVariantFromUInt32(APPUSERMODEL_STARTPINOPTION_NOPINONINSTALL, &startPinPropVar); + if (!SUCCEEDED(hr)) return false; + + hr = propertyStore->SetValue(pkey_AppUserModel_StartPinOption, startPinPropVar); + PropVariantClear(&startPinPropVar); + if (!SUCCEEDED(hr)) return false; + + hr = propertyStore->Commit(); + if (!SUCCEEDED(hr)) return false; + + ComPtr persistFile; + hr = shellLink.As(&persistFile); + if (!SUCCEEDED(hr)) return false; + + hr = persistFile->Save(QDir::toNativeSeparators(path).toStdWString().c_str(), TRUE); + if (!SUCCEEDED(hr)) return false; + + return true; +} + +bool InitToastManager() { + if (!useToast || !ValidateAppUserModelIdShortcut()) return false; + + if (!SUCCEEDED(setCurrentProcessExplicitAppUserModelID(AppUserModelId))) { + return false; + } + if (!SUCCEEDED(wrap_GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &toastNotificationManager))) { + return false; + } + if (!SUCCEEDED(toastNotificationManager->CreateToastNotifierWithId(StringReferenceWrapper(AppUserModelId).Get(), &toastNotifier))) { + return false; + } + if (!SUCCEEDED(wrap_GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &toastNotificationFactory))) { + return false; + } + QDir().mkpath(cWorkingDir() + qsl("tdata/temp")); + return true; +} diff --git a/Telegram/SourceFiles/pspecific_wnd.h b/Telegram/SourceFiles/pspecific_wnd.h index 6e8040b23..bf07c1c1a 100644 --- a/Telegram/SourceFiles/pspecific_wnd.h +++ b/Telegram/SourceFiles/pspecific_wnd.h @@ -67,6 +67,9 @@ public: void psUpdateCounter(); + bool psHasNativeNotifications(); + void psCleanNotifyPhotosIn(int32 dt); + virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0; ~PsMainWindow(); @@ -77,6 +80,8 @@ public slots: void psSavePosition(Qt::WindowState state = Qt::WindowActive); void psShowTrayMenu(); + void psCleanNotifyPhotos(); + protected: bool psHasTrayIcon() const { @@ -100,6 +105,8 @@ private: HMENU ps_menu; HICON ps_iconBig, ps_iconSmall, ps_iconOverlay; + SingleTimer ps_cleanNotifyPhotosTimer; + void psDestroyIcons(); }; diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index a9a61afba..da839b676 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -42,6 +42,7 @@ QString gDialogLastPath, gDialogHelperPath; // optimize QFileDialog bool gSoundNotify = true; bool gDesktopNotify = true; DBINotifyView gNotifyView = dbinvShowPreview; +bool gWindowsNotifications = true; bool gStartMinimized = false; bool gStartInTray = false; bool gAutoStart = false; @@ -119,11 +120,7 @@ QString gLangFile; bool gRetina = false; float64 gRetinaFactor = 1.; int32 gIntRetinaFactor = 1; -#ifdef Q_OS_MAC -bool gCustomNotifies = false; -#else bool gCustomNotifies = true; -#endif uint64 gInstance = 0.; #ifdef Q_OS_WIN @@ -163,7 +160,6 @@ SavedPeers gSavedPeers; SavedPeersByTime gSavedPeersByTime; void settingsParseArgs(int argc, char *argv[]) { - gCustomNotifies = true; #ifdef Q_OS_MAC if (QSysInfo::macVersion() < QSysInfo::MV_10_8) { gUpdateURL = QUrl(qsl("http://tdesktop.com/mac32/tupdates/current")); diff --git a/Telegram/SourceFiles/settings.h b/Telegram/SourceFiles/settings.h index f5b577fbf..47c9a3610 100644 --- a/Telegram/SourceFiles/settings.h +++ b/Telegram/SourceFiles/settings.h @@ -101,6 +101,8 @@ DeclareSetting(bool, DesktopNotify); DeclareSetting(DBINotifyView, NotifyView); DeclareSetting(bool, AutoUpdate); +DeclareSetting(bool, WindowsNotifications); + struct TWindowPos { TWindowPos() : moncrc(0), maximized(0), x(0), y(0), w(0), h(0) { } diff --git a/Telegram/SourceFiles/settingswidget.cpp b/Telegram/SourceFiles/settingswidget.cpp index 641eb499d..d272122ed 100644 --- a/Telegram/SourceFiles/settingswidget.cpp +++ b/Telegram/SourceFiles/settingswidget.cpp @@ -122,6 +122,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), _desktopNotify(this, lang(lng_settings_desktop_notify), cDesktopNotify()), _senderName(this, lang(lng_settings_show_name), cNotifyView() <= dbinvShowName), _messagePreview(this, lang(lng_settings_show_preview), cNotifyView() <= dbinvShowPreview), + _windowsNotifications(this, lang(lng_settings_use_windows), cWindowsNotifications()), _soundNotify(this, lang(lng_settings_sound_notify), cSoundNotify()), // general @@ -186,7 +187,10 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), _connectionTypeText(lang(lng_connection_type) + ' '), _connectionTypeWidth(st::linkFont->m.width(_connectionTypeText)), _showSessions(this, lang(lng_settings_show_sessions)), - _logOut(this, lang(lng_settings_logout), st::btnLogout) + _askQuestion(this, lang(lng_settings_ask_question)), + _telegramFAQ(this, lang(lng_settings_faq)), + _logOut(this, lang(lng_settings_logout), st::btnLogout), + _supportGetRequest(0) { if (self()) { _nameText.setText(st::setNameFont, _nameCache, _textNameOptions); @@ -217,6 +221,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), connect(&_desktopNotify, SIGNAL(changed()), this, SLOT(onDesktopNotify())); connect(&_senderName, SIGNAL(changed()), this, SLOT(onSenderName())); connect(&_messagePreview, SIGNAL(changed()), this, SLOT(onMessagePreview())); + connect(&_windowsNotifications, SIGNAL(changed()), this, SLOT(onWindowsNotifications())); connect(&_soundNotify, SIGNAL(changed()), this, SLOT(onSoundNotify())); // general @@ -288,6 +293,8 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), connect(&_passwordTurnOff, SIGNAL(clicked()), this, SLOT(onPasswordOff())); connect(&_connectionType, SIGNAL(clicked()), this, SLOT(onConnectionType())); connect(&_showSessions, SIGNAL(clicked()), this, SLOT(onShowSessions())); + connect(&_askQuestion, SIGNAL(clicked()), this, SLOT(onAskQuestion())); + connect(&_telegramFAQ, SIGNAL(clicked()), this, SLOT(onTelegramFAQ())); connect(&_logOut, SIGNAL(clicked()), App::wnd(), SLOT(onLogout())); if (App::main()) { @@ -411,6 +418,9 @@ void SettingsInner::paintEvent(QPaintEvent *e) { top += _desktopNotify.height() + st::setLittleSkip; top += _senderName.height() + st::setLittleSkip; top += _messagePreview.height() + st::setSectionSkip; + if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) { + top += _windowsNotifications.height() + st::setSectionSkip; + } top += _soundNotify.height(); } @@ -637,6 +647,9 @@ void SettingsInner::resizeEvent(QResizeEvent *e) { _desktopNotify.move(_left, top); top += _desktopNotify.height() + st::setLittleSkip; _senderName.move(_left, top); top += _senderName.height() + st::setLittleSkip; _messagePreview.move(_left, top); top += _messagePreview.height() + st::setSectionSkip; + if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) { + _windowsNotifications.move(_left, top); top += _windowsNotifications.height() + st::setSectionSkip; + } _soundNotify.move(_left, top); top += _soundNotify.height(); } @@ -719,7 +732,12 @@ void SettingsInner::resizeEvent(QResizeEvent *e) { _connectionType.move(_left + _connectionTypeWidth, top); top += _connectionType.height() + st::setLittleSkip; if (self()) { _showSessions.move(_left, top); top += _showSessions.height() + st::setSectionSkip; + _askQuestion.move(_left, top); top += _askQuestion.height() + st::setLittleSkip; + _telegramFAQ.move(_left, top); top += _telegramFAQ.height() + st::setSectionSkip; _logOut.move(_left, top); + } else { + top += st::setSectionSkip - st::setLittleSkip; + _telegramFAQ.move(_left, top); } } @@ -810,7 +828,7 @@ bool SettingsInner::animStep(float64 ms) { void SettingsInner::updateSize(int32 newWidth) { if (_logOut.isHidden()) { - resize(newWidth, _connectionType.geometry().bottom() + st::setBottom); + resize(newWidth, _telegramFAQ.geometry().bottom() + st::setBottom); } else { resize(newWidth, _logOut.geometry().bottom() + st::setBottom); } @@ -936,11 +954,17 @@ void SettingsInner::showAll() { _desktopNotify.show(); _senderName.show(); _messagePreview.show(); + if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) { + _windowsNotifications.show(); + } else { + _windowsNotifications.hide(); + } _soundNotify.show(); } else { _desktopNotify.hide(); _senderName.hide(); _messagePreview.hide(); + _windowsNotifications.hide(); _soundNotify.hide(); } @@ -1049,6 +1073,7 @@ void SettingsInner::showAll() { _passwordTurnOff.show(); } _showSessions.show(); + _askQuestion.show(); _logOut.show(); } else { _passcodeEdit.hide(); @@ -1057,8 +1082,10 @@ void SettingsInner::showAll() { _passwordEdit.hide(); _passwordTurnOff.hide(); _showSessions.hide(); + _askQuestion.hide(); _logOut.hide(); } + _telegramFAQ.show(); } void SettingsInner::saveError(const QString &str) { @@ -1067,6 +1094,17 @@ void SettingsInner::saveError(const QString &str) { update(); } +void SettingsInner::supportGot(const MTPhelp_Support &support) { + if (!App::main()) return; + + if (support.type() == mtpc_help_support) { + const MTPDhelp_support &d(support.c_help_support()); + UserData *u = App::feedUsers(MTP_vector(1, d.vuser)); + App::main()->showPeerHistory(u->id, ShowAtUnreadMsgId); + App::wnd()->hideSettings(); + } +} + void SettingsInner::onUpdatePhotoCancel() { if (self()) { App::app()->cancelPhotoUpdate(self()->id); @@ -1110,6 +1148,25 @@ void SettingsInner::onShowSessions() { App::wnd()->showLayer(box); } +void SettingsInner::onAskQuestion() { + if (!App::self()) return; + + ConfirmBox *box = new ConfirmBox(lang(lng_settings_ask_sure), lang(lng_settings_ask_ok), lang(lng_settings_faq_button)); + connect(box, SIGNAL(confirmed()), this, SLOT(onAskQuestionSure())); + connect(box, SIGNAL(cancelPressed()), this, SLOT(onTelegramFAQ())); + App::wnd()->showLayer(box); +} + +void SettingsInner::onAskQuestionSure() { + if (_supportGetRequest) return; + _supportGetRequest = MTP::send(MTPhelp_GetSupport(), rpcDone(&SettingsInner::supportGot)); +} + +void SettingsInner::onTelegramFAQ() { + App::wnd()->hideLayer(); + QDesktopServices::openUrl(qsl("https://telegram.org/faq#general")); +} + void SettingsInner::onChangeLanguage() { if ((_changeLanguage.clickModifiers() & Qt::ShiftModifier) && (_changeLanguage.clickModifiers() & Qt::AltModifier)) { QString file; @@ -1349,6 +1406,13 @@ void SettingsInner::onSoundNotify() { Local::writeUserSettings(); } +void SettingsInner::onWindowsNotifications() { + cSetWindowsNotifications(!cWindowsNotifications()); + App::wnd()->notifyClearFast(); + cSetCustomNotifies(!cWindowsNotifications()); + Local::writeUserSettings(); +} + void SettingsInner::onDesktopNotify() { cSetDesktopNotify(_desktopNotify.checked()); if (!_desktopNotify.checked()) { diff --git a/Telegram/SourceFiles/settingswidget.h b/Telegram/SourceFiles/settingswidget.h index 1de46a36c..540c6f6c3 100644 --- a/Telegram/SourceFiles/settingswidget.h +++ b/Telegram/SourceFiles/settingswidget.h @@ -125,6 +125,8 @@ public slots: void onSenderName(); void onMessagePreview(); + void onWindowsNotifications(); + void onReplaceEmojis(); void onViewEmojis(); @@ -162,10 +164,16 @@ public slots: void onUpdateLocalStorage(); + void onAskQuestion(); + void onAskQuestionSure(); + void onTelegramFAQ(); + private: void saveError(const QString &str = QString()); + void supportGot(const MTPhelp_Support &support); + void setScale(DBIScale newScale); QString _testlang, _secretText; @@ -192,7 +200,7 @@ private: LinkButton _chooseUsername; // notifications - FlatCheckbox _desktopNotify, _senderName, _messagePreview, _soundNotify; + FlatCheckbox _desktopNotify, _senderName, _messagePreview, _windowsNotifications, _soundNotify; // general LinkButton _changeLanguage; @@ -261,9 +269,11 @@ private: LinkButton _connectionType; QString _connectionTypeText; int32 _connectionTypeWidth; - LinkButton _showSessions; + LinkButton _showSessions, _askQuestion, _telegramFAQ; FlatButton _logOut; + mtpRequestId _supportGetRequest; + void gotPassword(const MTPaccount_Password &result); void offPasswordDone(const MTPBool &result); bool offPasswordFail(const RPCError &error); diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 080b346af..86885d11e 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -404,7 +404,7 @@ QString saveFileName(const QString &title, const QString &filter, const QString void VideoOpenLink::onClick(Qt::MouseButton button) const { VideoData *data = video(); - if ((!data->user && !data->date) || button != Qt::LeftButton) return; + if (!data->date || button != Qt::LeftButton) return; QString already = data->already(true); if (!already.isEmpty()) { @@ -424,7 +424,7 @@ void VideoOpenLink::onClick(Qt::MouseButton button) const { } void VideoSaveLink::doSave(VideoData *data, bool forceSavingAs) { - if (!data->user && !data->date) return; + if (!data->date) return; QString already = data->already(true); if (!already.isEmpty() && !forceSavingAs) { @@ -456,13 +456,13 @@ void VideoSaveLink::onClick(Qt::MouseButton button) const { void VideoCancelLink::onClick(Qt::MouseButton button) const { VideoData *data = video(); - if ((!data->user && !data->date) || button != Qt::LeftButton) return; + if (!data->date || button != Qt::LeftButton) return; data->cancel(); } -VideoData::VideoData(const VideoId &id, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) : -id(id), access(access), user(user), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), openOnSaveMsgId(0), loader(0) { +VideoData::VideoData(const VideoId &id, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) : +id(id), access(access), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), openOnSaveMsgId(0), loader(0) { location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id)); } @@ -482,7 +482,7 @@ QString VideoData::already(bool check) { void AudioOpenLink::onClick(Qt::MouseButton button) const { AudioData *data = audio(); - if ((!data->user && !data->date) || button != Qt::LeftButton) return; + if (!data->date || button != Qt::LeftButton) return; QString already = data->already(true); bool play = App::hoveredLinkItem() && audioPlayer(); @@ -516,7 +516,7 @@ void AudioOpenLink::onClick(Qt::MouseButton button) const { } void AudioSaveLink::doSave(AudioData *data, bool forceSavingAs) { - if (!data->user && !data->date) return; + if (!data->date) return; QString already = data->already(true); if (!already.isEmpty() && !forceSavingAs) { @@ -549,7 +549,7 @@ void AudioSaveLink::onClick(Qt::MouseButton button) const { void AudioCancelLink::onClick(Qt::MouseButton button) const { AudioData *data = audio(); - if ((!data->user && !data->date) || button != Qt::LeftButton) return; + if (!data->date || button != Qt::LeftButton) return; data->cancel(); } @@ -569,8 +569,8 @@ bool StickerData::setInstalled() const { return false; } -AudioData::AudioData(const AudioId &id, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) : -id(id), access(access), user(user), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) { +AudioData::AudioData(const AudioId &id, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) : +id(id), access(access), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) { location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id)); } diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index 6bcdd6c5c..bbc1b41b3 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -167,9 +167,15 @@ struct BotInfo { QString startToken, startGroupToken; }; +enum UserBlockedStatus { + UserBlockUnknown = 0, + UserIsBlocked, + UserIsNotBlocked, +}; + struct PhotoData; struct UserData : public PeerData { - UserData(const PeerId &id) : PeerData(id), access(0), lnk(new PeerLink(this)), onlineTill(0), contact(-1), photosCount(-1), botInfo(0) { + UserData(const PeerId &id) : PeerData(id), access(0), lnk(new PeerLink(this)), onlineTill(0), contact(-1), blocked(UserBlockUnknown), photosCount(-1), botInfo(0) { } void setPhoto(const MTPUserProfilePhoto &photo); void setName(const QString &first, const QString &last, const QString &phoneName, const QString &username); @@ -192,6 +198,7 @@ struct UserData : public PeerData { TextLinkPtr lnk; int32 onlineTill; int32 contact; // -1 - not contact, cant add (self, empty, deleted, foreign), 0 - not contact, can add (request), 1 - contact + UserBlockedStatus blocked; typedef QList Photos; Photos photos; @@ -230,8 +237,8 @@ inline int32 newMessageFlags(PeerData *p) { typedef QMap PreparedPhotoThumbs; struct PhotoData { - PhotoData(const PhotoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) : - id(id), access(access), user(user), date(date), thumb(thumb), medium(medium), full(full), chat(0) { + PhotoData(const PhotoId &id, const uint64 &access = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) : + id(id), access(access), date(date), thumb(thumb), medium(medium), full(full), chat(0) { } void forget() { thumb->forget(); @@ -254,7 +261,6 @@ struct PhotoData { } PhotoId id; uint64 access; - int32 user; int32 date; ImagePtr thumb, replyPreview; ImagePtr medium; @@ -294,7 +300,7 @@ enum FileStatus { }; struct VideoData { - VideoData(const VideoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0); + VideoData(const VideoId &id, const uint64 &access = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0); void forget() { thumb->forget(); @@ -330,7 +336,6 @@ struct VideoData { VideoId id; uint64 access; - int32 user; int32 date; int32 duration; int32 w, h; @@ -390,7 +395,7 @@ public: }; struct AudioData { - AudioData(const AudioId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0); + AudioData(const AudioId &id, const uint64 &access = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0); void forget() { } @@ -425,7 +430,6 @@ struct AudioData { AudioId id; uint64 access; - int32 user; int32 date; QString mime; int32 duration; diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h index 5d8ee7a0e..976f40085 100644 --- a/Telegram/SourceFiles/types.h +++ b/Telegram/SourceFiles/types.h @@ -232,55 +232,56 @@ QString translitRusEng(const QString &rus); QString rusKeyboardLayoutSwitch(const QString &from); enum DataBlockId { - dbiKey = 0x00, - dbiUser = 0x01, - dbiDcOptionOld = 0x02, - dbiMaxGroupCount = 0x03, - dbiMutePeer = 0x04, - dbiSendKey = 0x05, - dbiAutoStart = 0x06, - dbiStartMinimized = 0x07, - dbiSoundNotify = 0x08, - dbiWorkMode = 0x09, - dbiSeenTrayTooltip = 0x0a, - dbiDesktopNotify = 0x0b, - dbiAutoUpdate = 0x0c, - dbiLastUpdateCheck = 0x0d, - dbiWindowPosition = 0x0e, - dbiConnectionType = 0x0f, + dbiKey = 0x00, + dbiUser = 0x01, + dbiDcOptionOld = 0x02, + dbiMaxGroupCount = 0x03, + dbiMutePeer = 0x04, + dbiSendKey = 0x05, + dbiAutoStart = 0x06, + dbiStartMinimized = 0x07, + dbiSoundNotify = 0x08, + dbiWorkMode = 0x09, + dbiSeenTrayTooltip = 0x0a, + dbiDesktopNotify = 0x0b, + dbiAutoUpdate = 0x0c, + dbiLastUpdateCheck = 0x0d, + dbiWindowPosition = 0x0e, + dbiConnectionType = 0x0f, // 0x10 reserved - dbiDefaultAttach = 0x11, - dbiCatsAndDogs = 0x12, - dbiReplaceEmojis = 0x13, - dbiAskDownloadPath = 0x14, - dbiDownloadPath = 0x15, - dbiScale = 0x16, - dbiEmojiTab = 0x17, - dbiRecentEmojisOld = 0x18, - dbiLoggedPhoneNumber = 0x19, - dbiMutedPeers = 0x1a, + dbiDefaultAttach = 0x11, + dbiCatsAndDogs = 0x12, + dbiReplaceEmojis = 0x13, + dbiAskDownloadPath = 0x14, + dbiDownloadPath = 0x15, + dbiScale = 0x16, + dbiEmojiTab = 0x17, + dbiRecentEmojisOld = 0x18, + dbiLoggedPhoneNumber = 0x19, + dbiMutedPeers = 0x1a, // 0x1b reserved - dbiNotifyView = 0x1c, - dbiSendToMenu = 0x1d, - dbiCompressPastedImage = 0x1e, - dbiLang = 0x1f, - dbiLangFile = 0x20, - dbiTileBackground = 0x21, - dbiAutoLock = 0x22, - dbiDialogLastPath = 0x23, - dbiRecentEmojis = 0x24, - dbiEmojiVariants = 0x25, - dbiRecentStickers = 0x26, - dbiDcOption = 0x27, - dbiTryIPv6 = 0x28, - dbiSongVolume = 0x29, + dbiNotifyView = 0x1c, + dbiSendToMenu = 0x1d, + dbiCompressPastedImage = 0x1e, + dbiLang = 0x1f, + dbiLangFile = 0x20, + dbiTileBackground = 0x21, + dbiAutoLock = 0x22, + dbiDialogLastPath = 0x23, + dbiRecentEmojis = 0x24, + dbiEmojiVariants = 0x25, + dbiRecentStickers = 0x26, + dbiDcOption = 0x27, + dbiTryIPv6 = 0x28, + dbiSongVolume = 0x29, + dbiWindowsNotifications = 0x30, - dbiEncryptedWithSalt = 333, - dbiEncrypted = 444, + dbiEncryptedWithSalt = 333, + dbiEncrypted = 444, // 500-600 reserved - dbiVersion = 666, + dbiVersion = 666, }; enum DBISendKey { diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist index e397d0312..0e5abe0cb 100644 --- a/Telegram/Telegram.plist +++ b/Telegram/Telegram.plist @@ -11,7 +11,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.8.48 + 0.8.49 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) CFBundleSignature diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc index 6be096038..251f2edd5 100644 Binary files a/Telegram/Telegram.rc and b/Telegram/Telegram.rc differ diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index 80b18b34f..7f02c5851 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -54,14 +54,17 @@ $(SolutionDir)$(Platform)\$(Configuration)Intermediate\ + $(VC_IncludePath);$(WindowsSDK_IncludePath); $(SolutionDir)$(Platform)\$(Configuration)\ $(SolutionDir)$(Platform)\$(Configuration)Intermediate\ + $(VC_IncludePath);$(WindowsSDK_IncludePath); $(SolutionDir)$(Platform)\$(Configuration)\ $(SolutionDir)$(Platform)\$(Configuration)Intermediate\ + $(VC_IncludePath);$(WindowsSDK_IncludePath); @@ -80,7 +83,7 @@ Windows $(OutDir)$(ProjectName).exe .\..\..\Libraries\lzma\C\Util\LzmaLib\Debug;.\..\..\Libraries\libexif-0.6.20\win32\Debug;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Debug;.\..\..\Libraries\openal-soft\build\Debug;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatDebug;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories) - kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmaind.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Cored.lib;Qt5Guid.lib;qtharfbuzzngd.lib;qtpcred.lib;qtfreetyped.lib;Qt5Widgetsd.lib;Qt5Networkd.lib;Qt5PlatformSupportd.lib;platforms\qwindowsd.lib;imageformats\qwebpd.lib;libeay32MTd.lib;ssleay32MTd.lib;Crypt32.lib;zlibstat.lib;LzmaLib.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmaind.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Cored.lib;Qt5Guid.lib;qtharfbuzzngd.lib;qtpcred.lib;qtfreetyped.lib;Qt5Widgetsd.lib;Qt5Networkd.lib;Qt5PlatformSupportd.lib;platforms\qwindowsd.lib;imageformats\qwebpd.lib;libeay32MTd.lib;ssleay32MTd.lib;Crypt32.lib;zlibstat.lib;LzmaLib.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies) true LIBCMT @@ -108,7 +111,7 @@ Windows $(OutDir)$(ProjectName).exe .\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories) - kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies) $(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib $(IntDir)$(TargetName).pgd @@ -136,7 +139,7 @@ Windows $(OutDir)$(ProjectName).exe .\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories) - kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies) $(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj index acf18ab7f..681fafc96 100644 --- a/Telegram/Telegram.xcodeproj/project.pbxproj +++ b/Telegram/Telegram.xcodeproj/project.pbxproj @@ -1707,7 +1707,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.8.48; + CURRENT_PROJECT_VERSION = 0.8.49; DEBUG_INFORMATION_FORMAT = dwarf; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -1725,7 +1725,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 0.8.48; + CURRENT_PROJECT_VERSION = 0.8.49; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = fast; GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h; @@ -1751,10 +1751,10 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.8.48; + CURRENT_PROJECT_VERSION = 0.8.49; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 0.8; - DYLIB_CURRENT_VERSION = 0.8.48; + DYLIB_CURRENT_VERSION = 0.8.49; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; @@ -1885,10 +1885,10 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.8.48; + CURRENT_PROJECT_VERSION = 0.8.49; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 0.8; - DYLIB_CURRENT_VERSION = 0.8.48; + DYLIB_CURRENT_VERSION = 0.8.49; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; diff --git a/Telegram/Version.sh b/Telegram/Version.sh index 89b3f7622..deafb9a75 100755 --- a/Telegram/Version.sh +++ b/Telegram/Version.sh @@ -1,2 +1,2 @@ -echo 0.8 8048 0.8.48 0 +echo 0.8 8049 0.8.49 1 # AppVersionStrMajor AppVersion AppVersionStr DevChannel