diff --git a/Telegram/PrepareMac.sh b/Telegram/PrepareMac.sh index 584bd442e..0a12cf5aa 100755 --- a/Telegram/PrepareMac.sh +++ b/Telegram/PrepareMac.sh @@ -92,5 +92,6 @@ rm ./../Mac/Release/Telegram.app/Contents/Frameworks/Updater rm -rf ./../Mac/Release/Telegram.app/Contents/_CodeSignature mv ./../Mac/Release/tmacupd$AppVersion ./../Mac/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/ mv ./../Mac/Release/tsetup.$AppVersionStr$DevPostfix.dmg ./../Mac/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tsetup.$AppVersionStr$DevPostfix.dmg + echo "Version $AppVersionStr$DevPostfix prepared!"; diff --git a/Telegram/PrepareWin.bat b/Telegram/PrepareWin.bat index 2e28a555b..7fec83b31 100644 --- a/Telegram/PrepareWin.bat +++ b/Telegram/PrepareWin.bat @@ -1,10 +1,10 @@ @echo OFF set "AppVersionStrMajor=0.8" -set "AppVersion=8051" -set "AppVersionStrSmall=0.8.51" -set "AppVersionStr=0.8.51" -set "AppVersionStrFull=0.8.51.0" +set "AppVersion=8055" +set "AppVersionStrSmall=0.8.55" +set "AppVersionStr=0.8.55" +set "AppVersionStrFull=0.8.55.0" set "DevChannel=0" if %DevChannel% neq 0 goto preparedev diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings index eb93c89ae..23fdd7453 100644 --- a/Telegram/Resources/lang.strings +++ b/Telegram/Resources/lang.strings @@ -60,6 +60,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_weekday7_full" = "Sunday"; "lng_month_day" = "{month} {day}"; +"lng_month_day_year" = "{month} {day}, {year}"; "lng_cancel" = "Cancel"; "lng_continue" = "Continue"; @@ -117,6 +118,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_code_ph" = "Your code"; "lng_code_desc" = "We have sent you a message with activation\ncode to your phone. Please enter it below."; +"lng_code_telegram" = "Please enter the code you've just\nreceived in your previous [b]Telegram[/b] app."; +"lng_code_no_telegram" = "Send code via SMS"; "lng_code_call" = "Telegram will dial your number in {minutes}:{seconds}"; "lng_code_calling" = "Requesting a call from Telegram.."; "lng_code_called" = "Telegram dialed your number"; @@ -188,6 +191,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_show_preview" = "Show message preview"; "lng_settings_use_windows" = "Use Windows notifications"; "lng_settings_sound_notify" = "Play sound"; +"lng_settings_include_muted" = "Include muted chats in unread count"; "lng_notification_preview" = "You have a new message"; @@ -386,6 +390,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_profile_files_header" = "Files overview"; "lng_profile_audios" = "{count:_not_used_|# voice message|# voice messages} »"; "lng_profile_audios_header" = "Voice messages overview"; +"lng_profile_shared_links" = "{count:_not_used_|# shared link|# shared links} »"; +"lng_profile_shared_links_header" = "Shared links overview"; "lng_profile_audio_files_header" = "Playlist"; "lng_profile_show_all_types" = "Show all types"; "lng_profile_copy_phone" = "Copy phone number"; @@ -443,6 +449,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_media_type_videos" = "Video files"; "lng_media_type_files" = "Files"; "lng_media_type_audios" = "Voice messages"; +"lng_media_type_links" = "Shared links"; "lng_media_open_with" = "Open With"; "lng_media_download" = "Download"; @@ -641,7 +648,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}"; "lng_new_version_minor" = "— Bug fixes and other minor improvements"; -"lng_new_version_text" = "— Block users from their profile page\n— Added support for Windows toast notifications\n— Fixed input methods on Linux (Fcitx and IBus)"; +"lng_new_version_text" = "— Include muted chats in unread count in Settings\n— Shared links overview and search in shared media\n— Preview when sending links to GIF animations and PDF files"; "lng_menu_insert_unicode" = "Insert Unicode control character"; diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index 62e6cccc9..b684c2d93 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -374,6 +374,10 @@ introHeaderFont: font(24px); introHeaderSkip: 14px; introIconSkip: 54px; introFont: font(16px); +introLink: linkButton(btnDefLink) { + font: introFont; + overFont: font(16px underline); +} introColor: black; introLabel: flatLabel(labelDefFlat) { font: introFont; @@ -1485,6 +1489,10 @@ dropdownMediaAudios: iconedButton(dropdownMediaDocuments) { icon: sprite(62px, 348px, 24px, 24px); downIcon: sprite(62px, 348px, 24px, 24px); } +dropdownMediaLinks: iconedButton(dropdownMediaDocuments) { + icon: sprite(372px, 414px, 24px, 24px); + downIcon: sprite(62px, 348px, 24px, 24px); +} dragFont: font(28px semibold); dragSubfont: font(20px semibold); @@ -2036,3 +2044,15 @@ playerDuration: 200; playlistHoverBg: #f2f2f2; playlistPadding: 10px; + +linksSearchMargin: margins(20px, 20px, 20px, 0px); +linksMaxWidth: 520px; +linksLetterFont: font(24px); +linksMargin: 5px; +linksBorder: 1px; +linksBorderColor: #eaeaea; +linksDateColor: #000; +linksDateMargin: 15px; + +linksPhotoCheck: sprite(184px, 196px, 16px, 16px); +linksPhotoChecked: sprite(168px, 196px, 16px, 16px); diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 1a31593ba..3c0016f48 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -70,6 +70,9 @@ namespace { typedef QMap > RepliesTo; RepliesTo repliesTo; + typedef QMap SharedContactPhones; + SharedContactPhones sharedContactPhones; + Histories histories; typedef QHash MsgsData; @@ -79,6 +82,9 @@ namespace { typedef QMap RandomData; RandomData randomData; + typedef QMap SentTextData; + SentTextData sentTextData; + HistoryItem *hoveredItem = 0, *pressedItem = 0, *hoveredLinkItem = 0, *pressedLinkItem = 0, *contextItem = 0, *mousedItem = 0; QPixmap *sprite = 0, *emojis = 0, *emojisLarge = 0; @@ -523,26 +529,6 @@ namespace App { data->left = false; data->forbidden = true; } break; - case mtpc_geoChat: { - const MTPDgeoChat &d(chat.c_geoChat()); - data = 0; -/* title = qs(d.vtitle); - - PeerId peer(peerFromChat(d.vid.v)); - data = App::chat(peer); - data->input = MTP_inputPeerChat(d.vid); - data->setPhoto(d.vphoto); - data->date = d.vdate.v; - data->count = d.vparticipants_count.v; - data->left = false; - data->forbidden = false; - data->access = d.vaccess_hash.v; - if (data->version < d.vversion.v) { - data->version = d.vversion.v; - data->participants = ChatData::Participants(); - data->botStatus = 0; - }/**/ - } break; } if (!data) continue; @@ -716,13 +702,33 @@ namespace App { } } + void checkEntitiesUpdate(const MTPDmessage &m) { + if (HistoryItem *existing = App::histItemById(m.vid.v)) { + bool hasLinks = m.has_entities() && !m.ventities.c_vector().v.isEmpty(); + if ((hasLinks && !existing->hasTextLinks()) || (!hasLinks && existing->textHasLinks())) { + existing->setText(qs(m.vmessage), m.has_entities() ? linksFromMTP(m.ventities.c_vector().v) : LinksInText()); + existing->initDimensions(0); + if (App::main()) App::main()->itemResized(existing); + if (existing->hasTextLinks()) { + existing->history()->addToOverview(existing, OverviewLinks); + } + } + } + } + void feedMsgs(const MTPVector &msgs, int msgsState) { const QVector &v(msgs.c_vector().v); QMap msgsIds; for (int32 i = 0, l = v.size(); i < l; ++i) { const MTPMessage &msg(v.at(i)); switch (msg.type()) { - case mtpc_message: msgsIds.insert(msg.c_message().vid.v, i); break; + case mtpc_message: { + const MTPDmessage &d(msg.c_message()); + msgsIds.insert(d.vid.v, i); + if (msgsState == 1) { // new message, index my forwarded messages to links overview + checkEntitiesUpdate(d); + } + } break; case mtpc_messageEmpty: msgsIds.insert(msg.c_messageEmpty().vid.v, i); break; case mtpc_messageService: msgsIds.insert(msg.c_messageService().vid.v, i); break; } @@ -1072,11 +1078,11 @@ namespace App { } WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert) { - return App::webPageSet(webpage.vid.v, convert, webpage.has_type() ? qs(webpage.vtype) : qsl("article"), qs(webpage.vurl), qs(webpage.vdisplay_url), webpage.has_site_name() ? qs(webpage.vsite_name) : QString(), webpage.has_title() ? qs(webpage.vtitle) : QString(), webpage.has_description() ? qs(webpage.vdescription) : QString(), webpage.has_photo() ? App::feedPhoto(webpage.vphoto) : 0, webpage.has_duration() ? webpage.vduration.v : 0, webpage.has_author() ? qs(webpage.vauthor) : QString(), 0); + return App::webPageSet(webpage.vid.v, convert, webpage.has_type() ? qs(webpage.vtype) : qsl("article"), qs(webpage.vurl), qs(webpage.vdisplay_url), webpage.has_site_name() ? qs(webpage.vsite_name) : QString(), webpage.has_title() ? qs(webpage.vtitle) : QString(), webpage.has_description() ? qs(webpage.vdescription) : QString(), webpage.has_photo() ? App::feedPhoto(webpage.vphoto) : 0, webpage.has_document() ? App::feedDocument(webpage.vdocument) : 0, webpage.has_duration() ? webpage.vduration.v : 0, webpage.has_author() ? qs(webpage.vauthor) : QString(), 0); } WebPageData *feedWebPage(const MTPDwebPagePending &webpage, WebPageData *convert) { - return App::webPageSet(webpage.vid.v, convert, QString(), QString(), QString(), QString(), QString(), QString(), 0, 0, QString(), webpage.vdate.v); + return App::webPageSet(webpage.vid.v, convert, QString(), QString(), QString(), QString(), QString(), QString(), 0, 0, 0, QString(), webpage.vdate.v); } WebPageData *feedWebPage(const MTPWebPage &webpage) { @@ -1430,7 +1436,7 @@ namespace App { return i.value(); } - WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, int32 duration, const QString &author, int32 pendingTill) { + WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill) { if (convert) { if (convert->id != webPage) { WebPagesData::iterator i = webPagesData.find(convert->id); @@ -1447,6 +1453,7 @@ namespace App { convert->title = title; convert->description = description; convert->photo = photo; + convert->doc = doc; convert->duration = duration; convert->author = author; if (convert->pendingTill > 0 && pendingTill <= 0 && api()) api()->clearWebPageRequest(convert); @@ -1460,7 +1467,7 @@ namespace App { if (convert) { result = convert; } else { - result = new WebPageData(webPage, toWebPageType(type), url, displayUrl, siteName, title, description, photo, duration, author, (pendingTill >= -1) ? pendingTill : -1); + result = new WebPageData(webPage, toWebPageType(type), url, displayUrl, siteName, title, description, photo, doc, duration, author, (pendingTill >= -1) ? pendingTill : -1); if (pendingTill > 0 && api()) { api()->requestWebPageDelayed(result); } @@ -1477,6 +1484,7 @@ namespace App { result->title = title; result->description = description; result->photo = photo; + result->doc = doc; result->duration = duration; result->author = author; if (result->pendingTill > 0 && pendingTill <= 0 && api()) api()->clearWebPageRequest(result); @@ -1681,6 +1689,7 @@ namespace App { void historyClearItems() { historyClearMsgs(); randomData.clear(); + sentTextData.clear(); mutedPeers.clear(); updatedPeers.clear(); cSetSavedPeers(SavedPeers()); @@ -1719,6 +1728,7 @@ namespace App { ::audioItems.clear(); ::documentItems.clear(); ::webPageItems.clear(); + ::sharedContactPhones.clear(); ::repliesTo.clear(); lastPhotos.clear(); lastPhotosMap.clear(); @@ -1756,6 +1766,18 @@ namespace App { return 0; } + void historyRegSentText(uint64 randomId, const QString &text) { + sentTextData.insert(randomId, text); + } + + void historyUnregSentText(uint64 randomId) { + sentTextData.remove(randomId); + } + + QString histSentTextByItem(uint64 randomId) { + return sentTextData.value(randomId); + } + void prepareCorners(RoundCorners index, int32 radius, const style::color &color, const style::color *shadow = 0, QImage *cors = 0) { int32 r = radius * cIntRetinaFactor(), s = st::msgShadow * cIntRetinaFactor(); QImage rect(r * 3, r * 3 + (shadow ? s : 0), QImage::Format_ARGB32_Premultiplied), localCors[4]; @@ -1827,6 +1849,12 @@ namespace App { prepareCorners(BotKeyboardCorners, st::msgRadius, st::botKbBg); prepareCorners(BotKeyboardOverCorners, st::msgRadius, st::botKbOverBg); prepareCorners(BotKeyboardDownCorners, st::msgRadius, st::botKbDownBg); + prepareCorners(PhotoSelectOverlayCorners, st::msgRadius, st::overviewPhotoSelectOverlay); + + prepareCorners(DocRedCorners, st::msgRadius, st::mvDocRedColor); + prepareCorners(DocYellowCorners, st::msgRadius, st::mvDocYellowColor); + prepareCorners(DocGreenCorners, st::msgRadius, st::mvDocGreenColor); + prepareCorners(DocBlueCorners, st::msgRadius, st::mvDocBlueColor); prepareCorners(MessageInCorners, st::msgRadius, st::msgInBg, &st::msgInShadow); prepareCorners(MessageInSelectedCorners, st::msgRadius, st::msgInSelectBg, &st::msgInSelectShadow); @@ -2093,6 +2121,14 @@ namespace App { return ::webPageItems; } + void regSharedContactPhone(int32 userId, const QString &phone) { + ::sharedContactPhones[userId] = phone; + } + + QString phoneFromSharedContact(int32 userId) { + return ::sharedContactPhones.value(userId); + } + void regMuted(PeerData *peer, int32 changeIn) { ::mutedPeers.insert(peer, true); if (App::main()) App::main()->updateMutedIn(changeIn); diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index a68c390c3..f14f280eb 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -58,6 +58,12 @@ enum RoundCorners { BotKeyboardCorners, BotKeyboardOverCorners, BotKeyboardDownCorners, + PhotoSelectOverlayCorners, + + DocRedCorners, + DocYellowCorners, + DocGreenCorners, + DocBlueCorners, InShadowCorners, // for photos without bg InSelectedShadowCorners, @@ -112,6 +118,7 @@ namespace App { void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos, bool emitPeerUpdated = true); void feedParticipantAdd(const MTPDupdateChatParticipantAdd &d, bool emitPeerUpdated = true); void feedParticipantDelete(const MTPDupdateChatParticipantDelete &d, bool emitPeerUpdated = true); + void checkEntitiesUpdate(const MTPDmessage &m); void feedMsgs(const MTPVector &msgs, int msgsState = 0); // 2 - new read message, 1 - new unread message, 0 - not new message, -1 - searched message void feedWereRead(const QVector &msgsIds); void feedInboxRead(const PeerId &peer, int32 upTo); @@ -166,7 +173,7 @@ namespace App { 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); - WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, int32 duration, const QString &author, int32 pendingTill); + WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill); ImageLinkData *imageLink(const QString &imageLink); ImageLinkData *imageLinkSet(const QString &imageLink, ImageLinkType type, const QString &url); void forgetMedia(); @@ -188,6 +195,9 @@ namespace App { void historyRegRandom(uint64 randomId, MsgId itemId); void historyUnregRandom(uint64 randomId); MsgId histItemByRandom(uint64 randomId); + void historyRegSentText(uint64 itemId, const QString &text); + void historyUnregSentText(uint64 itemId); + QString histSentTextByItem(uint64 itemId); void hoveredItem(HistoryItem *item); HistoryItem *hoveredItem(); @@ -238,6 +248,9 @@ namespace App { void unregWebPageItem(WebPageData *data, HistoryItem *item); const WebPageItems &webPageItems(); + void regSharedContactPhone(int32 userId, const QString &phone); + QString phoneFromSharedContact(int32 userId); + void regMuted(PeerData *peer, int32 changeIn); void unregMuted(PeerData *peer); void updateMuted(); diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index 85096cf9c..efb917d1d 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -95,7 +95,10 @@ namespace { Application::Application(int &argc, char **argv) : PsApplication(argc, argv), serverName(psServerPrefix() + cGUIDStr()), closing(false), - updateRequestId(0), updateReply(0), updateThread(0), updateDownloader(0), _translator(0) { + #ifndef TDESKTOP_DISABLE_AUTOUPDATE + updateRequestId(0), updateReply(0), updateThread(0), updateDownloader(0), + #endif + _translator(0) { DEBUG_LOG(("Application Info: creation..")); @@ -178,9 +181,11 @@ Application::Application(int &argc, char **argv) : PsApplication(argc, argv), connect(&socket, SIGNAL(readyRead()), this, SLOT(socketReading())); connect(&server, SIGNAL(newConnection()), this, SLOT(newInstanceConnected())); connect(this, SIGNAL(aboutToQuit()), this, SLOT(closeApplication())); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE connect(&updateCheckTimer, SIGNAL(timeout()), this, SLOT(startUpdateCheck())); connect(this, SIGNAL(updateFailed()), this, SLOT(onUpdateFailed())); connect(this, SIGNAL(updateReady()), this, SLOT(onUpdateReady())); + #endif connect(this, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(onAppStateChanged(Qt::ApplicationState))); //connect(&writeUserConfigTimer, SIGNAL(timeout()), this, SLOT(onWriteUserConfig())); //writeUserConfigTimer.setSingleShot(true); @@ -195,6 +200,7 @@ Application::Application(int &argc, char **argv) : PsApplication(argc, argv), } } +#ifndef TDESKTOP_DISABLE_AUTOUPDATE void Application::updateGotCurrent() { if (!updateReply || updateThread) return; @@ -258,6 +264,7 @@ void Application::onUpdateFailed() { cSetLastUpdateCheck(unixtime()); Local::writeSettings(); } +#endif void Application::regPhotoUpdate(const PeerId &peer, MsgId msgId) { photoUpdates.insert(msgId, peer); @@ -431,11 +438,16 @@ void Application::onSwitchTestMode() { } Application::UpdatingState Application::updatingState() { + #ifndef TDESKTOP_DISABLE_AUTOUPDATE if (!updateThread) return Application::UpdatingNone; if (!updateDownloader) return Application::UpdatingReady; return Application::UpdatingDownload; + #else + return Application::UpdatingNone; + #endif } +#ifndef TDESKTOP_DISABLE_AUTOUPDATE int32 Application::updatingSize() { if (!updateDownloader) return 0; return updateDownloader->size(); @@ -445,6 +457,7 @@ int32 Application::updatingReady() { if (!updateDownloader) return 0; return updateDownloader->ready(); } +#endif FileUploader *Application::uploader() { if (!::uploader) ::uploader = new FileUploader(); @@ -488,6 +501,7 @@ void Application::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId) App::uploader()->uploadMedia(newId, ready); } +#ifndef TDESKTOP_DISABLE_AUTOUPDATE void Application::stopUpdate() { if (updateReply) { updateReply->abort(); @@ -541,6 +555,7 @@ void Application::startUpdateCheck(bool forceWait) { updateCheckTimer.start((updateInSecs + 5) * 1000); } } +#endif namespace { QChar _toHex(ushort v) { @@ -643,11 +658,13 @@ void Application::socketError(QLocalSocket::LocalSocketError e) { return App::quit(); } + #ifndef TDESKTOP_DISABLE_AUTOUPDATE if (!cNoStartUpdate() && checkReadyUpdate()) { cSetRestartingUpdate(true); DEBUG_LOG(("Application Info: installing update instead of starting app..")); return App::quit(); } + #endif startApp(); } @@ -656,9 +673,9 @@ void Application::checkMapVersion() { if (Local::oldMapVersion() < AppVersion) { if (Local::oldMapVersion()) { QString versionFeatures; - if (cDevVersion() && Local::oldMapVersion() < 8050) { - versionFeatures = QString::fromUtf8("\xe2\x80\x94 Bug fixes in Windows notifications\n\xe2\x80\x94 Fixed input methods on Linux (Fcitx and IBus)");// .replace('@', qsl("@") + QChar(0x200D)); - } else if (!cDevVersion() && Local::oldMapVersion() < 8051) { + if (cDevVersion() && Local::oldMapVersion() < 8054) { + versionFeatures = QString::fromUtf8("\xe2\x80\x94 Preview when sending links to GIF animations and PDF files\n\xe2\x80\x94 Full date and time shown when mouse over message timestamp");// .replace('@', qsl("@") + QChar(0x200D)); + } else if (!cDevVersion() && Local::oldMapVersion() < 8055) { versionFeatures = lang(lng_new_version_text).trimmed(); } if (!versionFeatures.isEmpty()) { @@ -833,13 +850,15 @@ Application::~Application() { App::deinitMedia(); deinitImageLinkManager(); mainApp = 0; - delete updateReply; delete ::uploader; + #ifndef TDESKTOP_DISABLE_AUTOUPDATE + delete updateReply; updateReply = 0; if (updateDownloader) updateDownloader->deleteLater(); updateDownloader = 0; if (updateThread) updateThread->quit(); updateThread = 0; + #endif delete window; diff --git a/Telegram/SourceFiles/application.h b/Telegram/SourceFiles/application.h index 694db8850..c94ce93d9 100644 --- a/Telegram/SourceFiles/application.h +++ b/Telegram/SourceFiles/application.h @@ -49,8 +49,10 @@ public: UpdatingReady, }; UpdatingState updatingState(); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE int32 updatingSize(); int32 updatingReady(); + #endif FileUploader *uploader(); void uploadProfilePhoto(const QImage &tosend, const PeerId &peerId); @@ -78,11 +80,13 @@ public: signals: + #ifndef TDESKTOP_DISABLE_AUTOUPDATE void updateChecking(); void updateLatest(); void updateDownloading(qint64 ready, qint64 total); void updateReady(); void updateFailed(); + #endif void peerPhotoDone(PeerId peer); void peerPhotoFail(PeerId peer); @@ -91,7 +95,9 @@ signals: public slots: + #ifndef TDESKTOP_DISABLE_AUTOUPDATE void startUpdateCheck(bool forceWait = false); + #endif void socketConnected(); void socketError(QLocalSocket::LocalSocketError e); void socketDisconnected(); @@ -103,11 +109,13 @@ public slots: void readClients(); void removeClients(); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE void updateGotCurrent(); void updateFailedCurrent(QNetworkReply::NetworkError e); void onUpdateReady(); void onUpdateFailed(); + #endif void photoUpdated(MsgId msgId, const MTPInputFile &file); @@ -142,12 +150,14 @@ private: Window *window; + #ifndef TDESKTOP_DISABLE_AUTOUPDATE mtpRequestId updateRequestId; QNetworkAccessManager updateManager; QNetworkReply *updateReply; SingleTimer updateCheckTimer; QThread *updateThread; UpdateDownloader *updateDownloader; + #endif QTimer writeUserConfigTimer; diff --git a/Telegram/SourceFiles/art/sprite.png b/Telegram/SourceFiles/art/sprite.png index 648101a31..784f8a93a 100644 Binary files a/Telegram/SourceFiles/art/sprite.png and b/Telegram/SourceFiles/art/sprite.png differ diff --git a/Telegram/SourceFiles/art/sprite_200x.png b/Telegram/SourceFiles/art/sprite_200x.png index f8d5d7f38..7ef912b1d 100644 Binary files a/Telegram/SourceFiles/art/sprite_200x.png and b/Telegram/SourceFiles/art/sprite_200x.png differ diff --git a/Telegram/SourceFiles/autoupdater.cpp b/Telegram/SourceFiles/autoupdater.cpp index 2d4771ce2..a84b3ca54 100644 --- a/Telegram/SourceFiles/autoupdater.cpp +++ b/Telegram/SourceFiles/autoupdater.cpp @@ -15,11 +15,14 @@ GNU General Public License for more details. Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014 John Preston, https://desktop.telegram.org */ + #include "stdafx.h" #include "application.h" #include "pspecific.h" #include "autoupdater.h" +#ifndef TDESKTOP_DISABLE_AUTOUPDATE + #ifdef Q_OS_WIN typedef DWORD VerInt; typedef WCHAR VerChar; @@ -534,3 +537,5 @@ bool checkReadyUpdate() { #endif return true; } + +#endif diff --git a/Telegram/SourceFiles/autoupdater.h b/Telegram/SourceFiles/autoupdater.h index 097f335ad..f8580c6b3 100644 --- a/Telegram/SourceFiles/autoupdater.h +++ b/Telegram/SourceFiles/autoupdater.h @@ -17,6 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once +#ifndef TDESKTOP_DISABLE_AUTOUPDATE + #include #include #include @@ -60,3 +62,5 @@ private: }; bool checkReadyUpdate(); + +#endif diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp index 75353e55e..0694a143c 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.cpp +++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp @@ -285,7 +285,6 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) { } if (uid) { App::main()->addNewContact(uid); - App::main()->choosePeer(App::peerFromUser(uid), ShowAtUnreadMsgId); App::wnd()->hideLayer(); } else { _addButton.hide(); diff --git a/Telegram/SourceFiles/boxes/contactsbox.cpp b/Telegram/SourceFiles/boxes/contactsbox.cpp index c5cec8baa..00933bcb2 100644 --- a/Telegram/SourceFiles/boxes/contactsbox.cpp +++ b/Telegram/SourceFiles/boxes/contactsbox.cpp @@ -1271,6 +1271,8 @@ void CreateGroupBox::created(const MTPUpdates &updates) { } break; case mtpc_updateShortChatMessage: { } break; + case mtpc_updateShortSentMessage: { + } break; case mtpc_updatesTooLong: { } break; } diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 3490453cd..fb3462f1c 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -static const int32 AppVersion = 8051; -static const wchar_t *AppVersionStr = L"0.8.51"; +static const int32 AppVersion = 8055; +static const wchar_t *AppVersionStr = L"0.8.55"; static const bool DevVersion = false; static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)"; @@ -81,6 +81,7 @@ enum { AutoSearchTimeout = 900, // 0.9 secs SearchPerPage = 50, SearchManyPerPage = 100, + LinksOverviewPerPage = 12, MediaOverviewStartPerPage = 5, MediaOverviewPreloadCount = 4, diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index d7e7fc8f9..c731fae0a 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -829,22 +829,17 @@ void DialogsListWidget::contactsReceived(const QVector &contacts) { refresh(); } -int32 DialogsListWidget::addNewContact(int32 uid, bool select) { +int32 DialogsListWidget::addNewContact(int32 uid, bool select) { // -2 - err, -1 - don't scroll, >= 0 - scroll PeerId peer = App::peerFromUser(uid); - if (!App::peerLoaded(peer)) return -1; + if (!App::peerLoaded(peer)) return -2; History *history = App::history(peer); contacts.addByName(history); DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(peer); if (i == dialogs.list.rowByPeer.cend()) { DialogRow *added = contactsNoDialogs.addByName(history); - if (!added) return -1; - if (select && false) { - sel = added; - contactSel = true; - } -// if (contactsNoDialogs.list.count == 1 && !dialogs.list.count) refresh(); - return added ? ((dialogs.list.count + added->pos) * st::dlgHeight) : -1; + if (!added) return -2; + return -1; } if (select) { sel = i.value(); @@ -1700,7 +1695,6 @@ bool DialogsWidget::onSearchMessages(bool searchCache) { return false; } - void DialogsWidget::onNeedSearchMessages() { if (!onSearchMessages(true)) { _searchTimer.start(AutoSearchTimeout); @@ -1843,9 +1837,9 @@ bool DialogsWidget::addNewContact(int32 uid, bool show) { _filter.setText(QString()); onFilterUpdate(); int32 to = list.addNewContact(uid, true); - if (to < 0 || !show) return false; + if (to < -1 || !show) return false; list.refresh(); - scroll.scrollToY(to); + if (to >= 0) scroll.scrollToY(to); return true; } diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index 7efb555ec..e012fcb21 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -35,7 +35,7 @@ public: void activate(); void contactsReceived(const QVector &contacts); - int32 addNewContact(int32 uid, bool sel = false); // return y of row or -1 if failed + int32 addNewContact(int32 uid, bool sel = false); // -2 - err, -1 - don't scroll, >= 0 - scroll int32 filteredOffset() const; int32 peopleOffset() const; diff --git a/Telegram/SourceFiles/gui/emoji_config.h b/Telegram/SourceFiles/gui/emoji_config.h index d66229f6a..9a7a5de94 100644 --- a/Telegram/SourceFiles/gui/emoji_config.h +++ b/Telegram/SourceFiles/gui/emoji_config.h @@ -146,8 +146,8 @@ inline bool emojiEdge(const QChar *ch) { inline QString replaceEmojis(const QString &text) { QString result; - LinkRanges lnkRanges = textParseLinks(text, TextParseLinks | TextParseMentions | TextParseHashtags); - int32 currentLink = 0, lnkCount = lnkRanges.size(); + LinksInText links = textParseLinks(text, TextParseLinks | TextParseMentions | TextParseHashtags); + int32 currentLink = 0, lnkCount = links.size(); const QChar *emojiStart = text.unicode(), *emojiEnd = emojiStart, *e = text.cend(); bool canFindEmoji = true, consumePrevious = false; for (const QChar *ch = emojiEnd; ch != e;) { @@ -157,14 +157,14 @@ inline QString replaceEmojis(const QString &text) { emojiFind(ch, e, newEmojiEnd, emojiCode); } - while (currentLink < lnkCount && ch >= lnkRanges[currentLink].from + lnkRanges[currentLink].len) { + while (currentLink < lnkCount && ch >= emojiStart + links[currentLink].offset + links[currentLink].length) { ++currentLink; } EmojiPtr emoji = emojiCode ? emojiGet(emojiCode) : 0; if (emoji && emoji != TwoSymbolEmoji && (ch == emojiStart || !ch->isLetterOrNumber() || !(ch - 1)->isLetterOrNumber()) && (newEmojiEnd == e || !newEmojiEnd->isLetterOrNumber() || newEmojiEnd == emojiStart || !(newEmojiEnd - 1)->isLetterOrNumber()) && - (currentLink >= lnkCount || (ch < lnkRanges[currentLink].from && newEmojiEnd <= lnkRanges[currentLink].from) || (ch >= lnkRanges[currentLink].from + lnkRanges[currentLink].len && newEmojiEnd > lnkRanges[currentLink].from + lnkRanges[currentLink].len)) + (currentLink >= lnkCount || (ch < emojiStart + links[currentLink].offset && newEmojiEnd <= emojiStart + links[currentLink].offset) || (ch >= emojiStart + links[currentLink].offset + links[currentLink].length && newEmojiEnd > emojiStart + links[currentLink].offset + links[currentLink].length)) ) { // if (newEmojiEnd < e && newEmojiEnd->unicode() == ' ') ++newEmojiEnd; if (result.isEmpty()) result.reserve(text.size()); diff --git a/Telegram/SourceFiles/gui/flattextarea.cpp b/Telegram/SourceFiles/gui/flattextarea.cpp index d2ff0020e..0e3a6a72d 100644 --- a/Telegram/SourceFiles/gui/flattextarea.cpp +++ b/Telegram/SourceFiles/gui/flattextarea.cpp @@ -24,7 +24,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &pholder, const QString &v) : QTextEdit(v, parent), _ph(pholder), _oldtext(v), _phVisible(!v.length()), a_phLeft(_phVisible ? 0 : st.phShift), a_phAlpha(_phVisible ? 1 : 0), a_phColor(st.phColor->c), - _st(st), _undoAvailable(false), _redoAvailable(false), _fakeMargin(0), + _st(st), _undoAvailable(false), _redoAvailable(false), _inDrop(false), _fakeMargin(0), _touchPress(false), _touchRightButton(false), _touchMove(false), _replacingEmojis(false) { setAcceptRichText(false); resize(_st.width, _st.font->height); @@ -530,7 +530,7 @@ QStringList FlatTextarea::linksList() const { void FlatTextarea::insertFromMimeData(const QMimeData *source) { QTextEdit::insertFromMimeData(source); - emit spacedReturnedPasted(); + if (!_inDrop) emit spacedReturnedPasted(); } void FlatTextarea::insertEmoji(EmojiPtr emoji, QTextCursor c) { @@ -814,3 +814,14 @@ void FlatTextarea::resizeEvent(QResizeEvent *e) { _phelided = _st.font->m.elidedText(_ph, Qt::ElideRight, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1); QTextEdit::resizeEvent(e); } + +void FlatTextarea::mousePressEvent(QMouseEvent *e) { + QTextEdit::mousePressEvent(e); +} + +void FlatTextarea::dropEvent(QDropEvent *e) { + _inDrop = true; + QTextEdit::dropEvent(e); + _inDrop = false; + emit spacedReturnedPasted(); +} diff --git a/Telegram/SourceFiles/gui/flattextarea.h b/Telegram/SourceFiles/gui/flattextarea.h index 732a6008d..408f3ed16 100644 --- a/Telegram/SourceFiles/gui/flattextarea.h +++ b/Telegram/SourceFiles/gui/flattextarea.h @@ -35,6 +35,8 @@ public: void focusOutEvent(QFocusEvent *e); void keyPressEvent(QKeyEvent *e); void resizeEvent(QResizeEvent *e); + void mousePressEvent(QMouseEvent *e); + void dropEvent(QDropEvent *e); const QString &getLastText() const; void updatePlaceholder(); @@ -118,7 +120,7 @@ private: anim::cvalue a_phColor; style::flatTextarea _st; - bool _undoAvailable, _redoAvailable; + bool _undoAvailable, _redoAvailable, _inDrop; int32 _fakeMargin; diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp index 5e7d50bdc..83f24fb4c 100644 --- a/Telegram/SourceFiles/gui/text.cpp +++ b/Telegram/SourceFiles/gui/text.cpp @@ -20,6 +20,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "lang.h" +#include "pspecific.h" + #include namespace { @@ -328,13 +330,13 @@ public: } bool checkWaitedLink() { - if (waitingLink == linksEnd || ptr < waitingLink->from || links.size() >= 0x7FFF) { + if (waitingLink == linksEnd || ptr < start + waitingLink->offset || links.size() >= 0x7FFF) { return true; } createBlock(); - QString lnkUrl = QString(waitingLink->from, waitingLink->len), lnkText; + QString lnkUrl = QString(start + waitingLink->offset, waitingLink->length), lnkText; int32 fullDisplayed; getLinkData(lnkUrl, lnkText, fullDisplayed); @@ -342,7 +344,7 @@ public: lnkIndex = 0x8000 + links.size(); _t->_text += lnkText; - ptr = waitingLink->from + waitingLink->len; + ptr = start + waitingLink->offset + waitingLink->length; createBlock(); ++waitingLink; @@ -519,8 +521,51 @@ public: emoji = e; } - TextParser(Text *t, const QString &text, const TextParseOptions &options) : _t(t), src(text), - rich(options.flags & TextParseRichText), multiline(options.flags & TextParseMultiline), maxLnkIndex(0), flags(0), lnkIndex(0), stopAfterWidth(QFIXED_MAX) { + TextParser(Text *t, const QString &text, const TextParseOptions &options) : _t(t), + src(text), + rich(options.flags & TextParseRichText), + multiline(options.flags & TextParseMultiline), + maxLnkIndex(0), + flags(0), + lnkIndex(0), + stopAfterWidth(QFIXED_MAX) { + if (options.flags & TextParseLinks) { + lnkRanges = textParseLinks(src, options.flags, rich); + } + parse(options); + } + TextParser(Text *t, const QString &text, const LinksInText &links, const TextParseOptions &options) : _t(t), + src(text), + rich(options.flags & TextParseRichText), + multiline(options.flags & TextParseMultiline), + maxLnkIndex(0), + flags(0), + lnkIndex(0), + stopAfterWidth(QFIXED_MAX) { + if ((options.flags & TextParseLinks) && !links.isEmpty()) { + bool parseMentions = (options.flags & TextParseMentions); + bool parseHashtags = (options.flags & TextParseHashtags); + bool parseBotCommands = (options.flags & TextParseBotCommands); + if (parseMentions && parseHashtags && parseBotCommands) { + lnkRanges = links; + } else { + int32 i = 0, l = links.size(); + lnkRanges.reserve(l); + const QChar *p = text.constData(), s = text.size(); + for (; i < l; ++i) { + LinkInTextType t = links.at(i).type; + if ((t == LinkInTextMention && !parseMentions) || + (t == LinkInTextHashtag && !parseHashtags) || + (t == LinkInTextBotCommand && !parseBotCommands)) { + continue; + } + lnkRanges.push_back(links.at(i)); + } + } + } + parse(options); + } + void parse(const TextParseOptions &options) { int flags = options.flags; if (options.maxw > 0 && options.maxh > 0) { stopAfterWidth = ((options.maxh / _t->_font->height) + 1) * options.maxw; @@ -529,19 +574,16 @@ public: start = src.constData(); end = start + src.size(); - if (options.flags & TextParseLinks) { - lnkRanges = textParseLinks(src, options.flags, rich); + ptr = start; + while (ptr != end && chIsTrimmed(*ptr, rich)) { + ++ptr; } - - while (start != end && chIsTrimmed(*start, rich)) { - ++start; - } - while (start != end && chIsTrimmed(*(end - 1), rich)) { + while (ptr != end && chIsTrimmed(*(end - 1), rich)) { --end; } _t->_text.resize(0); - _t->_text.reserve(end - start); + _t->_text.reserve(end - ptr); diacs = 0; sumWidth = 0; @@ -552,9 +594,9 @@ public: ch = chInt = 0; lastSkipped = false; lastSpace = true; - waitingLink = lnkRanges.isEmpty() ? 0 : lnkRanges.constData(); - linksEnd = lnkRanges.isEmpty() ? 0 : waitingLink + lnkRanges.size(); - for (ptr = start; ptr <= end; ++ptr) { + waitingLink = lnkRanges.cbegin(); + linksEnd = lnkRanges.cend(); + for (; ptr <= end; ++ptr) { if (!checkWaitedLink()) { break; } @@ -615,8 +657,8 @@ private: const QChar *start, *end, *ptr; bool rich, multiline; - LinkRanges lnkRanges; - const LinkRange *waitingLink, *linksEnd; + LinksInText lnkRanges; + LinksInText::const_iterator waitingLink, linksEnd; struct TextLinkData { TextLinkData(const QString &url = QString(), int32 fullDisplayed = 1) : url(url), fullDisplayed(fullDisplayed) { @@ -769,6 +811,15 @@ void TextLink::onClick(Qt::MouseButton button) const { } } +void EmailLink::onClick(Qt::MouseButton button) const { + if (button == Qt::LeftButton || button == Qt::MiddleButton) { + QUrl url(qstr("mailto:") + _email); + if (!QDesktopServices::openUrl(url)) { + psOpenFile(url.toString(QUrl::FullyEncoded), true); + } + } +} + void MentionLink::onClick(Qt::MouseButton button) const { if (button == Qt::LeftButton || button == Qt::MiddleButton) { App::openUserByName(_tag.mid(1), true); @@ -2299,9 +2350,13 @@ void Text::setText(style::font font, const QString &text, const TextParseOptions { TextParser parser(this, text, options); } + recountNaturalSize(true, options.dir); +} +void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) { NewlineBlock *lastNewline = 0; + _maxWidth = _minHeight = 0; int32 lineHeight = 0; int32 result = 0, lastNewlineStart = 0; QFixed _width = 0, last_rBearing = 0, last_rPadding = 0; @@ -2313,14 +2368,16 @@ void Text::setText(style::font font, const QString &text, const TextParseOptions if (_btype == TextBlockNewline) { if (!lineHeight) lineHeight = blockHeight; - Qt::LayoutDirection dir = options.dir; - if (dir == Qt::LayoutDirectionAuto) { - dir = TextParser::stringDirection(_text, lastNewlineStart, b->from()); - } - if (lastNewline) { - lastNewline->_nextDir = dir; - } else { - _startDir = dir; + if (initial) { + Qt::LayoutDirection dir = optionsDir; + if (dir == Qt::LayoutDirectionAuto) { + dir = TextParser::stringDirection(_text, lastNewlineStart, b->from()); + } + if (lastNewline) { + lastNewline->_nextDir = dir; + } else { + _startDir = dir; + } } lastNewlineStart = b->from(); lastNewline = static_cast(b); @@ -2344,14 +2401,16 @@ void Text::setText(style::font font, const QString &text, const TextParseOptions last_rPadding = b->f_rpadding(); continue; } - Qt::LayoutDirection dir = options.dir; - if (dir == Qt::LayoutDirectionAuto) { - dir = TextParser::stringDirection(_text, lastNewlineStart, _text.size()); - } - if (lastNewline) { - lastNewline->_nextDir = dir; - } else { - _startDir = dir; + if (initial) { + Qt::LayoutDirection dir = optionsDir; + if (dir == Qt::LayoutDirectionAuto) { + dir = TextParser::stringDirection(_text, lastNewlineStart, _text.size()); + } + if (lastNewline) { + lastNewline->_nextDir = dir; + } else { + _startDir = dir; + } } if (_width > 0) { if (!lineHeight) lineHeight = _blockHeight(_blocks.back(), _font); @@ -2362,6 +2421,16 @@ void Text::setText(style::font font, const QString &text, const TextParseOptions } } +void Text::setMarkedText(style::font font, const QString &text, const LinksInText &links, const TextParseOptions &options) { + if (!_textStyle) _initDefault(); + _font = font; + clean(); + { + TextParser parser(this, text, links, options); + } + recountNaturalSize(true, options.dir); +} + void Text::setRichText(style::font font, const QString &text, TextParseOptions options, const TextCustomTagsMap &custom) { QString parsed; parsed.reserve(text.size()); @@ -2449,6 +2518,82 @@ bool Text::hasLinks() const { return !_links.isEmpty(); } +void Text::setSkipBlock(int32 width, int32 height) { + if (!_blocks.isEmpty() && _blocks.back()->type() == TextBlockSkip) { + SkipBlock *block = static_cast(_blocks.back()); + if (block->width() == width && block->height() == height) return; + _text.resize(block->from()); + _blocks.pop_back(); + } + _text.push_back('_'); + _blocks.push_back(new SkipBlock(_font, _text, _text.size() - 1, width, height, 0)); + recountNaturalSize(false); +} + +void Text::removeSkipBlock() { + if (!_blocks.isEmpty() && _blocks.back()->type() == TextBlockSkip) { + _text.resize(_blocks.back()->from()); + _blocks.pop_back(); + recountNaturalSize(false); + } +} + +LinksInText Text::calcLinksInText() const { + LinksInText result; + int32 lnkFrom = 0, lnkIndex = 0, offset = 0; + for (TextBlocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); true; ++i) { + int32 blockLnkIndex = (i == e) ? 0 : (*i)->lnkIndex(); + int32 blockFrom = (i == e) ? _text.size() : (*i)->from(); + if (blockLnkIndex != lnkIndex) { + if (lnkIndex) { // write link + const TextLinkPtr &lnk(_links.at(lnkIndex - 1)); + const QString &url(lnk ? lnk->text() : QString()); + + int32 rangeFrom = lnkFrom, rangeTo = blockFrom; + if (rangeTo > rangeFrom) { + QStringRef r = _text.midRef(rangeFrom, rangeTo - rangeFrom); + if (url.isEmpty()) { + offset += r.size(); + } else { + QUrl u(url); + if (r.size() <= 3 || _text.midRef(lnkFrom, r.size() - 3) == (u.isValid() ? u.toDisplayString() : url).midRef(0, r.size() - 3)) { // same link + if (url.at(0) == '@') { + result.push_back(LinkInText(LinkInTextMention, offset, url.size())); + } else if (url.at(0) == '#') { + result.push_back(LinkInText(LinkInTextHashtag, offset, url.size())); + } else if (url.at(0) == '/') { + result.push_back(LinkInText(LinkInTextBotCommand, offset, url.size())); + } else if (url.indexOf('@') > 0 && url.indexOf('/') <= 0) { + result.push_back(LinkInText(LinkInTextEmail, offset, url.size())); + } else { + result.push_back(LinkInText(LinkInTextUrl, offset, url.size())); + } + offset += url.size(); + } else { + result.push_back(LinkInText(LinkInTextCustomUrl, offset, r.size(), url)); + offset += r.size(); + } + } + } + } + lnkIndex = blockLnkIndex; + lnkFrom = blockFrom; + } + if (i == e) break; + + TextBlockType type = (*i)->type(); + if (type == TextBlockSkip) continue; + + if (!blockLnkIndex) { + int32 rangeFrom = (*i)->from(), rangeTo = uint16((*i)->from() + TextPainter::_blockLength(this, i, e)); + if (rangeTo > rangeFrom) { + offset += rangeTo - rangeFrom; + } + } + } + return result; +} + int32 Text::countHeight(int32 w) const { QFixed width = w; if (width < _minResizeWidth) width = _minResizeWidth; @@ -4035,16 +4180,16 @@ QString textSearchKey(const QString &text) { bool textSplit(QString &sendingText, QString &leftText, int32 limit) { if (leftText.isEmpty() || !limit) return false; - LinkRanges lnkRanges = textParseLinks(leftText, TextParseLinks | TextParseMentions | TextParseHashtags); - int32 currentLink = 0, lnkCount = lnkRanges.size(); + LinksInText links = textParseLinks(leftText, TextParseLinks | TextParseMentions | TextParseHashtags); + int32 currentLink = 0, lnkCount = links.size(); int32 s = 0, half = limit / 2, goodLevel = 0; for (const QChar *start = leftText.constData(), *ch = start, *end = leftText.constEnd(), *good = ch; ch != end; ++ch, ++s) { - while (currentLink < lnkCount && ch >= lnkRanges[currentLink].from + lnkRanges[currentLink].len) { + while (currentLink < lnkCount && ch >= start + links[currentLink].offset + links[currentLink].length) { ++currentLink; } - bool inLink = (currentLink < lnkCount) && (ch > lnkRanges[currentLink].from) && (ch < lnkRanges[currentLink].from + lnkRanges[currentLink].len); + bool inLink = (currentLink < lnkCount) && (ch > start + links[currentLink].offset) && (ch < start + links[currentLink].offset + links[currentLink].length); if (s > half) { if (inLink) { if (!goodLevel) good = ch; @@ -4102,8 +4247,8 @@ bool textSplit(QString &sendingText, QString &leftText, int32 limit) { return true; } -LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some code is duplicated in flattextarea.cpp! - LinkRanges lnkRanges; +LinksInText textParseLinks(const QString &text, int32 flags, bool rich) { // some code is duplicated in flattextarea.cpp! + LinksInText result; bool withHashtags = (flags & TextParseHashtags); bool withMentions = (flags & TextParseMentions); @@ -4126,7 +4271,8 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some QRegularExpressionMatch mMention = withMentions ? _reMention.match(text, qMax(mentionSkip, matchOffset)) : QRegularExpressionMatch(); QRegularExpressionMatch mBotCommand = withBotCommands ? _reBotCommand.match(text, matchOffset) : QRegularExpressionMatch(); - LinkRange link; + LinkInTextType lnkType = LinkInTextUrl; + int32 lnkOffset = 0, lnkLength = 0; int32 domainOffset = mDomain.hasMatch() ? mDomain.capturedStart() : INT_MAX, domainEnd = mDomain.hasMatch() ? mDomain.capturedEnd() : INT_MAX, explicitDomainOffset = mExplicitDomain.hasMatch() ? mExplicitDomain.capturedStart() : INT_MAX, @@ -4191,9 +4337,9 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some continue; } } - - link.from = start + mentionOffset; - link.len = start + mentionEnd - link.from; + lnkType = LinkInTextMention; + lnkOffset = mentionOffset; + lnkLength = mentionEnd - mentionOffset; } else if (hashtagOffset < domainOffset && hashtagOffset < botCommandOffset) { if (hashtagOffset > nextCmd) { const QChar *after = textSkipCommand(start + nextCmd, start + len); @@ -4203,8 +4349,9 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some } } - link.from = start + hashtagOffset; - link.len = start + hashtagEnd - link.from; + lnkType = LinkInTextHashtag; + lnkOffset = hashtagOffset; + lnkLength = hashtagEnd - hashtagOffset; } else if (botCommandOffset < domainOffset) { if (botCommandOffset > nextCmd) { const QChar *after = textSkipCommand(start + nextCmd, start + len); @@ -4214,8 +4361,9 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some } } - link.from = start + botCommandOffset; - link.len = start + botCommandEnd - link.from; + lnkType = LinkInTextBotCommand; + lnkOffset = botCommandOffset; + lnkLength = botCommandEnd - botCommandOffset; } else { if (domainOffset > nextCmd) { const QChar *after = textSkipCommand(start + nextCmd, start + len); @@ -4239,16 +4387,17 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some if (mailOffset < offset) { mailOffset = offset; } - link.from = start + mailOffset; - link.len = domainEnd - mailOffset; + lnkType = LinkInTextEmail; + lnkOffset = mailOffset; + lnkLength = domainEnd - mailOffset; } } - if (!link.from || !link.len) { + if (lnkType == LinkInTextUrl && !lnkLength) { if (!isProtocolValid || !isTopDomainValid) { matchOffset = domainEnd; continue; } - link.from = start + domainOffset; + lnkOffset = domainOffset; QStack parenth; const QChar *domainEnd = start + mDomain.capturedEnd(), *p = domainEnd; @@ -4283,15 +4432,15 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some continue; } } - link.len = p - link.from; + lnkLength = (p - start) - lnkOffset; } } - lnkRanges.push_back(link); + result.push_back(LinkInText(lnkType, lnkOffset, lnkLength)); - offset = matchOffset = (link.from - start) + link.len; + offset = matchOffset = lnkOffset + lnkLength; } - return lnkRanges; + return result; } void emojiDraw(QPainter &p, EmojiPtr e, int x, int y) { diff --git a/Telegram/SourceFiles/gui/text.h b/Telegram/SourceFiles/gui/text.h index 84d7da3aa..bfc3749f0 100644 --- a/Telegram/SourceFiles/gui/text.h +++ b/Telegram/SourceFiles/gui/text.h @@ -39,14 +39,57 @@ enum { TextInstagramHashtags = 0x200, }; -struct LinkRange { - LinkRange() : from(0), len(0) { - } - const QChar *from; - int32 len; +enum LinkInTextType { + LinkInTextUrl, + LinkInTextCustomUrl, + LinkInTextEmail, + LinkInTextHashtag, + LinkInTextMention, + LinkInTextBotCommand, }; -typedef QVector LinkRanges; -LinkRanges textParseLinks(const QString &text, int32 flags, bool rich = false); +struct LinkInText { + LinkInText(LinkInTextType type, int32 offset, int32 length, const QString &text = QString()) : type(type), offset(offset), length(length), text(text) { + } + LinkInTextType type; + int32 offset, length; + QString text; +}; +typedef QList LinksInText; +inline LinksInText linksFromMTP(const QVector &entities) { + LinksInText result; + if (!entities.isEmpty()) { + result.reserve(entities.size()); + for (int32 i = 0, l = entities.size(); i != l; ++i) { + const MTPMessageEntity &e(entities.at(i)); + switch (e.type()) { + case mtpc_messageEntityUrl: { const MTPDmessageEntityUrl &d(e.c_messageEntityUrl()); result.push_back(LinkInText(LinkInTextUrl, d.voffset.v, d.vlength.v)); } break; + case mtpc_messageEntityTextUrl: { const MTPDmessageEntityTextUrl &d(e.c_messageEntityTextUrl()); result.push_back(LinkInText(LinkInTextCustomUrl, d.voffset.v, d.vlength.v, textClean(qs(d.vurl)))); } break; + case mtpc_messageEntityEmail: { const MTPDmessageEntityEmail &d(e.c_messageEntityEmail()); result.push_back(LinkInText(LinkInTextEmail, d.voffset.v, d.vlength.v)); } break; + case mtpc_messageEntityHashtag: { const MTPDmessageEntityHashtag &d(e.c_messageEntityHashtag()); result.push_back(LinkInText(LinkInTextHashtag, d.voffset.v, d.vlength.v)); } break; + case mtpc_messageEntityMention: { const MTPDmessageEntityMention &d(e.c_messageEntityMention()); result.push_back(LinkInText(LinkInTextMention, d.voffset.v, d.vlength.v)); } break; + case mtpc_messageEntityBotCommand: { const MTPDmessageEntityBotCommand &d(e.c_messageEntityBotCommand()); result.push_back(LinkInText(LinkInTextBotCommand, d.voffset.v, d.vlength.v)); } break; + } + } + } + return result; +} +inline MTPVector linksToMTP(const LinksInText &links) { + MTPVector result(MTP_vector(0)); + QVector &v(result._vector().v); + for (int32 i = 0, s = links.size(); i != s; ++i) { + const LinkInText &l(links.at(i)); + switch (l.type) { + case LinkInTextUrl: v.push_back(MTP_messageEntityUrl(MTP_int(l.offset), MTP_int(l.length))); break; + case LinkInTextCustomUrl: v.push_back(MTP_messageEntityTextUrl(MTP_int(l.offset), MTP_int(l.length), MTP_string(l.text))); break; + case LinkInTextEmail: v.push_back(MTP_messageEntityEmail(MTP_int(l.offset), MTP_int(l.length))); break; + case LinkInTextHashtag: v.push_back(MTP_messageEntityHashtag(MTP_int(l.offset), MTP_int(l.length))); break; + case LinkInTextMention: v.push_back(MTP_messageEntityMention(MTP_int(l.offset), MTP_int(l.length))); break; + case LinkInTextBotCommand: v.push_back(MTP_messageEntityBotCommand(MTP_int(l.offset), MTP_int(l.length))); break; + } + } + return result; +} +LinksInText textParseLinks(const QString &text, int32 flags, bool rich = false); #include "gui/emoji_config.h" @@ -326,11 +369,7 @@ public: return _email; } - void onClick(Qt::MouseButton button) const { - if (button == Qt::LeftButton || button == Qt::MiddleButton) { - QDesktopServices::openUrl(qsl("mailto:") + _email); - } - } + void onClick(Qt::MouseButton button) const; const QString &readable() const { return _email; @@ -475,6 +514,7 @@ public: int32 countHeight(int32 width) const; void setText(style::font font, const QString &text, const TextParseOptions &options = _defaultOptions); void setRichText(style::font font, const QString &text, TextParseOptions options = _defaultOptions, const TextCustomTagsMap &custom = TextCustomTagsMap()); + void setMarkedText(style::font font, const QString &text, const LinksInText &links, const TextParseOptions &options = _defaultOptions); void setLink(uint16 lnkIndex, const TextLinkPtr &lnk); bool hasLinks() const; @@ -482,6 +522,9 @@ public: bool hasSkipBlock() const { return _blocks.isEmpty() ? false : _blocks.back()->type() == TextBlockSkip; } + void setSkipBlock(int32 width, int32 height); + void removeSkipBlock(); + LinksInText calcLinksInText() const; int32 maxWidth() const { return _maxWidth.ceil().toInt(); @@ -534,6 +577,8 @@ public: private: + void recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir = Qt::LayoutDirectionAuto); + QFixed _minResizeWidth, _maxWidth; int32 _minHeight; @@ -591,7 +636,7 @@ inline bool chIsSpace(QChar ch, bool rich = false) { return ch.isSpace() || (ch < 32 && !(rich && ch == TextCommand)) || (ch == QChar::ParagraphSeparator) || (ch == QChar::LineSeparator) || (ch == QChar::ObjectReplacementCharacter) || (ch == QChar::SoftHyphen) || (ch == QChar::CarriageReturn) || (ch == QChar::Tabulation); } inline bool chIsBad(QChar ch) { - return (ch == 0) || (ch >= 8232 && ch < 8239) || (ch >= 65024 && ch < 65040 && ch != 65039) || (ch >= 127 && ch < 160 && ch != 156); + return (ch == 0) || (ch >= 8232 && ch < 8237) || (ch >= 65024 && ch < 65040 && ch != 65039) || (ch >= 127 && ch < 160 && ch != 156); } inline bool chIsTrimmed(QChar ch, bool rich = false) { return (!rich || ch != TextCommand) && (chIsSpace(ch) || chIsBad(ch)); diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index a486510a7..512435906 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -110,15 +110,17 @@ namespace { return item ? item->toHistoryForwarded() : 0; } inline const TextParseOptions &itemTextParseOptions(HistoryItem *item) { - History *h = item->history(); - UserData *f = item->from(); - if ((!h->peer->chat && h->peer->asUser()->botInfo) || (!f->chat && f->asUser()->botInfo) || (h->peer->chat && h->peer->asChat()->botStatus >= 0)) { - return _historyBotOptions; - } - return _historyTextOptions; + return itemTextParseOptions(item->history(), item->from()); } } +const TextParseOptions &itemTextParseOptions(History *h, UserData *f) { + if ((!h->peer->chat && h->peer->asUser()->botInfo) || (!f->chat && f->asUser()->botInfo) || (h->peer->chat && h->peer->asChat()->botStatus >= 0)) { + return _historyBotOptions; + } + return _historyTextOptions; +} + void historyInit() { _initTextOptions(); } @@ -346,7 +348,7 @@ bool History::updateTyping(uint64 ms, uint32 dots, bool force) { ++i; } } - for (SendActionUsers::iterator i = sendActions.begin(), e = sendActions.end(); i != e;) { + for (SendActionUsers::iterator i = sendActions.begin(); i != sendActions.cend();) { if (ms >= i.value().until) { i = sendActions.erase(i); changed = true; @@ -643,7 +645,9 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPmessage &msg, boo const MTPMessageMedia *media = 0; switch (msg.type()) { - case mtpc_message: media = &msg.c_message().vmedia; break; + case mtpc_message: + media = msg.c_message().has_media() ? (&msg.c_message().vmedia) : 0; + break; } if (media) { existing->updateMedia(*media); @@ -659,7 +663,7 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPmessage &msg, boo case mtpc_message: { const MTPDmessage m(msg.c_message()); int badMedia = 0; // 1 - unsupported, 2 - empty - switch (m.vmedia.type()) { + if (m.has_media()) switch (m.vmedia.type()) { case mtpc_messageMediaEmpty: case mtpc_messageMediaContact: break; case mtpc_messageMediaGeo: @@ -886,6 +890,24 @@ void History::createInitialDateBlock(const QDateTime &date) { push_front(dateBlock); // date block } +void History::addToOverview(HistoryItem *item, MediaOverviewType type) { + if (_overviewIds[type].constFind(item->id) == _overviewIds[type].cend()) { + _overview[type].push_back(item->id); + _overviewIds[type].insert(item->id, NullType()); + if (_overviewCount[type] > 0) ++_overviewCount[type]; + if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, type); + } +} + +bool History::addToOverviewFront(HistoryItem *item, MediaOverviewType type) { + if (_overviewIds[type].constFind(item->id) == _overviewIds[type].cend()) { + _overview[type].push_front(item->id); + _overviewIds[type].insert(item->id, NullType()); + return true; + } + return false; +} + HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem *adding, bool newMsg) { if (!adding) { if (newBlock) delete to; @@ -926,23 +948,15 @@ HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem * HistoryMediaType mt = media->type(); MediaOverviewType t = mediaToOverviewType(mt); if (t != OverviewCount) { - if (_overviewIds[t].constFind(adding->id) == _overviewIds[t].cend()) { - _overview[t].push_back(adding->id); - _overviewIds[t].insert(adding->id, NullType()); - if (_overviewCount[t] > 0) ++_overviewCount[t]; - if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, t); - } + addToOverview(adding, t); if (mt == MediaTypeDocument && static_cast(media)->document()->song()) { - t = OverviewAudioDocuments; - if (_overviewIds[t].constFind(adding->id) == _overviewIds[t].cend()) { - _overview[t].push_back(adding->id); - _overviewIds[t].insert(adding->id, NullType()); - if (_overviewCount[t] > 0) ++_overviewCount[t]; - if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, t); - } + addToOverview(adding, OverviewAudioDocuments); } } } + if (adding->hasTextLinks()) { + addToOverview(adding, OverviewLinks); + } if (adding->from()->id) { if (peer->chat) { QList *lastAuthors = &(peer->asChat()->lastAuthors); @@ -1026,7 +1040,7 @@ void History::addToFront(const QVector &slice) { int32 addToH = 0, skip = 0; if (!isEmpty()) { - addToH = -front()->height; + if (width) addToH = -front()->height; pop_front(); // remove date block } HistoryItem *till = isEmpty() ? 0 : front()->front(), *prev = 0; @@ -1040,12 +1054,16 @@ void History::addToFront(const QVector &slice) { if (prev && prev->date.date() != adding->date.date()) { HistoryItem *dayItem = createDayServiceMsg(this, block, adding->date); block->push_back(dayItem); - dayItem->y = block->height; - block->height += dayItem->resize(width); + if (width) { + dayItem->y = block->height; + block->height += dayItem->resize(width); + } } block->push_back(adding); - adding->y = block->height; - block->height += adding->resize(width); + if (width) { + adding->y = block->height; + block->height += adding->resize(width); + } setMsgCount(msgCount + 1); prev = adding; } @@ -1054,8 +1072,10 @@ void History::addToFront(const QVector &slice) { if (till && prev && prev->date.date() != till->date.date()) { HistoryItem *dayItem = createDayServiceMsg(this, block, till->date); block->push_back(dayItem); - dayItem->y = block->height; - block->height += dayItem->resize(width); + if (width) { + dayItem->y = block->height; + block->height += dayItem->resize(width); + } } if (block->size()) { if (loadedAtBottom() && wasMsgCount < unreadCount && msgCount >= unreadCount) { @@ -1070,8 +1090,10 @@ void History::addToFront(const QVector &slice) { } } push_front(block); - addToH += block->height; - ++skip; + if (width) { + addToH += block->height; + ++skip; + } if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors int32 mask = 0; @@ -1083,21 +1105,15 @@ void History::addToFront(const QVector &slice) { HistoryMediaType mt = media->type(); MediaOverviewType t = mediaToOverviewType(mt); if (t != OverviewCount) { - if (_overviewIds[t].constFind(item->id) == _overviewIds[t].cend()) { - _overview[t].push_front(item->id); - _overviewIds[t].insert(item->id, NullType()); - mask |= (1 << t); - } + if (addToOverviewFront(item, t)) mask |= (1 << t); if (mt == MediaTypeDocument && static_cast(media)->document()->song()) { - t = OverviewAudioDocuments; - if (_overviewIds[t].constFind(item->id) == _overviewIds[t].cend()) { - _overview[t].push_front(item->id); - _overviewIds[t].insert(item->id, NullType()); - mask |= (1 << t); - } + if (addToOverviewFront(item, OverviewAudioDocuments)) mask |= (1 << OverviewAudioDocuments); } } } + if (item->hasTextLinks()) { + if (addToOverviewFront(item, OverviewLinks)) mask |= (1 << OverviewLinks); + } if (item->from()->id) { if (lastAuthors) { // chats if (!lastAuthors->contains(item->from())) { @@ -1150,16 +1166,18 @@ void History::addToFront(const QVector &slice) { HistoryBlock *dateBlock = new HistoryBlock(this); HistoryItem *dayItem = createDayServiceMsg(this, dateBlock, front()->front()->date); dateBlock->push_back(dayItem); - int32 dh = dayItem->resize(width); - dateBlock->height = dh; - if (skip) { - front()->y += dh; + if (width) { + int32 dh = dayItem->resize(width); + dateBlock->height = dh; + if (skip) { + front()->y += dh; + } + addToH += dh; + ++skip; } push_front(dateBlock); // date block - addToH += dh; - ++skip; } - if (addToH) { + if (width && addToH) { for (iterator i = begin(), e = end(); i != e; ++i) { if (skip) { --skip; @@ -1249,6 +1267,14 @@ void History::addToBack(const QVector &slice) { } } } + if (item->hasTextLinks()) { + MediaOverviewType t = OverviewLinks; + if (_overviewCount[t] != 0) { + _overview[t].push_back(item->id); + _overviewIds[t].insert(item->id, NullType()); + mask |= (1 << t); + } + } } } for (int32 t = 0; t < OverviewCount; ++t) { @@ -1311,7 +1337,7 @@ void History::setUnreadCount(int32 newUnreadCount, bool psUpdate) { App::histories().unreadFull += newUnreadCount - unreadCount; if (mute) App::histories().unreadMuted += newUnreadCount - unreadCount; unreadCount = newUnreadCount; - if (psUpdate) App::wnd()->updateCounter(); + if (psUpdate && (!mute || cIncludeMuted())) App::wnd()->updateCounter(); if (unreadBar) unreadBar->setCount(unreadCount); } } @@ -1760,6 +1786,9 @@ void HistoryItem::destroy() { history()->eraseFromOverview(OverviewAudioDocuments, id); } } + if (hasTextLinks()) { + history()->eraseFromOverview(OverviewLinks, id); + } delete this; } @@ -1976,19 +2005,37 @@ void HistoryPhoto::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x return fwd->getForwardedState(lnk, state, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right()); } } - height -= st::mediaPadding.bottom(); + height -= skipy + st::mediaPadding.bottom(); width -= st::mediaPadding.left() + st::mediaPadding.right(); if (!_caption.isEmpty()) { + int32 dateX = skipx + width + st::msgDateDelta.x() - parent->timeWidth(true) + st::msgDateSpace; + int32 dateY = _height - st::msgPadding.bottom() + st::msgDateDelta.y() - st::msgDateFont->height; + bool inDate = QRect(dateX, dateY, parent->timeWidth(true) - st::msgDateSpace, st::msgDateFont->height).contains(x, y); + if (inDate) { + state = HistoryInDateCursorState; + } + height -= _caption.countHeight(width) + st::webPagePhotoSkip; - if (x >= skipx && y >= height + st::webPagePhotoSkip && x < skipx + width && y < _height) { + if (x >= skipx && y >= skipy + height + st::webPagePhotoSkip && x < skipx + width && y < _height) { bool inText = false; - _caption.getState(lnk, inText, x - skipx, y - height - st::webPagePhotoSkip, width); - state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState; + _caption.getState(lnk, inText, x - skipx, y - skipy - height - st::webPagePhotoSkip, width); + state = inDate ? HistoryInDateCursorState : (inText ? HistoryInTextCursorState : HistoryDefaultCursorState); } } } - if (x >= skipx && y >= skipy && x < skipx + width && y < height) { + if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { lnk = openl; + if (_caption.isEmpty()) { + int32 dateX = skipx + width - parent->timeWidth(false) - st::msgDateImgDelta - st::msgDateImgPadding.x(); + int32 dateY = skipy + height - st::msgDateFont->height - st::msgDateImgDelta - st::msgDateImgPadding.y(); + if (parent->out()) { + dateX -= st::msgCheckRect.pxWidth() + st::msgDateImgCheckSpace; + } + bool inDate = QRect(dateX, dateY, parent->timeWidth(true) - st::msgDateSpace, st::msgDateFont->height).contains(x, y); + if (inDate) { + state = HistoryInDateCursorState; + } + } return; } } @@ -2230,15 +2277,11 @@ HistoryVideo::HistoryVideo(const MTPDvideo &video, const QString &caption, Histo int32 tw = data->thumb->width(), th = data->thumb->height(); if (data->thumb->isNull() || !tw || !th) { - _thumbw = _thumbx = _thumby = 0; + _thumbw = 0; } else if (tw > th) { _thumbw = (tw * st::mediaThumbSize) / th; - _thumbx = (_thumbw - st::mediaThumbSize) / 2; - _thumby = 0; } else { _thumbw = st::mediaThumbSize; - _thumbx = 0; - _thumby = ((th * _thumbw) / tw - st::mediaThumbSize) / 2; } } @@ -2387,6 +2430,13 @@ void HistoryVideo::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x } } + int32 dateX = width - st::msgPadding.right() + st::msgDateDelta.x() - parent->timeWidth(true) + st::msgDateSpace; + int32 dateY = height - st::msgPadding.bottom() + st::msgDateDelta.y() - st::msgDateFont->height; + bool inDate = QRect(dateX, dateY, parent->timeWidth(true) - st::msgDateSpace, st::msgDateFont->height).contains(x, y); + if (inDate) { + state = HistoryInDateCursorState; + } + int32 tw = width - st::mediaPadding.left() - st::mediaPadding.right(); if (x >= st::mediaPadding.left() && y >= skipy + st::mediaPadding.top() && x < st::mediaPadding.left() + tw && y < skipy + st::mediaPadding.top() + st::mediaThumbSize && !data->loader && data->access) { lnk = _openl; @@ -2395,7 +2445,7 @@ void HistoryVideo::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x if (!_caption.isEmpty() && x >= st::mediaPadding.left() && x < st::mediaPadding.left() + tw && y >= skipy + st::mediaPadding.top() + st::mediaThumbSize + st::webPagePhotoSkip) { bool inText = false; _caption.getState(lnk, inText, x - st::mediaPadding.left(), y - skipy - st::mediaPadding.top() - st::mediaThumbSize - st::webPagePhotoSkip, tw); - state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState; + state = inDate ? HistoryInDateCursorState : (inText ? HistoryInTextCursorState : HistoryDefaultCursorState); } } @@ -2883,6 +2933,14 @@ void HistoryAudio::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x if (x >= 0 && y >= skipy && x < width && y < _height && !data->loader && data->access) { lnk = _openl; + + int32 dateX = width - st::msgPadding.right() + st::msgDateDelta.x() - parent->timeWidth(true) + st::msgDateSpace; + int32 dateY = _height - st::msgPadding.bottom() + st::msgDateDelta.y() - st::msgDateFont->height; + bool inDate = QRect(dateX, dateY, parent->timeWidth(true) - st::msgDateSpace, st::msgDateFont->height).contains(x, y); + if (inDate) { + state = HistoryInDateCursorState; + } + return; } } @@ -2925,15 +2983,11 @@ HistoryDocument::HistoryDocument(DocumentData *document) : HistoryMedia() int32 tw = data->thumb->width(), th = data->thumb->height(); if (data->thumb->isNull() || !tw || !th) { - _thumbw = _thumbx = _thumby = 0; + _thumbw = 0; } else if (tw > th) { _thumbw = (tw * st::mediaThumbSize) / th; - _thumbx = (_thumbw - st::mediaThumbSize) / 2; - _thumby = 0; } else { _thumbw = st::mediaThumbSize; - _thumbx = 0; - _thumby = ((th * _thumbw) / tw - st::mediaThumbSize) / 2; } } @@ -3399,6 +3453,14 @@ void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int3 if (x >= 0 && y >= skipy && x < width && y < _height && !data->loader && data->access) { lnk = _openl; + + int32 dateX = width - st::msgPadding.right() + st::msgDateDelta.x() - parent->timeWidth(true) + st::msgDateSpace; + int32 dateY = _height - st::msgPadding.bottom() + st::msgDateDelta.y() - st::msgDateFont->height; + bool inDate = QRect(dateX, dateY, parent->timeWidth(true) - st::msgDateSpace, st::msgDateFont->height).contains(x, y); + if (inDate) { + state = HistoryInDateCursorState; + } + return; } } @@ -3408,17 +3470,7 @@ HistoryMedia *HistoryDocument::clone() const { } ImagePtr HistoryDocument::replyPreview() { - if (data->replyPreview->isNull() && !data->thumb->isNull()) { - if (data->thumb->loaded()) { - int w = data->thumb->width(), h = data->thumb->height(); - if (w <= 0) w = 1; - if (h <= 0) h = 1; - data->replyPreview = ImagePtr(w > h ? data->thumb->pix(w * st::msgReplyBarSize.height() / h, st::msgReplyBarSize.height()) : data->thumb->pix(st::msgReplyBarSize.height()), "PNG"); - } else { - data->thumb->load(); - } - } - return data->replyPreview; + return data->makeReplyPreview(); } HistorySticker::HistorySticker(DocumentData *document) : HistoryMedia() @@ -3581,6 +3633,10 @@ void HistorySticker::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 const HistoryReply *reply = toHistoryReply(parent); if (reply) { usew -= reply->replyToWidth(); + if (parent->out()) { + usex = width - usew; + } + int32 rw = width - usew, rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); int32 rx = parent->out() ? 0 : usew, ry = _height - rh; if (x >= rx && y >= ry && x < rx + rw && y < ry + rh) { @@ -3588,6 +3644,15 @@ void HistorySticker::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 return; } } + int32 dateX = usex + usew - parent->timeWidth(false) - st::msgDateImgDelta - st::msgDateImgPadding.x(); + int32 dateY = _height - st::msgDateFont->height - st::msgDateImgDelta - st::msgDateImgPadding.y(); + if (parent->out()) { + dateX -= st::msgCheckRect.pxWidth() + st::msgDateImgCheckSpace; + } + bool inDate = QRect(dateX, dateY, parent->timeWidth(true) - st::msgDateSpace, st::msgDateFont->height).contains(x, y); + if (inDate) { + state = HistoryInDateCursorState; + } } HistoryMedia *HistorySticker::clone() const { @@ -3599,18 +3664,14 @@ HistoryContact::HistoryContact(int32 userId, const QString &first, const QString , phone(App::formatPhone(phone)) , contact(App::userLoaded(userId)) { + App::regSharedContactPhone(userId, phone); + _maxw = st::mediaMaxWidth; name.setText(st::mediaFont, (first + ' ' + last).trimmed(), _textNameOptions); phonew = st::mediaFont->m.width(phone); if (contact) { - if (contact->phone.isEmpty()) { - contact->setPhone(phone); - } - if (contact->contact < 0) { - contact->contact = 0; - } contact->photo->load(); } } @@ -3811,13 +3872,16 @@ void HistoryContact::updateFrom(const MTPMessageMedia &media) { HistoryWebPage::HistoryWebPage(WebPageData *data) : HistoryMedia() , data(data) -, _openl(data->url.isEmpty() ? 0 : new TextLink(data->url)) -, _photol((data->photo && data->type != WebPageVideo) ? new PhotoLink(data->photo) : 0) +, _openl(0) +, _attachl(0) , _asArticle(false) , _title(st::msgMinWidth - st::webPageLeft) , _description(st::msgMinWidth - st::webPageLeft) , _siteNameWidth(0) , _durationWidth(0) +, _docNameWidth(0) +, _docThumbWidth(0) +, _docDownloadDone(0) , _pixw(0), _pixh(0) { } @@ -3831,7 +3895,9 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) { return; } if (!_openl && !data->url.isEmpty()) _openl = TextLinkPtr(new TextLink(data->url)); - if (!_photol && data->photo && data->type != WebPageVideo) _photol = TextLinkPtr(new PhotoLink(data->photo)); + if (!_attachl && data->photo && data->type != WebPageVideo) _attachl = TextLinkPtr(new PhotoLink(data->photo)); + if (!_attachl && data->doc) _attachl = TextLinkPtr(new DocumentOpenLink(data->doc)); + if (data->photo && data->type != WebPagePhoto && data->type != WebPageVideo) { if (data->type == WebPageProfile) { _asArticle = true; @@ -3843,6 +3909,7 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) { } else { _asArticle = false; } + if (_asArticle) { w = st::webPagePhotoSize; _maxw = st::webPageLeft + st::webPagePhotoSize; @@ -3869,6 +3936,31 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) { _maxw = st::webPageLeft + qMax(thumbh, qMax(w, int32(st::minPhotoSize))) + parent->timeWidth(true); _minh = qMax(thumbh, int32(st::minPhotoSize)); _minh += st::webPagePhotoSkip; + } else if (data->doc) { + if (!data->doc->thumb->isNull()) { + data->doc->thumb->load(); + + int32 tw = data->doc->thumb->width(), th = data->doc->thumb->height(); + if (data->doc->thumb->isNull() || !tw || !th) { + _docThumbWidth = 0; + } else if (tw > th) { + _docThumbWidth = (tw * st::mediaThumbSize) / th; + } else { + _docThumbWidth = st::mediaThumbSize; + } + } + _docName = documentName(data->doc); + _docSize = data->doc->song() ? formatDurationAndSizeText(data->doc->song()->duration, data->doc->size) : formatSizeText(data->doc->size); + _docNameWidth = st::mediaFont->m.width(_docName.isEmpty() ? qsl("Document") : _docName); + + if (parent == animated.msg) { + _maxw = st::webPageLeft + (animated.w / cIntRetinaFactor()) + parent->timeWidth(true); + _minh = animated.h / cIntRetinaFactor(); + _minh += st::webPagePhotoSkip; + } else { + _maxw = qMax(st::webPageLeft + st::mediaThumbSize + st::mediaPadding.right() + _docNameWidth + st::mediaPadding.right(), st::mediaMaxWidth); + _minh = st::mediaThumbSize; + } } else { _maxw = st::webPageLeft; _minh = 0; @@ -3912,7 +4004,7 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) { _minh += qMin(_description.minHeight(), 3 * st::webPageTitleFont->height); } } - if (!_asArticle && data->photo && (_siteNameWidth || !_title.isEmpty() || !_description.isEmpty())) { + if (!_asArticle && (data->photo || data->doc) && (_siteNameWidth || !_title.isEmpty() || !_description.isEmpty())) { _minh += st::webPagePhotoSkip; } if (data->type == WebPageVideo && data->duration) { @@ -3926,15 +4018,29 @@ void HistoryWebPage::draw(QPainter &p, const HistoryItem *parent, bool selected, if (width < 0) width = w; if (width < 1 || data->pendingTill) return; - int32 bottomSkip = 0; - //if (!data->pendingTill) { - if (data->photo) { - bottomSkip += st::webPagePhotoSkip; - if (_asArticle || (st::webPageLeft + qMax(_pixw, int16(st::minPhotoSize)) + parent->timeWidth(true) > width)) { - bottomSkip += (st::msgDateFont->height - st::msgDateDelta.y()); - } + int16 animw = 0, animh = 0; + if (data->doc && animated.msg == parent) { + animw = animated.w / cIntRetinaFactor(); + animh = animated.h / cIntRetinaFactor(); + if (width - st::webPageLeft < animw) { + animw = width - st::webPageLeft; + animh = (animw * animated.h / animated.w); + if (animh < 1) animh = 1; } - //} + } + + int32 bottomSkip = 0; + if (data->photo) { + bottomSkip += st::webPagePhotoSkip; + if (_asArticle || (st::webPageLeft + qMax(_pixw, int16(st::minPhotoSize)) + parent->timeWidth(true) > width)) { + bottomSkip += (st::msgDateFont->height - st::msgDateDelta.y()); + } + } else if (data->doc && animated.msg == parent) { + bottomSkip += st::webPagePhotoSkip; + if (st::webPageLeft + qMax(animw, int16(st::minPhotoSize)) + parent->timeWidth(true) > width) { + bottomSkip += (st::msgDateFont->height - st::msgDateDelta.y()); + } + } style::color bar = (selected ? (parent->out() ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (parent->out() ? st::msgOutReplyBarColor : st::msgInReplyBarColor)); style::color semibold = (selected ? (parent->out() ? st::msgOutServiceSelColor : st::msgInServiceSelColor) : (parent->out() ? st::msgOutServiceColor : st::msgInServiceColor)); @@ -4076,6 +4182,100 @@ void HistoryWebPage::draw(QPainter &p, const HistoryItem *parent, bool selected, } p.translate(0, pixheight); + } else if (!_asArticle && data->doc) { + if (_siteNameWidth || !_title.isEmpty() || !_description.isEmpty()) { + p.translate(0, st::webPagePhotoSkip); + } + + if (parent == animated.msg) { + p.drawPixmap(0, 0, animated.current(animw * cIntRetinaFactor(), animh * cIntRetinaFactor(), true)); + if (selected) { + App::roundRect(p, 0, 0, animw, animh, textstyleCurrent()->selectOverlay, SelectedOverlayCorners); + } + } else { + QString statusText; + if (data->doc->song()) { + SongMsgId playing; + AudioPlayerState playingState = AudioPlayerStopped; + int64 playingPosition = 0, playingDuration = 0; + int32 playingFrequency = 0; + if (audioPlayer()) { + audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency); + } + + bool already = !data->doc->already().isEmpty(), hasdata = !data->doc->data.isEmpty(); + QRect img; + if (data->doc->status == FileFailed) { + statusText = lang(lng_attach_failed); + img = parent->out() ? st::mediaMusicOutImg : st::mediaMusicInImg; + } else if (already || hasdata) { + bool showPause = false; + if (playing.msgId == parent->id && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) { + statusText = formatDurationText(playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency)) + qsl(" / ") + formatDurationText(playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency)); + showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting); + } else { + statusText = formatDurationText(data->doc->song()->duration); + } + if (!showPause && playing.msgId == parent->id && App::main() && App::main()->player()->seekingSong(playing)) showPause = true; + img = parent->out() ? (showPause ? st::mediaPauseOutImg : st::mediaPlayOutImg) : (showPause ? st::mediaPauseInImg : st::mediaPlayInImg); + } else { + if (data->doc->loader) { + int32 offset = data->doc->loader->currentOffset(); + if (_docDownloadTextCache.isEmpty() || _docDownloadDone != offset) { + _docDownloadDone = offset; + _docDownloadTextCache = formatDownloadText(_docDownloadDone, data->doc->size); + } + statusText = _docDownloadTextCache; + } else { + statusText = _docSize; + } + img = parent->out() ? st::mediaMusicOutImg : st::mediaMusicInImg; + } + + p.drawPixmap(QPoint(0, 0), App::sprite(), img); + } else { + if (data->doc->status == FileFailed) { + statusText = lang(lng_attach_failed); + } else if (data->doc->loader) { + int32 offset = data->doc->loader->currentOffset(); + if (_docDownloadTextCache.isEmpty() || _docDownloadDone != offset) { + _docDownloadDone = offset; + _docDownloadTextCache = formatDownloadText(_docDownloadDone, data->doc->size); + } + statusText = _docDownloadTextCache; + } else { + statusText = _docSize; + } + + if (_docThumbWidth) { + data->doc->thumb->checkload(); + p.drawPixmap(QPoint(0, 0), data->doc->thumb->pixSingle(_docThumbWidth, 0, st::mediaThumbSize, st::mediaThumbSize)); + } else { + p.drawPixmap(QPoint(0, 0), App::sprite(), (parent->out() ? st::mediaDocOutImg : st::mediaDocInImg)); + } + } + if (selected) { + App::roundRect(p, 0, 0, st::mediaThumbSize, st::mediaThumbSize, textstyleCurrent()->selectOverlay, SelectedOverlayCorners); + } + + int32 tleft = st::mediaPadding.left() + st::mediaThumbSize + st::mediaPadding.right(); + int32 twidth = width - tleft - st::mediaPadding.right(); + int32 fullTimeWidth = parent->timeWidth(true) + st::msgPadding.right(); + int32 secondwidth = width - tleft - fullTimeWidth; + + p.setFont(st::mediaFont->f); + p.setPen(st::black->c); + if (twidth < _docNameWidth) { + p.drawText(tleft, st::mediaNameTop + st::mediaFont->ascent, st::mediaFont->m.elidedText(_docName, Qt::ElideRight, twidth)); + } else { + p.drawText(tleft, st::mediaNameTop + st::mediaFont->ascent, _docName); + } + + style::color status(selected ? (parent->out() ? st::mediaOutSelectColor : st::mediaInSelectColor) : (parent->out() ? st::mediaOutColor : st::mediaInColor)); + p.setPen(status->p); + + p.drawText(tleft, st::mediaThumbSize - st::mediaDetailsShift - st::mediaFont->descent, statusText); + } } p.restore(); @@ -4108,7 +4308,7 @@ int32 HistoryWebPage::resize(int32 width, bool dontRecountText, const HistoryIte _height = st::webPagePhotoSize; _height += st::webPagePhotoSkip + (st::msgDateFont->height - st::msgDateDelta.y()); } else if (data->photo) { - _pixw = qMin(width, int32(_maxw - st::webPageLeft)); + _pixw = qMin(width, int32(_maxw - st::webPageLeft - parent->timeWidth(true))); int32 tw = convertScale(data->photo->full->width()), th = convertScale(data->photo->full->height()); if (tw > st::maxMediaSize) { @@ -4136,6 +4336,24 @@ int32 HistoryWebPage::resize(int32 width, bool dontRecountText, const HistoryIte if (qMax(_pixw, int16(st::minPhotoSize)) + parent->timeWidth(true) > width) { _height += (st::msgDateFont->height - st::msgDateDelta.y()); } + } else if (data->doc) { + if (parent == animated.msg) { + int32 w = qMin(width, int32(animated.w / cIntRetinaFactor())); + if (w > st::maxMediaSize) { + w = st::maxMediaSize; + } + _height = animated.h / cIntRetinaFactor(); + if (animated.w / cIntRetinaFactor() > w) { + _height = (w * _height / (animated.w / cIntRetinaFactor())); + if (_height <= 0) _height = 1; + } + _height += st::webPagePhotoSkip; + if (w + parent->timeWidth(true) > width) { + _height += (st::msgDateFont->height - st::msgDateDelta.y()); + } + } else { + _height = st::mediaThumbSize; + } } else { _height = 0; } @@ -4150,7 +4368,7 @@ int32 HistoryWebPage::resize(int32 width, bool dontRecountText, const HistoryIte if (!_description.isEmpty()) { _height += qMin(_description.countHeight(width), st::webPageDescriptionFont->height * 3); } - if (data->photo && (_siteNameWidth || !_title.isEmpty() || !_description.isEmpty())) { + if ((data->photo || data->doc) && (_siteNameWidth || !_title.isEmpty() || !_description.isEmpty())) { _height += st::webPagePhotoSkip; } } @@ -4160,10 +4378,12 @@ int32 HistoryWebPage::resize(int32 width, bool dontRecountText, const HistoryIte void HistoryWebPage::regItem(HistoryItem *item) { App::regWebPageItem(data, item); + if (data->doc) App::regDocumentItem(data->doc, item); } void HistoryWebPage::unregItem(HistoryItem *item) { App::unregWebPageItem(data, item); + if (data->doc) App::unregDocumentItem(data->doc, item); } const QString HistoryWebPage::inDialogsText() const { @@ -4235,10 +4455,20 @@ void HistoryWebPage::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 y -= st::webPagePhotoSkip; } if (!_asArticle) { - int32 pixwidth = qMax(_pixw, int16(st::minPhotoSize)), pixheight = qMax(_pixh, int16(st::minPhotoSize)); - if (x >= 0 && y >= 0 && x < pixwidth && y < pixheight) { - lnk = _photol ? _photol : _openl; - return; + if (data->doc && parent == animated.msg) { + int32 h = (width == w) ? _height : (width * animated.h / animated.w); + if (h < 1) h = 1; + if (x >= 0 && y >= 0 && x < width && y < h) { + lnk = _attachl; + return; + } + } else { + int32 attachwidth = data->doc ? (width - st::mediaPadding.right()) : qMax(_pixw, int16(st::minPhotoSize)); + int32 attachheight = data->doc ? st::mediaThumbSize : qMax(_pixh, int16(st::minPhotoSize)); + if (x >= 0 && y >= 0 && x < attachwidth && y < attachheight) { + lnk = _attachl ? _attachl : _openl; + return; + } } } } @@ -4248,7 +4478,7 @@ HistoryMedia *HistoryWebPage::clone() const { } ImagePtr HistoryWebPage::replyPreview() { - return data->photo ? data->photo->makeReplyPreview() : ImagePtr(); + return data->photo ? data->photo->makeReplyPreview() : (data->doc ? data->doc->makeReplyPreview() : ImagePtr()); } namespace { @@ -4974,11 +5204,22 @@ void HistoryImageLink::getState(TextLinkPtr &lnk, HistoryCursorState &state, int return fwd->getForwardedState(lnk, state, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right()); } } - height -= st::mediaPadding.bottom(); + height -= skipy + st::mediaPadding.bottom(); width -= st::mediaPadding.left() + st::mediaPadding.right(); } - if (x >= skipx && y >= skipy && x < skipx + width && y < height && data) { + if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height && data) { lnk = link; + + int32 dateX = skipx + width - parent->timeWidth(false) - st::msgDateImgDelta - st::msgDateImgPadding.x(); + int32 dateY = skipy + height - st::msgDateFont->height - st::msgDateImgDelta - st::msgDateImgPadding.y(); + if (parent->out()) { + dateX -= st::msgCheckRect.pxWidth() + st::msgDateImgCheckSpace; + } + bool inDate = QRect(dateX, dateY, parent->timeWidth(true) - st::msgDateSpace, st::msgDateFont->height).contains(x, y); + if (inDate) { + state = HistoryInDateCursorState; + } + return; } } @@ -4996,11 +5237,11 @@ HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, const MTPD { QString text(textClean(qs(msg.vmessage))); initTime(); - initMedia(msg.vmedia, text); - initDimensions(text); + initMedia(msg.has_media() ? (&msg.vmedia) : 0, text); + setText(text, msg.has_entities() ? linksFromMTP(msg.ventities.c_vector().v) : LinksInText()); } -HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const MTPMessageMedia &media) : +HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const LinksInText &links, const MTPMessageMedia *media) : HistoryItem(history, block, msgId, flags, date, from) , _text(st::msgMinWidth) , _textWidth(0) @@ -5010,10 +5251,10 @@ HistoryItem(history, block, msgId, flags, date, from) QString text(msg); initTime(); initMedia(media, text); - initDimensions(text); + setText(text, links); } -HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, HistoryMedia *fromMedia) : +HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const LinksInText &links, HistoryMedia *fromMedia) : HistoryItem(history, block, msgId, flags, date, from) , _text(st::msgMinWidth) , _textWidth(0) @@ -5025,7 +5266,7 @@ HistoryItem(history, block, msgId, flags, date, from) _media = fromMedia->clone(); _media->regItem(this); } - initDimensions(msg); + setText(msg, links); } HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, DocumentData *doc) : @@ -5037,7 +5278,7 @@ HistoryItem(history, block, msgId, flags, date, from) { initTime(); initMediaFromDocument(doc); - initDimensions(QString()); + setText(QString(), LinksInText()); } void HistoryMessage::initTime() { @@ -5045,53 +5286,53 @@ void HistoryMessage::initTime() { _timeWidth = st::msgDateFont->m.width(_time); } -void HistoryMessage::initMedia(const MTPMessageMedia &media, QString ¤tText) { - switch (media.type()) { +void HistoryMessage::initMedia(const MTPMessageMedia *media, QString ¤tText) { + switch (media ? media->type() : mtpc_messageMediaEmpty) { case mtpc_messageMediaContact: { - const MTPDmessageMediaContact &d(media.c_messageMediaContact()); + const MTPDmessageMediaContact &d(media->c_messageMediaContact()); _media = new HistoryContact(d.vuser_id.v, qs(d.vfirst_name), qs(d.vlast_name), qs(d.vphone_number)); } break; case mtpc_messageMediaGeo: { - const MTPGeoPoint &point(media.c_messageMediaGeo().vgeo); + const MTPGeoPoint &point(media->c_messageMediaGeo().vgeo); if (point.type() == mtpc_geoPoint) { const MTPDgeoPoint &d(point.c_geoPoint()); _media = new HistoryImageLink(qsl("location:%1,%2").arg(d.vlat.v).arg(d.vlong.v)); } } break; case mtpc_messageMediaVenue: { - const MTPDmessageMediaVenue &d(media.c_messageMediaVenue()); + const MTPDmessageMediaVenue &d(media->c_messageMediaVenue()); if (d.vgeo.type() == mtpc_geoPoint) { const MTPDgeoPoint &g(d.vgeo.c_geoPoint()); _media = new HistoryImageLink(qsl("location:%1,%2").arg(g.vlat.v).arg(g.vlong.v), qs(d.vtitle), qs(d.vaddress)); } } break; case mtpc_messageMediaPhoto: { - const MTPDmessageMediaPhoto &photo(media.c_messageMediaPhoto()); + const MTPDmessageMediaPhoto &photo(media->c_messageMediaPhoto()); if (photo.vphoto.type() == mtpc_photo) { _media = new HistoryPhoto(photo.vphoto.c_photo(), qs(photo.vcaption), this); } } break; case mtpc_messageMediaVideo: { - const MTPDmessageMediaVideo &video(media.c_messageMediaVideo()); + const MTPDmessageMediaVideo &video(media->c_messageMediaVideo()); if (video.vvideo.type() == mtpc_video) { _media = new HistoryVideo(video.vvideo.c_video(), qs(video.vcaption), this); } } break; case mtpc_messageMediaAudio: { - const MTPAudio &audio(media.c_messageMediaAudio().vaudio); + const MTPAudio &audio(media->c_messageMediaAudio().vaudio); if (audio.type() == mtpc_audio) { _media = new HistoryAudio(audio.c_audio()); } } break; case mtpc_messageMediaDocument: { - const MTPDocument &document(media.c_messageMediaDocument().vdocument); + const MTPDocument &document(media->c_messageMediaDocument().vdocument); if (document.type() == mtpc_document) { DocumentData *doc = App::feedDocument(document); return initMediaFromDocument(doc); } } break; case mtpc_messageMediaWebPage: { - const MTPWebPage &d(media.c_messageMediaWebPage().vwebpage); + const MTPWebPage &d(media->c_messageMediaWebPage().vwebpage); switch (d.type()) { case mtpc_webPageEmpty: initMediaFromText(currentText); break; case mtpc_webPagePending: { @@ -5125,16 +5366,6 @@ void HistoryMessage::initMediaFromDocument(DocumentData *doc) { _media->regItem(this); } -void HistoryMessage::initDimensions(const QString &text) { - if (!_media || !text.isEmpty()) { // !justMedia() - if (_media && _media->isDisplayed()) { - _text.setText(st::msgFont, text, itemTextParseOptions(this)); - } else { - _text.setText(st::msgFont, text + textcmdSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()), itemTextParseOptions(this)); - } - } -} - void HistoryMessage::initDimensions(const HistoryItem *parent) { if (justMedia()) { _media->initDimensions(this); @@ -5147,19 +5378,13 @@ void HistoryMessage::initDimensions(const HistoryItem *parent) { if (_media) { _media->initDimensions(this); if (_media->isDisplayed() && _text.hasSkipBlock()) { - QString was = HistoryMessage::selectedText(FullItemSel); - if (!was.isEmpty()) { - _text.setText(st::msgFont, was, itemTextParseOptions(this)); // without date skip - _textWidth = 0; - _textHeight = 0; - } + _text.removeSkipBlock(); + _textWidth = 0; + _textHeight = 0; } else if (!_media->isDisplayed() && !_text.hasSkipBlock()) { - QString was = HistoryMessage::selectedText(FullItemSel); - if (!was.isEmpty()) { - _text.setText(st::msgFont, was + textcmdSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()), itemTextParseOptions(this)); // without date skip - _textWidth = 0; - _textHeight = 0; - } + _text.setSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()); + _textWidth = 0; + _textHeight = 0; } if (_media->isDisplayed()) { int32 maxw = _media->maxWidth() + st::msgPadding.left() + st::msgPadding.right(); @@ -5191,6 +5416,10 @@ QString HistoryMessage::selectedText(uint32 selection) const { return _text.original(selectedFrom, selectedTo); } +LinksInText HistoryMessage::textLinks() const { + return _text.calcLinksInText(); +} + QString HistoryMessage::inDialogsText() const { QString result = _media ? _media->inDialogsText() : QString(); return result.isEmpty() ? _text.original(0, 0xFFFF, false) : result; @@ -5200,8 +5429,9 @@ HistoryMedia *HistoryMessage::getMedia(bool inOverview) const { return _media; } -void HistoryMessage::setMedia(const MTPmessageMedia &media) { - if ((!_media || _media->isImageLink()) && media.type() == mtpc_messageMediaEmpty) return; +void HistoryMessage::setMedia(const MTPMessageMedia *media) { + if ((!_media || _media->isImageLink()) && (!media || media->type() == mtpc_messageMediaEmpty)) return; + bool mediaWasDisplayed = false; if (_media) { mediaWasDisplayed = _media->isDisplayed(); @@ -5211,24 +5441,48 @@ void HistoryMessage::setMedia(const MTPmessageMedia &media) { QString t; initMedia(media, t); if (_media && _media->isDisplayed() && !mediaWasDisplayed) { - QString was = HistoryMessage::selectedText(FullItemSel); - if (!was.isEmpty()) { - _text.setText(st::msgFont, was, itemTextParseOptions(this)); // without date skip - _textWidth = 0; - _textHeight = 0; - } + _text.removeSkipBlock(); + _textWidth = 0; + _textHeight = 0; } else if (mediaWasDisplayed && (!_media || !_media->isDisplayed())) { - QString was = HistoryMessage::selectedText(FullItemSel); - if (!was.isEmpty()) { - _text.setText(st::msgFont, was + textcmdSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()), itemTextParseOptions(this)); // without date skip - _textWidth = 0; - _textHeight = 0; - } + _text.setSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()); + _textWidth = 0; + _textHeight = 0; } initDimensions(0); if (App::main()) App::main()->itemResized(this); } +void HistoryMessage::setText(const QString &text, const LinksInText &links) { + if (!_media || !text.isEmpty()) { // !justMedia() + if (_media && _media->isDisplayed()) { + _text.setMarkedText(st::msgFont, text, links, itemTextParseOptions(this)); + } else { + _text.setMarkedText(st::msgFont, text + textcmdSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()), links, itemTextParseOptions(this)); + } + if (id > 0) { + for (int32 i = 0, l = links.size(); i != l; ++i) { + if (links.at(i).type == LinkInTextUrl || links.at(i).type == LinkInTextCustomUrl || links.at(i).type == LinkInTextEmail) { + _flags |= MTPDmessage_flag_HAS_TEXT_LINKS; + break; + } + } + } + _textWidth = 0; + _textHeight = 0; + } +} + +void HistoryMessage::getTextWithLinks(QString &text, LinksInText &links) { + if (_text.isEmpty()) return; + links = _text.calcLinksInText(); + text = _text.original(); +} + +bool HistoryMessage::textHasLinks() { + return _text.hasLinks(); +} + void HistoryMessage::draw(QPainter &p, uint32 selection) const { textstyleSet(&(out() ? st::outTextStyle : st::inTextStyle)); @@ -5333,6 +5587,8 @@ void HistoryMessage::drawMessageText(QPainter &p, const QRect &trect, uint32 sel } int32 HistoryMessage::resize(int32 width, bool dontRecountText, const HistoryItem *parent) { + if (width < st::msgMinWidth) return _height; + width -= st::msgMargin.left() + st::msgMargin.right(); if (justMedia()) { _height = _media->resize(width, dontRecountText, this); @@ -5538,7 +5794,7 @@ HistoryMessage::~HistoryMessage() { } } -HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.vfrom_id.v, textClean(qs(msg.vmessage)), msg.vmedia) +HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.vfrom_id.v, textClean(qs(msg.vmessage)), msg.has_entities() ? linksFromMTP(msg.ventities.c_vector().v) : LinksInText(), msg.has_media() ? (&msg.vmedia) : 0) , fwdDate(::date(msg.vfwd_date)) , fwdFrom(App::user(msg.vfwd_from_id.v)) , fwdFromVersion(fwdFrom->nameVersion) @@ -5547,7 +5803,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const fwdNameUpdated(); } -HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, HistoryMessage *msg) : HistoryMessage(history, block, id, ((history->peer->input.type() != mtpc_inputPeerSelf) ? (MTPDmessage_flag_out | MTPDmessage_flag_unread) : 0) | (msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage_flag_media_unread : 0), ::date(unixtime()), MTP::authedId(), msg->justMedia() ? QString() : msg->HistoryMessage::selectedText(FullItemSel), msg->getMedia()) +HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, HistoryMessage *msg) : HistoryMessage(history, block, id, ((history->peer->input.type() != mtpc_inputPeerSelf) ? (MTPDmessage_flag_out | MTPDmessage_flag_unread) : 0) | (msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage_flag_media_unread : 0), ::date(unixtime()), MTP::authedId(), msg->justMedia() ? QString() : msg->HistoryMessage::selectedText(FullItemSel), msg->HistoryMessage::textLinks(), msg->getMedia()) , fwdDate(msg->dateForwarded()) , fwdFrom(msg->fromForwarded()) , fwdFromVersion(fwdFrom->nameVersion) @@ -5734,7 +5990,7 @@ void HistoryForwarded::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 return HistoryMessage::getSymbol(symbol, after, upon, x, y); } -HistoryReply::HistoryReply(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.vfrom_id.v, textClean(qs(msg.vmessage)), msg.vmedia) +HistoryReply::HistoryReply(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.vfrom_id.v, textClean(qs(msg.vmessage)), msg.has_entities() ? linksFromMTP(msg.ventities.c_vector().v) : LinksInText(), msg.has_media() ? (&msg.vmedia) : 0) , replyToMsgId(msg.vreply_to_msg_id.v) , replyToMsg(0) , replyToVersion(0) diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 1379928b5..e696535a4 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -107,6 +107,7 @@ enum MediaOverviewType { OverviewDocuments, OverviewAudios, OverviewAudioDocuments, + OverviewLinks, OverviewCount }; @@ -116,7 +117,7 @@ inline MediaOverviewType mediaToOverviewType(HistoryMediaType t) { case MediaTypePhoto: return OverviewPhotos; case MediaTypeVideo: return OverviewVideos; case MediaTypeDocument: return OverviewDocuments; - // case MediaTypeSticker: return OverviewDocuments; +// case MediaTypeSticker: return OverviewDocuments; case MediaTypeAudio: return OverviewAudios; } return OverviewCount; @@ -129,6 +130,7 @@ inline MTPMessagesFilter typeToMediaFilter(MediaOverviewType &type) { case OverviewDocuments: return MTP_inputMessagesFilterDocument(); case OverviewAudios: return MTP_inputMessagesFilterAudio(); case OverviewAudioDocuments: return MTP_inputMessagesFilterAudioDocuments(); + case OverviewLinks: return MTP_inputMessagesFilterUrl(); default: type = OverviewCount; break; } return MTPMessagesFilter(); @@ -183,6 +185,8 @@ struct History : public QList { void addToBack(const QVector &slice); void createInitialDateBlock(const QDateTime &date); HistoryItem *doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem *adding, bool newMsg); + void addToOverview(HistoryItem *item, MediaOverviewType type); + bool addToOverviewFront(HistoryItem *item, MediaOverviewType type); void newItemAdded(HistoryItem *item); void unregTyping(UserData *from); @@ -723,6 +727,9 @@ public: bool hasReplyMarkup() const { return _flags & MTPDmessage::flag_reply_markup; } + bool hasTextLinks() const { + return _flags & MTPDmessage_flag_HAS_TEXT_LINKS; + } virtual bool needCheck() const { return true; } @@ -773,7 +780,14 @@ public: virtual HistoryMedia *getMedia(bool inOverview = false) const { return 0; } - virtual void setMedia(const MTPmessageMedia &media) { + virtual void setMedia(const MTPMessageMedia *media) { + } + virtual void setText(const QString &text, const LinksInText &links) { + } + virtual void getTextWithLinks(QString &text, LinksInText &links) { + } + virtual bool textHasLinks() { + return false; } virtual QString time() const { return QString(); @@ -989,7 +1003,7 @@ private: Text _caption; QString _size; - int32 _thumbw, _thumbx, _thumby; + int32 _thumbw; mutable QString _dldTextCache, _uplTextCache; mutable int32 _dldDone, _uplDone; @@ -1170,20 +1184,26 @@ public: void unregItem(HistoryItem *item); bool hasReplyPreview() const { - return data->photo && !data->photo->thumb->isNull(); + return (data->photo && !data->photo->thumb->isNull()) || (data->doc && !data->doc->thumb->isNull()); } ImagePtr replyPreview(); + WebPageData *webpage() { + return data; + } + private: WebPageData *data; - TextLinkPtr _openl, _photol; + TextLinkPtr _openl, _attachl; bool _asArticle; Text _title, _description; int32 _siteNameWidth; - QString _duration; - int32 _durationWidth; + QString _duration, _docName, _docSize; + int32 _durationWidth, _docNameWidth, _docThumbWidth; + mutable QString _docDownloadTextCache; + mutable int32 _docDownloadDone; int16 _pixw, _pixh; }; @@ -1274,16 +1294,15 @@ class HistoryMessage : public HistoryItem { public: HistoryMessage(History *history, HistoryBlock *block, const MTPDmessage &msg); - HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const MTPMessageMedia &media); - HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, HistoryMedia *media); + HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const LinksInText &links, const MTPMessageMedia *media); + HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const LinksInText &links, HistoryMedia *media); HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, DocumentData *doc); void initTime(); - void initMedia(const MTPMessageMedia &media, QString ¤tText); + void initMedia(const MTPMessageMedia *media, QString ¤tText); void initMediaFromText(QString ¤tText); void initMediaFromDocument(DocumentData *doc); void initDimensions(const HistoryItem *parent = 0); - void initDimensions(const QString &text); void fromNameUpdated() const; bool justMedia() const { @@ -1317,9 +1336,13 @@ public: } QString selectedText(uint32 selection) const; + LinksInText textLinks() const; QString inDialogsText() const; HistoryMedia *getMedia(bool inOverview = false) const; - void setMedia(const MTPmessageMedia &media); + void setMedia(const MTPMessageMedia *media); + void setText(const QString &text, const LinksInText &links); + void getTextWithLinks(QString &text, LinksInText &links); + bool textHasLinks(); QString time() const { return _time; @@ -1554,3 +1577,5 @@ protected: QString text; bool freezed; }; + +const TextParseOptions &itemTextParseOptions(History *h, UserData *f); diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index b022f64c2..eaa3f4ca7 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -559,10 +559,10 @@ void HistoryList::onDragExec() { QDrag *drag = new QDrag(App::wnd()); QMimeData *mimeData = new QMimeData; - if (dragSticker || dragByDate) { - mimeData->setData(qsl("application/x-td-forward-pressed"), "1"); - } else { + if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument || lnkContact) { mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1"); + } else { + mimeData->setData(qsl("application/x-td-forward-pressed"), "1"); } if (lnkDocument) { QString already = static_cast(textlnkDown().data())->document()->already(true); @@ -1346,7 +1346,6 @@ void HistoryList::onUpdateSelected() { if (_dragItem && _dragItem->detached()) { dragActionCancel(); } - linkTipTimer.start(1000); Qt::CursorShape cur = style::cur_default; HistoryCursorState cursorState = HistoryDefaultCursorState; @@ -1373,7 +1372,7 @@ void HistoryList::onUpdateSelected() { } } textlnkOver(lnk); - QToolTip::showText(_dragPos, QString(), App::wnd()); + QToolTip::hideText(); App::hoveredLinkItem((lnk && !lnkInDesc) ? item : 0); if (textlnkOver()) { if (App::hoveredLinkItem()) { @@ -1383,6 +1382,12 @@ void HistoryList::onUpdateSelected() { } } } + if (lnk || cursorState == HistoryInDateCursorState) { + linkTipTimer.start(1000); + } + if (_dragCursorState == HistoryInDateCursorState && cursorState != HistoryInDateCursorState) { + QToolTip::hideText(); + } if (_dragAction == NoDrag) { _dragCursorState = cursorState; @@ -1544,8 +1549,15 @@ void HistoryList::applyDragSelection(SelectedItems *toItems) const { void HistoryList::showLinkTip() { TextLinkPtr lnk = textlnkOver(); + int32 dd = QApplication::startDragDistance(); + QPoint dp(mapFromGlobal(_dragPos)); + QRect r(dp.x() - dd, dp.y() - dd, 2 * dd, 2 * dd); if (lnk && !lnk->fullDisplayed()) { - QToolTip::showText(_dragPos, lnk->readable(), App::wnd()); + QToolTip::showText(_dragPos, lnk->readable(), this, r); + } else if (_dragCursorState == HistoryInDateCursorState && _dragAction == NoDrag) { + if (App::hoveredItem()) { + QToolTip::showText(_dragPos, App::hoveredItem()->date.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat)), this, r); + } } } @@ -1873,7 +1885,10 @@ void BotKeyboard::showCommandTip() { if (_sel >= 0) { int row = (_sel / MatrixRowShift), col = _sel % MatrixRowShift; if (!_btns.at(row).at(col).full) { - QToolTip::showText(_lastMousePos, _btns.at(row).at(col).cmd); + int32 dd = QApplication::startDragDistance(); + QPoint dp(mapFromGlobal(_lastMousePos)); + QRect r(dp.x() - dd, dp.y() - dd, 2 * dd, 2 * dd); + QToolTip::showText(_lastMousePos, _btns.at(row).at(col).cmd, this, r); } } } @@ -1899,7 +1914,7 @@ void BotKeyboard::updateSelected() { if (newSel >= 0) break; } if (newSel != _sel) { - QToolTip::showText(_lastMousePos, QString(), App::wnd()); + QToolTip::hideText(); if (newSel < 0) { setCursor(style::cur_default); } else if (_sel < 0) { @@ -2712,19 +2727,17 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) { bool canShowNow = _history->isReadyFor(showAtMsgId, true); if (!canShowNow) { delayedShowAt(showAtMsgId); - return; + } else { + clearDelayedShowAt(); + if (_replyReturn && _replyReturn->id == showAtMsgId) { + calcNextReplyReturn(); + } + + _showAtMsgId = showAtMsgId; + _histInited = false; + + historyLoaded(); } - - clearDelayedShowAt(); - if (_replyReturn && _replyReturn->id == showAtMsgId) { - calcNextReplyReturn(); - } - - _showAtMsgId = showAtMsgId; - _histInited = false; - - historyLoaded(); - emit peerShown(_peer); App::main()->topBar()->update(); update(); @@ -3049,6 +3062,24 @@ void HistoryWidget::updateControlsVisibility() { resizeEvent(0); update(); } + } else { + _attachMention.hide(); + _send.hide(); + _unblock.hide(); + _botStart.hide(); + _attachDocument.hide(); + _attachPhoto.hide(); + _attachEmoji.hide(); + _kbShow.hide(); + _kbHide.hide(); + _cmdStart.hide(); + _attachType.hide(); + _emojiPan.hide(); + if (!_field.isHidden()) { + _field.hide(); + resizeEvent(0); + update(); + } } } @@ -3416,7 +3447,7 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const fastShowAtEnd(h); PeerData *p = App::peer(peer); - int32 flags = newMessageFlags(p); // unread, out + int32 flags = newMessageFlags(p) | MTPDmessage::flag_media; // unread, out bool lastKeyboardUsed = lastForceReplyReplied(replyTo); @@ -4296,14 +4327,15 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) { fastShowAtEnd(h); - int32 flags = newMessageFlags(h->peer); // unread, out + int32 flags = newMessageFlags(h->peer) | MTPDmessage::flag_media; // unread, out if (img.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id; if (img.type == ToPreparePhoto) { h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(img.photo, MTP_string("")), MTPnullMarkup, MTPnullEntities)); } else if (img.type == ToPrepareDocument) { h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup, MTPnullEntities)); } else if (img.type == ToPrepareAudio) { - h->addToBack(MTP_message(MTP_int(flags | MTPDmessage_flag_media_unread), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup, MTPnullEntities)); + flags |= MTPDmessage_flag_media_unread; + h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup, MTPnullEntities)); } if (_peer && img.peer == _peer->id) { @@ -4902,7 +4934,7 @@ void HistoryWidget::onStickerSend(DocumentData *sticker) { bool lastKeyboardUsed = lastForceReplyReplied(); bool out = (_peer->input.type() != mtpc_inputPeerSelf), unread = (_peer->input.type() != mtpc_inputPeerSelf); - int32 flags = newMessageFlags(_peer); // unread, out + int32 flags = newMessageFlags(_peer) | MTPDmessage::flag_media; // unread, out int32 sendFlags = 0; if (replyToId()) { flags |= MTPDmessage::flag_reply_to_msg_id; @@ -5114,18 +5146,25 @@ void HistoryWidget::updatePreview() { if (_previewData->title.isEmpty()) { if (_previewData->description.isEmpty()) { title = _previewData->author; - desc = _previewData->url; + desc = ((_previewData->doc && !_previewData->doc->name.isEmpty()) ? _previewData->doc->name : _previewData->url); } else { title = _previewData->description; - desc = _previewData->author.isEmpty() ? _previewData->url : _previewData->author; + desc = _previewData->author.isEmpty() ? ((_previewData->doc && !_previewData->doc->name.isEmpty()) ? _previewData->doc->name : _previewData->url) : _previewData->author; } } else { title = _previewData->title; - desc = _previewData->description.isEmpty() ? (_previewData->author.isEmpty() ? _previewData->url : _previewData->author) : _previewData->description; + desc = _previewData->description.isEmpty() ? (_previewData->author.isEmpty() ? ((_previewData->doc && !_previewData->doc->name.isEmpty()) ? _previewData->doc->name : _previewData->url) : _previewData->author) : _previewData->description; } } else { title = _previewData->siteName; - desc = _previewData->title.isEmpty() ? (_previewData->description.isEmpty() ? (_previewData->author.isEmpty() ? _previewData->url : _previewData->author) : _previewData->description) : _previewData->title; + desc = _previewData->title.isEmpty() ? (_previewData->description.isEmpty() ? (_previewData->author.isEmpty() ? ((_previewData->doc && !_previewData->doc->name.isEmpty()) ? _previewData->doc->name : _previewData->url) : _previewData->author) : _previewData->description) : _previewData->title; + } + if (title.isEmpty()) { + if (_previewData->photo) { + title = lang(lng_attach_photo); + } else if (_previewData->doc) { + title = lang(lng_attach_file); + } } _previewTitle.setText(st::msgServiceNameFont, title, _textNameOptions); _previewDescription.setText(st::msgFont, desc, _textDlgOptions); @@ -5407,8 +5446,8 @@ void HistoryWidget::drawField(Painter &p) { if (drawPreview) { int32 previewLeft = st::replySkip + st::webPageLeft; p.fillRect(st::replySkip, backy + st::msgReplyPadding.top(), st::webPageBar, st::msgReplyBarSize.height(), st::msgInReplyBarColor->b); - if (_previewData->photo && !_previewData->photo->thumb->isNull()) { - ImagePtr replyPreview = _previewData->photo->makeReplyPreview(); + if ((_previewData->photo && !_previewData->photo->thumb->isNull()) || (_previewData->doc && !_previewData->doc->thumb->isNull())) { + ImagePtr replyPreview = _previewData->photo ? _previewData->photo->makeReplyPreview() : _previewData->doc->makeReplyPreview(); if (!replyPreview->isNull()) { QRect to(previewLeft, backy + st::msgReplyPadding.top(), st::msgReplyBarSize.height(), st::msgReplyBarSize.height()); if (replyPreview->width() == replyPreview->height()) { diff --git a/Telegram/SourceFiles/intro/intro.cpp b/Telegram/SourceFiles/intro/intro.cpp index 0a6bace09..c71a7d5d7 100644 --- a/Telegram/SourceFiles/intro/intro.cpp +++ b/Telegram/SourceFiles/intro/intro.cpp @@ -43,7 +43,9 @@ namespace { countryForReg = nearest.vcountry.c_string().v.c_str(); emit signalEmitOn->countryChanged(); } + #ifndef TDESKTOP_DISABLE_AUTOUPDATE if (App::app()) App::app()->startUpdateCheck(); + #endif } } @@ -63,6 +65,7 @@ visibilityChanging(0), _callTimeout(60), _registered(false), _hasRecovery(false), +_codeByTelegram(false), _back(this, st::setClose), _backFrom(0), _backTo(0) { setGeometry(QRect(0, st::titleHeight, wnd->width(), wnd->height() - st::titleHeight)); @@ -333,6 +336,11 @@ void IntroWidget::setPwdHint(const QString &hint) { _pwdHint = hint; } +void IntroWidget::setCodeByTelegram(bool byTelegram) { + _codeByTelegram = byTelegram; + if (code) code->updateDescText(); +} + void IntroWidget::setCallTimeout(int32 callTimeout) { _callTimeout = callTimeout; } @@ -365,6 +373,10 @@ const QString &IntroWidget::getPwdHint() const { return _pwdHint; } +bool IntroWidget::codeByTelegram() const { + return _codeByTelegram; +} + void IntroWidget::resizeEvent(QResizeEvent *e) { QRect r(innerRect()); if (steps) steps->setGeometry(r); diff --git a/Telegram/SourceFiles/intro/intro.h b/Telegram/SourceFiles/intro/intro.h index dd59066a5..af7f11d0f 100644 --- a/Telegram/SourceFiles/intro/intro.h +++ b/Telegram/SourceFiles/intro/intro.h @@ -52,6 +52,7 @@ public: void setPwdSalt(const QByteArray &salt); void setHasRecovery(bool hasRecovery); void setPwdHint(const QString &hint); + void setCodeByTelegram(bool byTelegram); const QString &getPhone() const; const QString &getPhoneHash() const; @@ -60,6 +61,7 @@ public: const QByteArray &getPwdSalt() const; bool getHasRecovery() const; const QString &getPwdHint() const; + bool codeByTelegram() const; void finish(const MTPUser &user, const QImage &photo = QImage()); @@ -114,7 +116,7 @@ private: QString _code; QByteArray _pwdSalt; - bool _hasRecovery; + bool _hasRecovery, _codeByTelegram; QString _pwdHint; QString _firstname, _lastname; diff --git a/Telegram/SourceFiles/intro/introcode.cpp b/Telegram/SourceFiles/intro/introcode.cpp index b9dc0bf57..9b8848b88 100644 --- a/Telegram/SourceFiles/intro/introcode.cpp +++ b/Telegram/SourceFiles/intro/introcode.cpp @@ -69,6 +69,9 @@ void CodeInput::correctValue(QKeyEvent *e, const QString &was) { IntroCode::IntroCode(IntroWidget *parent) : IntroStage(parent), errorAlpha(0), next(this, lang(lng_intro_next), st::btnIntroNext), + _desc(st::introTextSize.width()), + _noTelegramCode(this, lang(lng_code_no_telegram), st::introLink), + _noTelegramCodeRequestId(0), code(this, st::inpIntroCode, lang(lng_code_ph)), waitTillCall(intro()->getCallTimeout()) { setVisible(false); setGeometry(parent->innerRect()); @@ -78,6 +81,24 @@ IntroCode::IntroCode(IntroWidget *parent) : IntroStage(parent), errorAlpha(0), connect(&code, SIGNAL(changed()), this, SLOT(onInputChange())); connect(&callTimer, SIGNAL(timeout()), this, SLOT(onSendCall())); connect(&checkRequest, SIGNAL(timeout()), this, SLOT(onCheckRequest())); + connect(&_noTelegramCode, SIGNAL(clicked()), this, SLOT(onNoTelegramCode())); + + updateDescText(); +} + +void IntroCode::updateDescText() { + _desc.setRichText(st::introFont, lang(intro()->codeByTelegram() ? lng_code_telegram : lng_code_desc)); + if (intro()->codeByTelegram()) { + _noTelegramCode.show(); + callTimer.stop(); + } else { + _noTelegramCode.hide(); + waitTillCall = intro()->getCallTimeout(); + if (!callTimer.isActive()) { + callTimer.start(1000); + } + } + update(); } void IntroCode::paintEvent(QPaintEvent *e) { @@ -87,21 +108,25 @@ void IntroCode::paintEvent(QPaintEvent *e) { if (!trivial) { p.setClipRect(e->rect()); } + bool codeByTelegram = intro()->codeByTelegram(); if (trivial || e->rect().intersects(textRect)) { p.setFont(st::introHeaderFont->f); p.drawText(textRect, intro()->getPhone(), style::al_top); p.setFont(st::introFont->f); - p.drawText(textRect, lang(lng_code_desc), style::al_bottom); + _desc.draw(p, textRect.x(), textRect.y() + textRect.height() - 2 * st::introFont->height, textRect.width(), style::al_top); } - QString callText = lang(lng_code_calling); - if (waitTillCall >= 3600) { - callText = lng_code_call(lt_minutes, qsl("%1:%2").arg(waitTillCall / 3600).arg((waitTillCall / 60) % 60, 2, 10, QChar('0')), lt_seconds, qsl("%1").arg(waitTillCall % 60, 2, 10, QChar('0'))); - } else if (waitTillCall > 0) { - callText = lng_code_call(lt_minutes, QString::number(waitTillCall / 60), lt_seconds, qsl("%1").arg(waitTillCall % 60, 2, 10, QChar('0'))); - } else if (waitTillCall < 0) { - callText = lang(lng_code_called); + if (codeByTelegram) { + } else { + QString callText = lang(lng_code_calling); + if (waitTillCall >= 3600) { + callText = lng_code_call(lt_minutes, qsl("%1:%2").arg(waitTillCall / 3600).arg((waitTillCall / 60) % 60, 2, 10, QChar('0')), lt_seconds, qsl("%1").arg(waitTillCall % 60, 2, 10, QChar('0'))); + } else if (waitTillCall > 0) { + callText = lng_code_call(lt_minutes, QString::number(waitTillCall / 60), lt_seconds, qsl("%1").arg(waitTillCall % 60, 2, 10, QChar('0'))); + } else if (waitTillCall < 0) { + callText = lang(lng_code_called); + } + p.drawText(QRect(textRect.left(), code.y() + code.height() + st::introCallSkip, st::introTextSize.width(), st::introErrHeight), callText, style::al_center); } - p.drawText(QRect(textRect.left(), code.y() + code.height() + st::introCallSkip, st::introTextSize.width(), st::introErrHeight), callText, style::al_center); if (animating() || error.length()) { p.setOpacity(errorAlpha.current()); p.setFont(st::introErrFont->f); @@ -116,6 +141,7 @@ void IntroCode::resizeEvent(QResizeEvent *e) { code.move((width() - code.width()) / 2, st::introTextTop + st::introTextSize.height() + st::introCountry.top); } textRect = QRect((width() - st::introTextSize.width()) / 2, st::introTextTop, st::introTextSize.width(), st::introTextSize.height()); + _noTelegramCode.move(textRect.left() + (st::introTextSize.width() - _noTelegramCode.width()) / 2, code.y() + code.height() + st::introCallSkip + (st::introErrHeight - _noTelegramCode.height()) / 2); } void IntroCode::showError(const QString &err) { @@ -150,7 +176,9 @@ bool IntroCode::animStep(float64 ms) { void IntroCode::activate() { waitTillCall = intro()->getCallTimeout(); - callTimer.start(1000); + if (!intro()->codeByTelegram()) { + callTimer.start(1000); + } error = ""; errorAlpha = anim::fvalue(0); sentCode = QString(); @@ -300,6 +328,31 @@ void IntroCode::onSubmitCode(bool force) { sentRequest = MTP::send(MTPauth_SignIn(MTP_string(intro()->getPhone()), MTP_string(intro()->getPhoneHash()), MTP_string(sentCode)), rpcDone(&IntroCode::codeSubmitDone), rpcFail(&IntroCode::codeSubmitFail)); } +void IntroCode::onNoTelegramCode() { + if (_noTelegramCodeRequestId) return; + _noTelegramCodeRequestId = MTP::send(MTPauth_SendSms(MTP_string(intro()->getPhone()), MTP_string(intro()->getPhoneHash())), rpcDone(&IntroCode::noTelegramCodeDone), rpcFail(&IntroCode::noTelegramCodeFail)); +} + +void IntroCode::noTelegramCodeDone(const MTPBool &result) { + intro()->setCodeByTelegram(false); + updateDescText(); +} + +bool IntroCode::noTelegramCodeFail(const RPCError &error) { + if (error.type().startsWith(qsl("FLOOD_WAIT_"))) { + showError(lang(lng_flood_error)); + code.setFocus(); + return true; + } + if (cDebug()) { // internal server error + showError(error.type() + ": " + error.description()); + } else { + showError(lang(lng_server_error)); + } + code.setFocus(); + return false; +} + void IntroCode::onNext() { onSubmitCode(); } diff --git a/Telegram/SourceFiles/intro/introcode.h b/Telegram/SourceFiles/intro/introcode.h index 6e44aa827..b171d0574 100644 --- a/Telegram/SourceFiles/intro/introcode.h +++ b/Telegram/SourceFiles/intro/introcode.h @@ -64,9 +64,12 @@ public: void codeSubmitDone(const MTPauth_Authorization &result); bool codeSubmitFail(const RPCError &error); + void updateDescText(); + public slots: void onSubmitCode(bool force = false); + void onNoTelegramCode(); void onInputChange(); void onSendCall(); void onCheckRequest(); @@ -84,8 +87,14 @@ private: FlatButton next; + Text _desc; + LinkButton _noTelegramCode; + mtpRequestId _noTelegramCodeRequestId; QRect textRect; + void noTelegramCodeDone(const MTPBool &result); + bool noTelegramCodeFail(const RPCError &result); + CodeInput code; QString sentCode; mtpRequestId sentRequest; diff --git a/Telegram/SourceFiles/intro/introphone.cpp b/Telegram/SourceFiles/intro/introphone.cpp index 7c968bb3d..9c1196067 100644 --- a/Telegram/SourceFiles/intro/introphone.cpp +++ b/Telegram/SourceFiles/intro/introphone.cpp @@ -231,7 +231,7 @@ void IntroPhone::phoneCheckDone(const MTPauth_CheckedPhone &result) { checkRequest.start(1000); - sentRequest = MTP::send(MTPauth_SendCode(MTP_string(sentPhone), MTP_int(0), MTP_int(ApiId), MTP_string(ApiHash), MTP_string(Application::language())), rpcDone(&IntroPhone::phoneSubmitDone), rpcFail(&IntroPhone::phoneSubmitFail)); + sentRequest = MTP::send(MTPauth_SendCode(MTP_string(sentPhone), MTP_int(5), MTP_int(ApiId), MTP_string(ApiHash), MTP_string(Application::language())), rpcDone(&IntroPhone::phoneSubmitDone), rpcFail(&IntroPhone::phoneSubmitFail)); } else { showError(lang(lng_bad_phone_noreg), true); enableAll(true); @@ -250,6 +250,7 @@ void IntroPhone::phoneSubmitDone(const MTPauth_SentCode &result) { const MTPDauth_sentAppCode &d(result.c_auth_sentAppCode()); intro()->setPhone(sentPhone, d.vphone_code_hash.c_string().v.c_str(), d.vphone_registered.v); intro()->setCallTimeout(d.vsend_call_timeout.v); + intro()->setCodeByTelegram(true); } intro()->onIntroNext(); } diff --git a/Telegram/SourceFiles/lang.h b/Telegram/SourceFiles/lang.h index 7cb0fea1d..e99c42dca 100644 --- a/Telegram/SourceFiles/lang.h +++ b/Telegram/SourceFiles/lang.h @@ -78,7 +78,13 @@ LangString langCounted(ushort key0, ushort tag, float64 value); const char *langKeyName(LangKey key); inline LangString langDayOfMonth(const QDate &date) { - int32 month = date.month(), day = date.day(); + QDate c(QDate::currentDate()); + int32 month = date.month(), day = date.day(), year = date.year(), cyear = c.year(), cmonth = c.month(); + if (year != cyear) { + if (year > cyear + 1 || cyear > year + 1 || (year == cyear + 1 && month + 12 > cmonth + 3) || (cyear == year + 1 && cmonth + 12 > month + 3)) { + return (month > 0 && month <= 12) ? lng_month_day_year(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_day, QString::number(day), lt_year, QString::number(year)) : qsl("MONTH_ERR"); + } + } return (month > 0 && month <= 12) ? lng_month_day(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_day, QString::number(day)) : qsl("MONTH_ERR"); } diff --git a/Telegram/SourceFiles/langs/lang_de.strings b/Telegram/SourceFiles/langs/lang_de.strings index 8b9ee477f..2bfd27567 100644 --- a/Telegram/SourceFiles/langs/lang_de.strings +++ b/Telegram/SourceFiles/langs/lang_de.strings @@ -60,6 +60,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_weekday7_full" = "Sonntag"; "lng_month_day" = "{day}. {month}"; +"lng_month_day_year" = "{day} {month}, {year}"; "lng_cancel" = "Abbrechen"; "lng_continue" = "Weiter"; @@ -117,6 +118,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_code_ph" = "Dein Code"; "lng_code_desc" = "Wir haben dir einen Aktivierungscode gesendet.\nBitte Code hier eingeben."; +"lng_code_telegram" = "Bitte den Code eingeben, den du in der\nzuvor benutzen [b]Telegram[/b]-App erhalten hast."; +"lng_code_no_telegram" = "Code per SMS senden"; "lng_code_call" = "Telegram ruft dich an in {minutes}:{seconds}"; "lng_code_calling" = "Telegram ruft dich an.."; "lng_code_called" = "Telegram ruft dich gerade an."; @@ -188,6 +191,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_show_preview" = "Nachrichtenvorschau anzeigen"; "lng_settings_use_windows" = "Windows Benachrichtigungen"; "lng_settings_sound_notify" = "Ton abspielen"; +"lng_settings_include_muted" = "Stummgeschaltete Chats mitzählen"; "lng_notification_preview" = "Du hast eine neue Nachricht"; @@ -386,6 +390,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_profile_files_header" = "Dateiübersicht"; "lng_profile_audios" = "{count:_not_used_|# Sprachnachricht|# Sprachnachrichten} »"; "lng_profile_audios_header" = "Übersicht Sprachnachrichten"; +"lng_profile_shared_links" = "{count:_not_used_|# Link|# Links} »"; +"lng_profile_shared_links_header" = "Linkübersicht"; "lng_profile_audio_files_header" = "Wiedergabeliste"; "lng_profile_show_all_types" = "Alle Filter anzeigen"; "lng_profile_copy_phone" = "Telefonnummer kopieren"; @@ -443,6 +449,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_media_type_videos" = "Videos"; "lng_media_type_files" = "Dateien"; "lng_media_type_audios" = "Sprachnachrichten"; +"lng_media_type_links" = "Links"; "lng_media_open_with" = "Öffnen mit"; "lng_media_download" = "Download"; @@ -641,7 +648,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram Desktop wurde aktualisiert auf Version {version}\n\n{changes}\n\nGesamter Versionsverlauf:\n{link}"; "lng_new_version_minor" = "— Fehlerbehebungen und Softwareoptimierungen"; -"lng_new_version_text" = "— Blockiere Nutzer über die Profilseite (im Chat auf den Namen oben tippen)\n— Windows 8, 8.1 und 10: Native Windowsbenachrichtigungen\n— Fehlerbehebung: Eingabemethoden unter Linux (Fcitx und iBus)"; +"lng_new_version_text" = "— Stummgeschaltete Chats können ab sofort optional mitgezählt werden (Einstellungen > Stummgeschaltete Chats mitzählen)\n— Übersicht der im Chat geteilten Links im Bereich 'Geteilte Medien'\n— GIF-Vorschau und PDF-Vorschau von Direktlinks (.pdf und .gif)"; "lng_menu_insert_unicode" = "Unicode-Steuerzeichen einfügen"; diff --git a/Telegram/SourceFiles/langs/lang_es.strings b/Telegram/SourceFiles/langs/lang_es.strings index 121130a6d..47e93f526 100644 --- a/Telegram/SourceFiles/langs/lang_es.strings +++ b/Telegram/SourceFiles/langs/lang_es.strings @@ -60,6 +60,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_weekday7_full" = "domingo"; "lng_month_day" = "{day} de {month}"; +"lng_month_day_year" = "{day} de {month} de {year}"; "lng_cancel" = "Cancelar"; "lng_continue" = "Continuar"; @@ -117,6 +118,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_code_ph" = "Tu código"; "lng_code_desc" = "Hemos enviado un mensaje con un código de \nactivación a tu teléfono. Por favor, ponlo abajo."; +"lng_code_telegram" = "Por favor, pon el código que acabas\nde recibir en tu otra aplicación de [b]Telegram[/b]."; +"lng_code_no_telegram" = "Enviar el código vía SMS"; "lng_code_call" = "Telegram marcará tu número en {minutes}:{seconds}"; "lng_code_calling" = "Solicitando una llamada de Telegram..."; "lng_code_called" = "Telegram marcó tu número"; @@ -188,6 +191,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_show_preview" = "Mostrar la vista previa del mensaje"; "lng_settings_use_windows" = "Usar notificaciones de Windows"; "lng_settings_sound_notify" = "Reproducir sonido"; +"lng_settings_include_muted" = "Incluir los chats silenciados en el conteo de 'no leídos'"; "lng_notification_preview" = "Tienes un nuevo mensaje"; @@ -386,6 +390,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_profile_files_header" = "Archivos"; "lng_profile_audios" = "{count:_not_used_|# mensaje de voz|# mensajes de voz} »"; "lng_profile_audios_header" = "Mensajes de voz"; +"lng_profile_shared_links" = "{count:_not_used_|# enlace|# enlaces} »"; +"lng_profile_shared_links_header" = "Enlaces"; "lng_profile_audio_files_header" = "Lista de reproducción"; "lng_profile_show_all_types" = "Mostrar todos los tipos"; "lng_profile_copy_phone" = "Copiar número"; @@ -443,6 +449,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_media_type_videos" = "Vídeos"; "lng_media_type_files" = "Archivos"; "lng_media_type_audios" = "Mensajes de voz"; +"lng_media_type_links" = "Enlaces"; "lng_media_open_with" = "Abrir con"; "lng_media_download" = "Descargar"; @@ -641,7 +648,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram Desktop fue actualizada a la versión {version}\n\n{changes}\n\nEl historial completo está disponible aquí:\n{link}"; "lng_new_version_minor" = "— Corrección de errores y otras mejoras menores"; -"lng_new_version_text" = "— Bloquea usuarios desde sus perfiles\n— Añadido el soporte para notificaciones Windows toast\n— Arreglados los métodos de entrada en Linux (Fcitx e IBus)"; +"lng_new_version_text" = "— Incluye los chats silenciados en el conteo de 'no leídos', en Ajustes\n— Vista y búsqueda de los enlaces compartidos, en 'Todos los archivos'\n— Vista previa al enviar enlaces a GIF animados o archivos PDF"; "lng_menu_insert_unicode" = "Insertar caracteres de control Unicode"; diff --git a/Telegram/SourceFiles/langs/lang_it.strings b/Telegram/SourceFiles/langs/lang_it.strings index f053bb974..dfa4eff43 100644 --- a/Telegram/SourceFiles/langs/lang_it.strings +++ b/Telegram/SourceFiles/langs/lang_it.strings @@ -60,12 +60,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_weekday7_full" = "Domenica"; "lng_month_day" = "{day} {month}"; +"lng_month_day_year" = "{day} {month} {year}"; "lng_cancel" = "Annulla"; "lng_continue" = "Continua"; "lng_close" = "Chiudi"; -"lng_connecting" = "Connessione..."; -"lng_reconnecting" = "Riconnessione {count:ora|in # s|in # s}..."; +"lng_connecting" = "Connetto..."; +"lng_reconnecting" = "Riconnetto {count:ora|in # s|in # s}..."; "lng_reconnecting_try_now" = "Prova ora"; "lng_status_service_notifications" = "notifiche di servizio"; @@ -86,7 +87,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_status_lastseen_date" = "ultimo accesso {date}"; "lng_status_lastseen_date_time" = "ultimo accesso {date} alle {time}"; "lng_status_online" = "in linea"; -"lng_status_connecting" = "connessione..."; +"lng_status_connecting" = "connetto..."; "lng_chat_status_unaccessible" = "gruppo non accessibile"; "lng_chat_status_members" = "{count:nessun membro|# membro|# membri}"; @@ -117,6 +118,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_code_ph" = "Codice"; "lng_code_desc" = "Abbiamo inviato un messaggio col codice\ndi attivazione al tuo telefono. Inseriscilo qui"; +"lng_code_telegram" = "Per favore inserisci il codice che hai\nappena ricevuto nell'altra app di [b]Telegram[/b]."; +"lng_code_no_telegram" = "Invia codice tramite SMS"; "lng_code_call" = "Telegram ti chiamerà tra {minutes}:{seconds}"; "lng_code_calling" = "Richiedendo una telefonata da Telegram.."; "lng_code_called" = "Telegram ti ha chiamato"; @@ -188,6 +191,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_show_preview" = "Mostra anteprima messaggio"; "lng_settings_use_windows" = "Usa le notifiche di Windows"; "lng_settings_sound_notify" = "Riproduci suono"; +"lng_settings_include_muted" = "Includi chat silenziate nel badge"; "lng_notification_preview" = "Hai un nuovo messaggio"; @@ -198,7 +202,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_auto_update" = "Aggiorna automaticamente"; "lng_settings_current_version" = "Versione {version}"; "lng_settings_check_now" = "Cerca aggiornamenti"; -"lng_settings_update_checking" = "Ricerca aggiornamenti.."; +"lng_settings_update_checking" = "Cerco aggiornamenti.."; "lng_settings_latest_installed" = "L'ultima versione è installata"; "lng_settings_downloading" = "Download aggiornamento {ready} / {total} MB.."; "lng_settings_update_ready" = "La nuova versione è pronta"; @@ -234,7 +238,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_download_path_clear" = "Elimina tutto"; "lng_download_path_header" = "Scegli il percorso di download"; "lng_download_path_default_radio" = "Cartella Telegram in «Download»"; -"lng_download_path_temp_radio" = "Cartella temporanea, pulita alla disconnessione"; +"lng_download_path_temp_radio" = "Cartella temporanea, pulita quando ti disconnetti"; "lng_download_path_dir_radio" = "Cartella personalizzata, pulita manualmente"; "lng_download_path_choose" = "Scegli il percorso di download"; "lng_sure_clear_downloads" = "Vuoi eliminare tutti i file scaricati nella cartella temporanea? Sarà fatto automaticamente alla disconnessione o alla disinstallazione del programma"; @@ -305,9 +309,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_cloud_password_is_same" = "La password non è stata cambiata"; "lng_connection_type" = "Tipo di connessione:"; -"lng_connection_auto_connecting" = "Default (connessione..)"; +"lng_connection_auto_connecting" = "Default (connetto..)"; "lng_connection_auto" = "Predefinito ({transport} in uso)"; -"lng_connection_proxy_connecting" = "Connessione tramite proxy.."; +"lng_connection_proxy_connecting" = "Connetto tramite proxy.."; "lng_connection_proxy" = "{transport} con proxy"; "lng_connection_header" = "Tipo di connessione"; "lng_connection_auto_rb" = "Auto (TCP se disponibile o HTTP)"; @@ -386,6 +390,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_profile_files_header" = "Panoramica file"; "lng_profile_audios" = "{count:_not_used_|# nota vocale|# note vocali} »"; "lng_profile_audios_header" = "Panoramica note vocali"; +"lng_profile_shared_links" = "{count:_not_used_|# link condiviso|# link condivisi} »"; +"lng_profile_shared_links_header" = "Panoramica link condivisi"; "lng_profile_audio_files_header" = "Playlist"; "lng_profile_show_all_types" = "Mostra tutti i tipi"; "lng_profile_copy_phone" = "Copia numero di telefono"; @@ -397,7 +403,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_create_group_title" = "Nuovo gruppo"; "lng_failed_add_participant" = "Impossibile aggiungere l'utente. Riprova più tardi."; -"lng_failed_add_not_mutual" = "Se una persona lascia un gruppo,\nsolo un contatto in comune può reinvitarla\n(lei deve avere il tuo numero\ndi telefono, e tu il suo)."; +"lng_failed_add_not_mutual" = "Se una persona lascia un gruppo, solo\nun contatto in comune può reinvitarla\n(chi ti invita deve avere il tuo\ncontatto su Telegram, e viceversa)."; "lng_sure_delete_contact" = "Sicuro di volere eliminare {contact} dalla tua lista dei contatti?"; "lng_sure_delete_history" = "Sicuro di voler eliminare tutta la cronologia dei messaggi con {contact}?\n\nQuesta azione non può essere annullata."; @@ -443,6 +449,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_media_type_videos" = "Video"; "lng_media_type_files" = "File"; "lng_media_type_audios" = "Note vocali"; +"lng_media_type_links" = "Link condivisi"; "lng_media_open_with" = "Apri con"; "lng_media_download" = "Download"; @@ -639,9 +646,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_new_authorization" = "{name},\nAbbiamo rilevato un accesso al tuo account da un nuovo dispositivo il {day}, {date} alle {time}\n\nDispositivo: {device}\nPosizione: {location}\n\nSe non sei tu, puoi andare su Impostazioni – Mostra tutte le sessioni e terminare quella sessione.\n\nSe credi che qualcuno si sia collegato al tuo account contro il tuo volere, puoi attivare la verifica in due passaggi nelle Impostazioni. \n\nGrazie, \nIl Team di Telegram"; -"lng_new_version_wrap" = "Telegram Desktop si è aggiornato alla versione {version}\n\n{changes}\n\nLa cronologia degli update è disponibile qui:\n{link}"; +"lng_new_version_wrap" = "Telegram Desktop si è aggiornato alla versione {version}\n\n{changes}\n\nLa cronologia degli aggiornamenti è disponibile qui:\n{link}"; "lng_new_version_minor" = "— Bug fix e altri miglioramenti minori"; -"lng_new_version_text" = "— Blocca gli utenti dalla loro pagina profilo\n— Aggiunto il supporto per le notifiche toast di Windows\n— Risolti i problemi con alcuni metodi di input su Linux (Fcitx and IBus)"; +"lng_new_version_text" = "— Includi chat silenziate nel badge nelle Impostazioni\n— Panoramica dei link condivisi e ricerca nei media condivisi\n— Anteprima quando invii una GIF o un file PDF."; "lng_menu_insert_unicode" = "Inserisci carattere di controllo Unicode"; diff --git a/Telegram/SourceFiles/langs/lang_ko.strings b/Telegram/SourceFiles/langs/lang_ko.strings index 6807a4abe..b6c0f4df1 100644 --- a/Telegram/SourceFiles/langs/lang_ko.strings +++ b/Telegram/SourceFiles/langs/lang_ko.strings @@ -60,6 +60,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_weekday7_full" = "일요일"; "lng_month_day" = "{month} {day}일"; +"lng_month_day_year" = "{month} {day}, {year}"; "lng_cancel" = "취소"; "lng_continue" = "계속"; @@ -117,6 +118,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_code_ph" = "코드번호"; "lng_code_desc" = "인증코드 메세지를 휴대폰으로 전송하였습니다.\n인증코드를 아래에 입력하여 주세요."; +"lng_code_telegram" = "[b]텔레그램[/b] 앱으로 부터 방금 수신받은,\n코드를 입력해주세요."; +"lng_code_no_telegram" = "코드를 SMS로 전송"; "lng_code_call" = "텔레그램이 {minutes}:{seconds}후에는 전화를 겁니다."; "lng_code_calling" = "텔레그램으로부터 전화 요청을 하고 있습니다.."; "lng_code_called" = "텔레그램이 회원님의 전화번호로 전화를 걸었습니다."; @@ -188,6 +191,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_show_preview" = "메시지 미리보기"; "lng_settings_use_windows" = "윈도우 알림 사용"; "lng_settings_sound_notify" = "소리 재생"; +"lng_settings_include_muted" = "안 읽은 메시지에 음소거된 채팅방 포함"; "lng_notification_preview" = "새로운 메시지가 있습니다."; @@ -386,6 +390,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_profile_files_header" = "파일 내역"; "lng_profile_audios" = "{count:_not_used_|#개의 음성 메시지|#개의 음성 메시지} »"; "lng_profile_audios_header" = "음성 메시지 내역"; +"lng_profile_shared_links" = "{count:_not_used_|# 공유된 링크|# 공유된 링크} »"; +"lng_profile_shared_links_header" = "공유된 링크 현황"; "lng_profile_audio_files_header" = "재생목록"; "lng_profile_show_all_types" = "모든 유형 보기"; "lng_profile_copy_phone" = "전화번호 복사"; @@ -443,6 +449,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_media_type_videos" = "비디오 파일"; "lng_media_type_files" = "파일"; "lng_media_type_audios" = "음성 메시지"; +"lng_media_type_links" = "공유된 링크"; "lng_media_open_with" = "다음으로 열기"; "lng_media_download" = "다운로드"; @@ -641,7 +648,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "텔레그램 데스크탑은 {version} 버전으로 업데이트 되었습니다.\n\n{changes}\n\n전체 버전 히스토리는 아래에서 확인 가능합니다:\n{link}"; "lng_new_version_minor" = "— 버그 수정 및 일부 기능 향상"; -"lng_new_version_text" = "— 프로필 화면에서 사용자 차단\n— 윈도우 알림 지원\n— 리눅스 입력 방법 수정 (Fcitx and IBus)"; +"lng_new_version_text" = "— 설정에서 안 읽은 메시지 수에 음소거된 채팅방 포함\n— 공유된 링크 현황과 공유된 미디어 검색 기능\n— GIF 링크 및 PDF 파일 전송시 프리뷰 기능"; "lng_menu_insert_unicode" = "유니코드 문자를 입력하세요."; diff --git a/Telegram/SourceFiles/langs/lang_nl.strings b/Telegram/SourceFiles/langs/lang_nl.strings index a4febb0f4..966775c7f 100644 --- a/Telegram/SourceFiles/langs/lang_nl.strings +++ b/Telegram/SourceFiles/langs/lang_nl.strings @@ -60,6 +60,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_weekday7_full" = "zondag"; "lng_month_day" = "{day} {month}"; +"lng_month_day_year" = "{day} {month}, {year}"; "lng_cancel" = "Annuleren"; "lng_continue" = "Doorgaan"; @@ -117,6 +118,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_code_ph" = "Je code"; "lng_code_desc" = "We hebben een bericht met activatiecode\nverstuurd naar je nummer, geef deze hieronder in."; +"lng_code_telegram" = "Voer de code in die je zojuist\nhebt ontvangen in je vorige [b]Telegram[/b]-app."; +"lng_code_no_telegram" = "Verstuur code via SMS"; "lng_code_call" = "Telegram belt je over {minutes}:{seconds}"; "lng_code_calling" = "Oproepverzoek versturen naar Telegram"; "lng_code_called" = "Telegram heeft je nummer gebeld"; @@ -188,6 +191,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_show_preview" = "Voorvertoning weergeven"; "lng_settings_use_windows" = "Windows-berichtgeving gebruiken"; "lng_settings_sound_notify" = "Geluiden afspelen"; +"lng_settings_include_muted" = "Stille chats meetellen in ongelezen"; "lng_notification_preview" = "Je hebt een nieuw bericht"; @@ -386,6 +390,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_profile_files_header" = "Bestandsoverzicht"; "lng_profile_audios" = "{count:_not_used_|# spraakbericht|# spraakberichten} »"; "lng_profile_audios_header" = "Overzicht van spraakberichten"; +"lng_profile_shared_links" = "{count:_not_used_|# gedeelde link|# gedeelde links} »"; +"lng_profile_shared_links_header" = "Overzicht van gedeelde links"; "lng_profile_audio_files_header" = "Afspeellijst"; "lng_profile_show_all_types" = "Alles weergeven"; "lng_profile_copy_phone" = "Telefoonnummer kopiëren"; @@ -443,6 +449,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_media_type_videos" = "Video's"; "lng_media_type_files" = "Bestanden"; "lng_media_type_audios" = "Spraakberichten"; +"lng_media_type_links" = "Gedeelde links"; "lng_media_open_with" = "Openen met"; "lng_media_download" = "Downloaden"; @@ -641,7 +648,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram is bijgewerkt naar versie {version}\n\n{changes} \n\nVolledige versiegeschiedenis is hier te vinden:\n{link}"; "lng_new_version_minor" = "— Probleemoplossing en andere kleine verbeteringen"; -"lng_new_version_text" = "— Blokkeer gebruikers vanaf de profielpagina\n— Ondersteuning voor Windows toast-meldingen\n— Problemen met invoermethodes onder Linux (Fcitx and IBus) opgelost"; +"lng_new_version_text" = "— Stille chats meetellen in ongelezen teller via instellingen\n— Gedeelde links-overzicht en zoeken in gedeelde media\n— Voorvertoning voor links naar GIF-animaties en PDF-bestanden"; "lng_menu_insert_unicode" = "Unicode-besturingsteken invoegen"; diff --git a/Telegram/SourceFiles/langs/lang_pt_BR.strings b/Telegram/SourceFiles/langs/lang_pt_BR.strings index 89c481fe4..b41698cc4 100644 --- a/Telegram/SourceFiles/langs/lang_pt_BR.strings +++ b/Telegram/SourceFiles/langs/lang_pt_BR.strings @@ -60,6 +60,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_weekday7_full" = "Domingo"; "lng_month_day" = "{month} {day}"; +"lng_month_day_year" = "{day} {month}, {year}"; "lng_cancel" = "Cancelar"; "lng_continue" = "Continuar"; @@ -117,6 +118,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_code_ph" = "Código"; "lng_code_desc" = "Enviamos uma SMS com um código de ativação\npara o seu telefone. Insira-o abaixo."; +"lng_code_telegram" = "Por favor insira código recebido\nem seu aplicativo prévio do [b]Telegram[/b]"; +"lng_code_no_telegram" = "Enviar código via SMS"; "lng_code_call" = "Telegram irá te ligar em {minutes}{seconds}"; "lng_code_calling" = "Aguardando a ligação do Telegram.."; "lng_code_called" = "Telegram ligou para o seu número"; @@ -188,6 +191,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_show_preview" = "Mostrar pré-visualização da mensagem"; "lng_settings_use_windows" = "Usar notificações do Windows"; "lng_settings_sound_notify" = "Tocar som"; +"lng_settings_include_muted" = "Incluir chats silenciados no contador de notificações"; "lng_notification_preview" = "Você tem uma nova mensagem"; @@ -380,12 +384,14 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_profile_no_media" = "Nenhuma mídia nessa conversa."; "lng_profile_photos" = "{count:_not_used_|# foto|# fotos} »"; "lng_profile_photos_header" = "Fotos"; -"lng_profile_videos" = "{count:_not_used_|# arquivo de vídeo|# arquivo de vídeos} »"; +"lng_profile_videos" = "{count:_not_used_|# vídeo|# vídeos} »"; "lng_profile_videos_header" = "Vídeos"; "lng_profile_files" = "{count:_not_used_|# arquivo|# arquivos} »"; "lng_profile_files_header" = "Arquivos"; "lng_profile_audios" = "{count:_not_used_|# mensagem de voz|# mensagens de voz} »"; "lng_profile_audios_header" = "Mensagens de voz"; +"lng_profile_shared_links" = "{count:_not_used_|# link|# links} »"; +"lng_profile_shared_links_header" = "Links"; "lng_profile_audio_files_header" = "Reprodução"; "lng_profile_show_all_types" = "Mostrar todos os tipos"; "lng_profile_copy_phone" = "Copiar número de telefone"; @@ -440,14 +446,15 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_media_type" = "Tipo de mídia"; "lng_media_type_photos" = "Fotos"; -"lng_media_type_videos" = "Arquivos de vídeo"; +"lng_media_type_videos" = "Vídeos"; "lng_media_type_files" = "Arquivos"; "lng_media_type_audios" = "Mensagens de voz"; +"lng_media_type_links" = "Links"; "lng_media_open_with" = "Abrir Com"; "lng_media_download" = "Download"; "lng_media_cancel" = "Cancelar"; -"lng_media_video" = "Arquivo de vídeo"; +"lng_media_video" = "Vídeos"; "lng_media_audio" = "Mensagem de voz"; "lng_emoji_category0" = "Frequentemente usado"; @@ -641,7 +648,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_new_version_wrap" = "Telegram Desktop foi atualizado para a versão {version}\n\n{changes}\n\nHistórico completo de mudanças disponível aqui:\n{link}"; "lng_new_version_minor" = "— Resolução de bugs e outras menores melhorias"; -"lng_new_version_text" = "— Bloqueie usuários direto da página do perfil\n— Adicionado suporte às notificações de sistema do Windows\n— Consertado métodos de entrada no Linux (Fcitx e IBus)"; +"lng_new_version_text" = "— Incluir chats silenciados no contador de notificações em Configurações\n— Visão geral dos links compartilhados e busca nas mídias compartilhadas\n— Pré-visualização em links com GIF e arquivos em PDF"; "lng_menu_insert_unicode" = "Inserir caractere de controle Unicode"; diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index 125041324..abb7952db 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -730,6 +730,14 @@ namespace { cSetSoundNotify(v == 1); } break; + case dbiIncludeMuted: { + qint32 v; + stream >> v; + if (!_checkStreamStatus(stream)) return false; + + cSetIncludeMuted(v == 1); + } break; + case dbiDesktopNotify: { qint32 v; stream >> v; @@ -744,7 +752,9 @@ namespace { if (!_checkStreamStatus(stream)) return false; cSetWindowsNotifications(v == 1); - cSetCustomNotifies((App::wnd() ? App::wnd()->psHasNativeNotifications() : true) && !cWindowsNotifications()); + if (cPlatform() == dbipWindows) { + cSetCustomNotifies((App::wnd() ? !App::wnd()->psHasNativeNotifications() : true) || !cWindowsNotifications()); + } } break; case dbiWorkMode: { @@ -1279,7 +1289,7 @@ namespace { _writeMap(WriteMapFast); } - uint32 size = 13 * (sizeof(quint32) + sizeof(qint32)); + uint32 size = 14 * (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)); @@ -1293,6 +1303,7 @@ namespace { data.stream << quint32(dbiReplaceEmojis) << qint32(cReplaceEmojis() ? 1 : 0); data.stream << quint32(dbiDefaultAttach) << qint32(cDefaultAttach()); data.stream << quint32(dbiSoundNotify) << qint32(cSoundNotify()); + data.stream << quint32(dbiIncludeMuted) << qint32(cIncludeMuted()); data.stream << quint32(dbiDesktopNotify) << qint32(cDesktopNotify()); data.stream << quint32(dbiNotifyView) << qint32(cNotifyView()); data.stream << quint32(dbiWindowsNotifications) << qint32(cWindowsNotifications()); diff --git a/Telegram/SourceFiles/main.cpp b/Telegram/SourceFiles/main.cpp index 26b897b08..99c7e7787 100644 --- a/Telegram/SourceFiles/main.cpp +++ b/Telegram/SourceFiles/main.cpp @@ -81,6 +81,7 @@ int main(int argc, char *argv[]) { DEBUG_LOG(("Application Info: Telegram done, result: %1").arg(result)); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE if (cRestartingUpdate()) { if (DevVersion) { LOG(("Writing 'devversion' file before launching the Updater!")); @@ -93,7 +94,9 @@ int main(int argc, char *argv[]) { DEBUG_LOG(("Application Info: executing updater to install update..")); psExecUpdater(); - } else if (cRestarting()) { + } else + #endif + if (cRestarting()) { DEBUG_LOG(("Application Info: executing Telegram, because of restart..")); psExecTelegram(); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 3a75d23cb..0ec1c8763 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -78,7 +78,7 @@ void TopBarWidget::onInfoClicked() { void TopBarWidget::onAddContact() { PeerData *p = App::main() ? App::main()->profilePeer() : 0; UserData *u = (p && !p->chat) ? p->asUser() : 0; - if (u) App::wnd()->showLayer(new AddContactBox(u->firstName, u->lastName, u->phone)); + if (u) App::wnd()->showLayer(new AddContactBox(u->firstName, u->lastName, u->phone.isEmpty() ? App::phoneFromSharedContact(App::userFromPeer(u->id)) : u->phone)); } void TopBarWidget::onEdit() { @@ -278,7 +278,7 @@ void TopBarWidget::showAll() { return; } PeerData *p = App::main() ? App::main()->profilePeer() : 0, *o = App::main() ? App::main()->overviewPeer() : 0; - if (p && (p->chat || p->asUser()->contact >= 0)) { + if (p && (p->chat || p->asUser()->contact >= 0 || !App::phoneFromSharedContact(App::userFromPeer(p->id)).isEmpty())) { if (p->chat) { if (p->asChat()->forbidden) { _edit.hide(); @@ -982,6 +982,62 @@ DialogsIndexed &MainWidget::dialogsList() { return dialogs.dialogsList(); } +inline bool replaceCharBySpace(ushort code) { + // \xe2\x80[\xa8 - \xac\xad] // 8232 - 8237 + // QString from1 = QString::fromUtf8("\xe2\x80\xa8"), to1 = QString::fromUtf8("\xe2\x80\xad"); + // \xcc[\xb3\xbf\x8a] // 819, 831, 778 + // QString bad1 = QString::fromUtf8("\xcc\xb3"), bad2 = QString::fromUtf8("\xcc\xbf"), bad3 = QString::fromUtf8("\xcc\x8a"); + // [\x00\x01\x02\x07\x08\x0b-\x1f] // '\t' = 0x09 + return (code >= 0x00 && code <= 0x02) || (code >= 0x07 && code <= 0x09) || (code >= 0x0b && code <= 0x1f) || + (code == 819) || (code == 831) || (code == 778) || (code >= 8232 && code <= 8237); +} + +QString cleanMessage(const QString &text) { + QString result = text; + QChar *_start = result.data(), *_end = _start + result.size(), *start = _start, *end = _end, *ch = start, *copy = 0; + for (; ch != end; ++ch) { + if (ch->unicode() == '\r') { + copy = ch + 1; + break; + } else if (replaceCharBySpace(ch->unicode())) { + *ch = ' '; + } + } + if (copy) { + for (; copy != end; ++copy) { + if (copy->unicode() == '\r') { + continue; + } else if (replaceCharBySpace(copy->unicode())) { + *ch++ = ' '; + } else { + *ch++ = *copy; + } + } + end = ch; + } + + // PHP trim() removes [ \t\n\r\x00\x0b], we have removed [\t\r\x00\x0b] before, so + for (; start != end; ++start) { + if (start->unicode() != ' ' && start->unicode() != '\n') { + break; + } + } + for (QChar *e = end - 1; start != end; end = e) { + if (e->unicode() != ' ' && e->unicode() != '\n') { + break; + } + --e; + } + if (start == end) { + return QString(); + } else if (start > _start) { + return QString(start, end - start); + } else if (end < _end) { + result.resize(end - start); + } + return result; +} + void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId replyTo, WebPageId webPageId) { saveRecentHashtags(text); QString sendingText, leftText = text; @@ -990,10 +1046,13 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl MsgId newId = clientMsgId(); uint64 randomId = MTP::nonce(); + sendingText = cleanMessage(sendingText); + App::historyRegRandom(randomId, newId); + App::historyRegSentText(randomId, sendingText); MTPstring msgText(MTP_string(sendingText)); - int32 flags = newMessageFlags(hist->peer); // unread, out + int32 flags = newMessageFlags(hist->peer) | MTPDmessage::flag_entities; // unread, out int32 sendFlags = 0; if (replyTo) { flags |= MTPDmessage::flag_reply_to_msg_id; @@ -1005,9 +1064,11 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl } else if (webPageId) { WebPageData *page = App::webPage(webPageId); media = MTP_messageMediaWebPage(MTP_webPagePending(MTP_long(page->id), MTP_int(page->pendingTill))); + flags |= MTPDmessage::flag_media; } - hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media, MTPnullMarkup, MTPnullEntities)); - hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup, MTPnullEntities), App::main()->rpcDone(&MainWidget::sentDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + MTPVector localEntities = linksToMTP(textParseLinks(sendingText, itemTextParseOptions(hist, App::self()).flags)); + hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media, MTPnullMarkup, localEntities)); + hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup, localEntities), App::main()->rpcDone(&MainWidget::sentUpdatesReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); } finishForwarding(hist); @@ -1173,6 +1234,7 @@ void MainWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) { case OverviewVideos: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaVideos, lang(lng_media_type_videos))), SIGNAL(clicked()), this, SLOT(onVideosSelect())); break; case OverviewDocuments: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaDocuments, lang(lng_media_type_files))), SIGNAL(clicked()), this, SLOT(onDocumentsSelect())); break; case OverviewAudios: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaAudios, lang(lng_media_type_audios))), SIGNAL(clicked()), this, SLOT(onAudiosSelect())); break; + case OverviewLinks: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaLinks, lang(lng_media_type_links))), SIGNAL(clicked()), this, SLOT(onLinksSelect())); break; } } } @@ -1193,6 +1255,9 @@ void MainWidget::itemRemoved(HistoryItem *item) { if (history.peer() == item->history()->peer) { history.itemRemoved(item); } + if (overview && overview->peer() == item->history()->peer) { + overview->itemRemoved(item); + } itemRemovedGif(item); if (!_toForward.isEmpty()) { SelectedItemSet::iterator i = _toForward.find(item->id); @@ -1730,11 +1795,12 @@ void MainWidget::dialogsCancelled() { } void MainWidget::serviceNotification(const QString &msg, const MTPMessageMedia &media, bool unread) { - int32 flags = unread ? MTPDmessage_flag_unread : 0; + int32 flags = (unread ? MTPDmessage_flag_unread : 0) | MTPDmessage::flag_entities; QString sendingText, leftText = msg; HistoryItem *item = 0; while (textSplit(sendingText, leftText, MaxMessageSize)) { - item = App::histories().addToBack(MTP_message(MTP_int(flags), MTP_int(clientMsgId()), MTP_int(ServiceUserId), MTP_peerUser(MTP_int(MTP::authedId())), MTPint(), MTPint(), MTPint(), MTP_int(unixtime()), MTP_string(sendingText), media, MTPnullMarkup, MTPnullEntities), unread ? 1 : 2); + MTPVector localEntities = linksToMTP(textParseLinks(sendingText, _historyTextOptions.flags)); + item = App::histories().addToBack(MTP_message(MTP_int(flags), MTP_int(clientMsgId()), MTP_int(ServiceUserId), MTP_peerUser(MTP_int(MTP::authedId())), MTPint(), MTPint(), MTPint(), MTP_int(unixtime()), MTP_string(sendingText), media, MTPnullMarkup, localEntities), unread ? 1 : 2); } if (item) { history.peerMessagesUpdated(item->history()->peer->id); @@ -2217,51 +2283,8 @@ void MainWidget::windowShown() { history.windowShown(); } -void MainWidget::sentDataReceived(uint64 randomId, const MTPmessages_SentMessage &result) { - switch (result.type()) { - case mtpc_messages_sentMessage: { - const MTPDmessages_sentMessage &d(result.c_messages_sentMessage()); - - if (randomId) feedUpdate(MTP_updateMessageID(d.vid, MTP_long(randomId))); // ignore real date - - if (updInited) { - if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { - _byPtsSentMessage.insert(ptsKey(SkippedSentMessage), result); - return; - } - } - - HistoryItem *item = App::histItemById(d.vid.v); - if (item) { - item->setMedia(d.vmedia); - } - } break; - - case mtpc_messages_sentMessageLink: { - const MTPDmessages_sentMessageLink &d(result.c_messages_sentMessageLink()); - - if (randomId) feedUpdate(MTP_updateMessageID(d.vid, MTP_long(randomId))); // ignore real date - - if (updInited) { - if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { - _byPtsSentMessage.insert(ptsKey(SkippedSentMessage), result); - return; - } - } - App::feedUserLinks(d.vlinks); - - if (d.vmedia.type() != mtpc_messageMediaEmpty) { - HistoryItem *item = App::histItemById(d.vid.v); - if (item) { - item->setMedia(d.vmedia); - } - } - } break; - }; -} - -void MainWidget::sentUpdatesReceived(const MTPUpdates &result) { - handleUpdates(result); +void MainWidget::sentUpdatesReceived(uint64 randomId, const MTPUpdates &result) { + handleUpdates(result, randomId); App::emitPeerUpdated(); } @@ -2506,6 +2529,11 @@ void MainWidget::onAudiosSelect() { _mediaType.hideStart(); } +void MainWidget::onLinksSelect() { + if (overview) overview->switchType(OverviewLinks); + _mediaType.hideStart(); +} + TopBarWidget *MainWidget::topBar() { return &_topBar; } @@ -2531,7 +2559,19 @@ void MainWidget::onPeerShown(PeerData *peer) { _topBar.hide(); } resizeEvent(0); - if (animating()) _topBar.hide(); + if (animating()) { + _topBar.hide(); + } +} + +void MainWidget::searchInPeer(PeerData *peer) { + dialogs.searchInPeer(peer); + if (cWideMode()) { + dialogs.activate(); + } else { + dialogsToUp(); + showDialogs(); + } } void MainWidget::searchInPeer(PeerData *peer) { @@ -2672,7 +2712,7 @@ void MainWidget::applySkippedPtsUpdates() { switch (i.value()) { case SkippedUpdate: feedUpdate(_byPtsUpdate.value(i.key())); break; case SkippedUpdates: handleUpdates(_byPtsUpdates.value(i.key())); break; - case SkippedSentMessage: sentDataReceived(0, _byPtsSentMessage.value(i.key())); break; +// case SkippedSentMessage: sentDataReceived(0, _byPtsSentMessage.value(i.key())); break; } } --updSkipPtsUpdateLevel; @@ -2684,7 +2724,7 @@ void MainWidget::clearSkippedPtsUpdates() { _byPtsQueue.clear(); _byPtsUpdate.clear(); _byPtsUpdates.clear(); - _byPtsSentMessage.clear(); +// _byPtsSentMessage.clear(); updSkipPtsUpdateLevel = 0; } @@ -2768,7 +2808,9 @@ void MainWidget::start(const MTPUser &user) { cSetOtherOnline(0); App::feedUsers(MTP_vector(1, user)); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE App::app()->startUpdateCheck(); + #endif MTP::send(MTPupdates_GetState(), rpcDone(&MainWidget::gotState)); update(); if (!cStartUrl().isEmpty()) { @@ -2941,6 +2983,8 @@ void MainWidget::inviteImportDone(const MTPUpdates &updates) { } break; case mtpc_updateShortChatMessage: { } break; + case mtpc_updateShortSentMessage: { + } break; case mtpc_updatesTooLong: { } break; } @@ -3035,7 +3079,6 @@ void MainWidget::gotNotifySetting(MTPInputNotifyPeer peer, const MTPPeerNotifySe case mtpc_inputNotifyAll: applyNotifySetting(MTP_notifyAll(), settings); break; case mtpc_inputNotifyUsers: applyNotifySetting(MTP_notifyUsers(), settings); break; case mtpc_inputNotifyChats: applyNotifySetting(MTP_notifyChats(), settings); break; - case mtpc_inputNotifyGeoChatPeer: break; // no MTP_peerGeoChat case mtpc_inputNotifyPeer: switch (peer.c_inputNotifyPeer().vpeer.type()) { case mtpc_inputPeerEmpty: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(MTP_int(0))), settings); break; @@ -3294,7 +3337,7 @@ void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) { update(); } -void MainWidget::handleUpdates(const MTPUpdates &updates) { +void MainWidget::handleUpdates(const MTPUpdates &updates, uint64 randomId) { switch (updates.type()) { case mtpc_updates: { const MTPDupdates &d(updates.c_updates()); @@ -3349,7 +3392,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates) { return; } bool out = (d.vflags.v & MTPDmessage_flag_out); - HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, out ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(out ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, MTPnullEntities)); + HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, out ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(out ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities)); if (item) { history.peerMessagesUpdated(item->history()->peer->id); } @@ -3369,7 +3412,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates) { _byPtsUpdates.insert(ptsKey(SkippedUpdates), updates); return; } - HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, MTPnullEntities)); + HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities)); if (item) { history.peerMessagesUpdated(item->history()->peer->id); } @@ -3377,6 +3420,41 @@ void MainWidget::handleUpdates(const MTPUpdates &updates) { updSetState(0, d.vdate.v, updQts, updSeq); } break; + case mtpc_updateShortSentMessage: { + const MTPDupdateShortSentMessage &d(updates.c_updateShortSentMessage()); + HistoryItem *item = 0; + if (randomId) { + QString text = App::histSentTextByItem(randomId); + feedUpdate(MTP_updateMessageID(d.vid, MTP_long(randomId))); // ignore real date + if (!text.isEmpty()) { + bool hasLinks = d.has_entities() && !d.ventities.c_vector().v.isEmpty(); + item = App::histItemById(d.vid.v); + if (item && ((hasLinks && !item->hasTextLinks()) || (!hasLinks && item->textHasLinks()))) { + bool was = item->hasTextLinks(); + item->setText(text, d.has_entities() ? linksFromMTP(d.ventities.c_vector().v) : LinksInText()); + item->initDimensions(0); + itemResized(item); + if (!was && item->hasTextLinks()) { + item->history()->addToOverview(item, OverviewLinks); + } + } + } + } + + if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { + _byPtsUpdates.insert(ptsKey(SkippedUpdates), updates); + return; + } + if (!item) { + item = App::histItemById(d.vid.v); + } + if (item) { + item->setMedia(d.has_media() ? (&d.vmedia) : 0); + } + + updSetState(0, d.vdate.v, updQts, updSeq); + } break; + case mtpc_updatesTooLong: { MTP_LOG(0, ("getDifference { good - updatesTooLong received }%1").arg(cTestMode() ? " TESTMODE" : "")); return getDifference(); @@ -3394,6 +3472,10 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { _byPtsUpdate.insert(ptsKey(SkippedUpdate), update); return; } + if (d.vmessage.type() == mtpc_message) { // index forwarded messages to links overview + App::checkEntitiesUpdate(d.vmessage.c_message()); + } + HistoryItem *item = App::histories().addToBack(d.vmessage); if (item) { history.peerMessagesUpdated(item->history()->peer->id); @@ -3434,6 +3516,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { } App::historyUnregRandom(d.vrandom_id.v); } + App::historyUnregSentText(d.vrandom_id.v); } break; case mtpc_updateReadMessagesContents: { @@ -3627,10 +3710,6 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { } } break; - case mtpc_updateNewGeoChatMessage: { - const MTPDupdateNewGeoChatMessage &d(update.c_updateNewGeoChatMessage()); - } break; - case mtpc_updateNewEncryptedMessage: { const MTPDupdateNewEncryptedMessage &d(update.c_updateNewEncryptedMessage()); } break; diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 9fec76a31..8279caf12 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -222,8 +222,10 @@ public: void windowShown(); - void sentDataReceived(uint64 randomId, const MTPmessages_SentMessage &data); - void sentUpdatesReceived(const MTPUpdates &updates); + void sentUpdatesReceived(uint64 randomId, const MTPUpdates &updates); + void sentUpdatesReceived(const MTPUpdates &updates) { + return sentUpdatesReceived(0, updates); + } void msgUpdated(PeerId peer, const HistoryItem *msg); void historyToDown(History *hist); void dialogsToUp(); @@ -429,6 +431,7 @@ public slots: void onVideosSelect(); void onDocumentsSelect(); void onAudiosSelect(); + void onLinksSelect(); void onForwardCancel(QObject *obj = 0); @@ -477,7 +480,7 @@ private: void feedUpdate(const MTPUpdate &update); void updateReceived(const mtpPrime *from, const mtpPrime *end); - void handleUpdates(const MTPUpdates &updates); + void handleUpdates(const MTPUpdates &updates, uint64 randomId = 0); bool updateFail(const RPCError &e); void usernameResolveDone(QPair toProfileStartToken, const MTPUser &result); @@ -543,7 +546,7 @@ private: enum PtsSkippedQueue { SkippedUpdate, SkippedUpdates, - SkippedSentMessage, +// SkippedSentMessage, SkippedStatedMessage, SkippedStatedMessages }; @@ -554,7 +557,7 @@ private: QMap _byPtsQueue; QMap _byPtsUpdate; QMap _byPtsUpdates; - QMap _byPtsSentMessage; +// QMap _byPtsSentMessage; SingleTimer _byPtsTimer; QMap _bySeqUpdates; diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.cpp b/Telegram/SourceFiles/mtproto/mtpConnection.cpp index 1a8e0b0f8..58b0e7745 100644 --- a/Telegram/SourceFiles/mtproto/mtpConnection.cpp +++ b/Telegram/SourceFiles/mtproto/mtpConnection.cpp @@ -2812,7 +2812,7 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt mtpRequestId fakeRequestId = sessionData->nextFakeRequestId(); haveReceived.insert(fakeRequestId, mtpResponse(update)); // notify main process about new updates - if (cons != mtpc_updatesTooLong && cons != mtpc_updateShortMessage && cons != mtpc_updateShortChatMessage && cons != mtpc_updateShort && cons != mtpc_updatesCombined && cons != mtpc_updates) { + if (cons != mtpc_updatesTooLong && cons != mtpc_updateShortMessage && cons != mtpc_updateShortChatMessage && cons != mtpc_updateShortSentMessage && cons != mtpc_updateShort && cons != mtpc_updatesCombined && cons != mtpc_updates) { LOG(("Message Error: unknown constructor %1").arg(cons)); // maybe new api?.. } diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.h b/Telegram/SourceFiles/mtproto/mtpConnection.h index 2b600b60f..0ce618f1d 100644 --- a/Telegram/SourceFiles/mtproto/mtpConnection.h +++ b/Telegram/SourceFiles/mtproto/mtpConnection.h @@ -25,6 +25,7 @@ enum { MTPDmessage_flag_out = (1 << 1), MTPDmessage_flag_notify_by_from = (1 << 4), MTPDmessage_flag_media_unread = (1 << 5), + MTPDmessage_flag_HAS_TEXT_LINKS = (1 << 31), // client side flag for having links MTPmessages_SendMessage_flag_skipWebPage = (1 << 1), diff --git a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h index e9e479134..682073f14 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 = 34; +static const mtpPrime mtpCurrentLayer = 36; template class MTPBoxed : public bareT { diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.cpp b/Telegram/SourceFiles/mtproto/mtpScheme.cpp index 48cf2b3f0..d6bd9b55d 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.cpp +++ b/Telegram/SourceFiles/mtproto/mtpScheme.cpp @@ -655,7 +655,8 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP case 1: 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(" w: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 3: to.add(" h: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" caption: "); ++stages.back(); types.push_back(mtpc_string); 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(" caption: "); ++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; @@ -673,7 +674,8 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP case 2: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 3: to.add(" w: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 4: to.add(" h: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" caption: "); ++stages.back(); types.push_back(mtpc_string); 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(" caption: "); ++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; @@ -1213,29 +1215,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_geoChat: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geoChat"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" 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; - case 2: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" address: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" venue: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" geo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 7: to.add(" participants_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 8: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 9: to.add(" checked_in: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 10: to.add(" version: "); ++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_chatFull: if (stage) { to.add(",\n").addSpaces(lev); @@ -1346,7 +1325,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP case 6: to.add(" reply_to_msg_id: "); ++stages.back(); if (flag & MTPDmessage::flag_reply_to_msg_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break; case 7: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 8: to.add(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 9: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 9: to.add(" media: "); ++stages.back(); if (flag & MTPDmessage::flag_media) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 9 IN FIELD flags ]"); } break; case 10: to.add(" reply_markup: "); ++stages.back(); if (flag & MTPDmessage::flag_reply_markup) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break; case 11: to.add(" entities: "); ++stages.back(); if (flag & MTPDmessage::flag_entities) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; @@ -1566,24 +1545,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_messageActionGeoChatCreate: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ messageActionGeoChatCreate"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" address: "); ++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_messageActionGeoChatCheckin: - to.add("{ messageActionGeoChatCheckin }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); - break; - case mtpc_messageActionChatJoinedByLink: if (stage) { to.add(",\n").addSpaces(lev); @@ -1840,19 +1801,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("{ inputNotifyAll }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - case mtpc_inputNotifyGeoChatPeer: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ inputNotifyGeoChatPeer"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); 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_inputPeerNotifyEventsEmpty: to.add("{ inputPeerNotifyEventsEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; @@ -2025,20 +1973,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_chatLocated: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ chatLocated"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" chat_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(" distance: "); ++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_contacts_link: if (stage) { to.add(",\n").addSpaces(lev); @@ -2194,43 +2128,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_messages_sentMessage: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ messages_sentMessage"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" 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(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" entities: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" pts_count: "); ++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_messages_sentMessageLink: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ messages_sentMessageLink"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" 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(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" links: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" seq: "); ++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_messages_chats: if (stage) { to.add(",\n").addSpaces(lev); @@ -2487,19 +2384,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_updateNewGeoChatMessage: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ updateNewGeoChatMessage"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" message: "); ++stages.back(); types.push_back(0); 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_updateNewEncryptedMessage: if (stage) { to.add(",\n").addSpaces(lev); @@ -2899,6 +2783,25 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_updateShortSentMessage: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ updateShortSentMessage"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" 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(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" media: "); ++stages.back(); if (flag & MTPDupdateShortSentMessage::flag_media) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 9 IN FIELD flags ]"); } break; + case 6: to.add(" entities: "); ++stages.back(); if (flag & MTPDupdateShortSentMessage::flag_entities) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_photos_photos: if (stage) { to.add(",\n").addSpaces(lev); @@ -3051,132 +2954,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_inputGeoChat: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ inputGeoChat"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" chat_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_geoChatMessageEmpty: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geoChatMessageEmpty"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" chat_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(" 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_geoChatMessage: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geoChatMessage"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" chat_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(" 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(" from_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(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" media: "); ++stages.back(); types.push_back(0); 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_geoChatMessageService: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geoChatMessageService"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" chat_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(" 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(" from_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(" action: "); ++stages.back(); types.push_back(0); 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_geochats_statedMessage: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_statedMessage"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" message: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" users: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" seq: "); ++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_geochats_located: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_located"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" results: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" messages: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" users: "); ++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; - - case mtpc_geochats_messages: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_messages"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" messages: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" users: "); ++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; - - case mtpc_geochats_messagesSlice: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_messagesSlice"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" messages: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" users: "); ++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; - case mtpc_encryptedChatEmpty: if (stage) { to.add(",\n").addSpaces(lev); @@ -4025,6 +3802,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP case 12: to.add(" embed_height: "); ++stages.back(); if (flag & MTPDwebPage::flag_embed_height) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break; case 13: to.add(" duration: "); ++stages.back(); if (flag & MTPDwebPage::flag_duration) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break; case 14: to.add(" author: "); ++stages.back(); if (flag & MTPDwebPage::flag_author) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 8 IN FIELD flags ]"); } break; + case 15: to.add(" document: "); ++stages.back(); if (flag & MTPDwebPage::flag_document) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 9 IN FIELD flags ]"); } break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -4863,20 +4641,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_geochats_setTyping: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_setTyping"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" typing: "); ++stages.back(); types.push_back(0); 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_messages_discardEncryption: if (stage) { to.add(",\n").addSpaces(lev); @@ -5785,19 +5549,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_geochats_getFullChat: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_getFullChat"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); 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_updates_getState: to.add("{ updates_getState }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; @@ -5941,159 +5692,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_geochats_getLocated: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_getLocated"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" geo_point: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" radius: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: 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; - } - break; - - case mtpc_geochats_getRecents: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_getRecents"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: 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; - } - break; - - case mtpc_geochats_search: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_search"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" q: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" filter: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" min_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(" max_date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: 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 7: 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; - } - break; - - case mtpc_geochats_getHistory: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_getHistory"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++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 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; - } - break; - - case mtpc_geochats_checkin: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_checkin"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); 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_geochats_editChatTitle: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_editChatTitle"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" address: "); ++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_geochats_editChatPhoto: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_editChatPhoto"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" photo: "); ++stages.back(); types.push_back(0); 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_geochats_sendMessage: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_sendMessage"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" random_id: "); ++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_geochats_sendMedia: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_sendMedia"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" random_id: "); ++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_geochats_createGeoChat: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ geochats_createGeoChat"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" geo_point: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" address: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" venue: "); ++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_messages_getDhConfig: if (stage) { to.add(",\n").addSpaces(lev); diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.h b/Telegram/SourceFiles/mtproto/mtpScheme.h index 6ee83d88c..82b548bb1 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.h +++ b/Telegram/SourceFiles/mtproto/mtpScheme.h @@ -77,8 +77,8 @@ enum { mtpc_inputMediaPhoto = 0xe9bfb4f3, mtpc_inputMediaGeoPoint = 0xf9c44144, mtpc_inputMediaContact = 0xa6e45987, - mtpc_inputMediaUploadedVideo = 0xe13fd4bc, - mtpc_inputMediaUploadedThumbVideo = 0x96fb97dc, + mtpc_inputMediaUploadedVideo = 0x82713fdf, + mtpc_inputMediaUploadedThumbVideo = 0x7780ddf9, mtpc_inputMediaVideo = 0x936a4ebd, mtpc_inputChatPhotoEmpty = 0x1ca48f57, mtpc_inputChatUploadedPhoto = 0x94254732, @@ -124,7 +124,7 @@ enum { mtpc_chatPhotoEmpty = 0x37c1011c, mtpc_chatPhoto = 0x6153276a, mtpc_messageEmpty = 0x83e5de54, - mtpc_message = 0xf07814c8, + mtpc_message = 0x2bebfa86, mtpc_messageService = 0x1d86f70e, mtpc_messageMediaEmpty = 0x3ded6320, mtpc_messageMediaPhoto = 0x3d8ce53d, @@ -171,7 +171,6 @@ enum { mtpc_contactBlocked = 0x561bc879, mtpc_contactSuggested = 0x3de191a1, mtpc_contactStatus = 0xd3680c61, - mtpc_chatLocated = 0x3631cf4c, mtpc_contacts_link = 0x3ace484c, mtpc_contacts_contactsNotModified = 0xb74ba9d2, mtpc_contacts_contacts = 0x6f8b8cb2, @@ -183,7 +182,6 @@ enum { mtpc_messages_dialogsSlice = 0x71e094f3, mtpc_messages_messages = 0x8c718e87, mtpc_messages_messagesSlice = 0xb446ae3, - mtpc_messages_sentMessage = 0x8a99d8e0, mtpc_messages_chats = 0x64ff9fd5, mtpc_messages_chatFull = 0xe5d7d19c, mtpc_messages_affectedHistory = 0xb45c69d1, @@ -228,20 +226,6 @@ enum { mtpc_help_appUpdate = 0x8987f311, mtpc_help_noAppUpdate = 0xc45a6536, mtpc_help_inviteText = 0x18cb9f78, - mtpc_messages_sentMessageLink = 0x35a1a663, - mtpc_inputGeoChat = 0x74d456fa, - mtpc_inputNotifyGeoChatPeer = 0x4d8ddec8, - mtpc_geoChat = 0x75eaea5a, - mtpc_geoChatMessageEmpty = 0x60311a9b, - mtpc_geoChatMessage = 0x4505f8e1, - mtpc_geoChatMessageService = 0xd34fa24e, - mtpc_geochats_statedMessage = 0x17b1578b, - mtpc_geochats_located = 0x48feb267, - mtpc_geochats_messages = 0xd1526db1, - mtpc_geochats_messagesSlice = 0xbc5863e8, - mtpc_messageActionGeoChatCreate = 0x6f038ebc, - mtpc_messageActionGeoChatCheckin = 0xc7d53de, - mtpc_updateNewGeoChatMessage = 0x5a68e3f7, mtpc_wallPaperSolid = 0x63117f24, mtpc_updateNewEncryptedMessage = 0x12bcbd9a, mtpc_updateEncryptedChatTyping = 0x1710f156, @@ -352,7 +336,7 @@ enum { mtpc_updateWebPage = 0x2cc36971, mtpc_webPageEmpty = 0xeb1477e8, mtpc_webPagePending = 0xc586da1c, - mtpc_webPage = 0xa31ea0b5, + mtpc_webPage = 0xca820ed7, mtpc_messageMediaWebPage = 0xa32dd600, mtpc_authorization = 0x7bf2e6f6, mtpc_account_authorizations = 0x1250abde, @@ -399,6 +383,7 @@ enum { mtpc_messageEntityCode = 0x28a20571, mtpc_messageEntityPre = 0x73924be0, mtpc_messageEntityTextUrl = 0x76a6d327, + mtpc_updateShortSentMessage = 0x11f1331c, mtpc_invokeAfterMsg = 0xcb9f372d, mtpc_invokeAfterMsgs = 0x3dc4b4f0, mtpc_auth_checkPhone = 0x6fe51dfb, @@ -442,7 +427,7 @@ enum { mtpc_messages_deleteMessages = 0xa5f18925, mtpc_messages_receivedMessages = 0x5a954c0, mtpc_messages_setTyping = 0xa3825e50, - mtpc_messages_sendMessage = 0xdf12390, + mtpc_messages_sendMessage = 0xfa88427a, mtpc_messages_sendMedia = 0xc8f16791, mtpc_messages_forwardMessages = 0x55e1728d, mtpc_messages_getChats = 0x3c6aa187, @@ -467,18 +452,6 @@ enum { mtpc_photos_getUserPhotos = 0x91cd32a8, mtpc_messages_forwardMessage = 0x33963bf9, mtpc_messages_sendBroadcast = 0xbf73f4da, - mtpc_geochats_getLocated = 0x7f192d8f, - mtpc_geochats_getRecents = 0xe1427e6f, - mtpc_geochats_checkin = 0x55b3e8fb, - mtpc_geochats_getFullChat = 0x6722dd6f, - mtpc_geochats_editChatTitle = 0x4c8e2273, - mtpc_geochats_editChatPhoto = 0x35d81a95, - mtpc_geochats_search = 0xcfcdc44d, - mtpc_geochats_getHistory = 0xb53f7a68, - mtpc_geochats_setTyping = 0x8b8a729, - mtpc_geochats_sendMessage = 0x61b0044, - mtpc_geochats_sendMedia = 0xb8f0deff, - mtpc_geochats_createGeoChat = 0xe092e16, mtpc_messages_getDhConfig = 0x26cf8950, mtpc_messages_requestEncryption = 0xf64daf43, mtpc_messages_acceptEncryption = 0x3dbc0415, @@ -685,7 +658,6 @@ class MTPchat; class MTPDchatEmpty; class MTPDchat; class MTPDchatForbidden; -class MTPDgeoChat; class MTPchatFull; class MTPDchatFull; @@ -721,7 +693,6 @@ class MTPDmessageActionChatEditTitle; class MTPDmessageActionChatEditPhoto; class MTPDmessageActionChatAddUser; class MTPDmessageActionChatDeleteUser; -class MTPDmessageActionGeoChatCreate; class MTPDmessageActionChatJoinedByLink; class MTPdialog; @@ -758,7 +729,6 @@ class MTPDauth_exportedAuthorization; class MTPinputNotifyPeer; class MTPDinputNotifyPeer; -class MTPDinputNotifyGeoChatPeer; class MTPinputPeerNotifyEvents; @@ -792,9 +762,6 @@ class MTPDcontactSuggested; class MTPcontactStatus; class MTPDcontactStatus; -class MTPchatLocated; -class MTPDchatLocated; - class MTPcontacts_link; class MTPDcontacts_link; @@ -819,10 +786,6 @@ class MTPmessages_messages; class MTPDmessages_messages; class MTPDmessages_messagesSlice; -class MTPmessages_sentMessage; -class MTPDmessages_sentMessage; -class MTPDmessages_sentMessageLink; - class MTPmessages_chats; class MTPDmessages_chats; @@ -847,7 +810,6 @@ class MTPDupdateUserPhoto; class MTPDupdateContactRegistered; class MTPDupdateContactLink; class MTPDupdateNewAuthorization; -class MTPDupdateNewGeoChatMessage; class MTPDupdateNewEncryptedMessage; class MTPDupdateEncryptedChatTyping; class MTPDupdateEncryption; @@ -879,6 +841,7 @@ class MTPDupdateShortChatMessage; class MTPDupdateShort; class MTPDupdatesCombined; class MTPDupdates; +class MTPDupdateShortSentMessage; class MTPphotos_photos; class MTPDphotos_photos; @@ -905,24 +868,6 @@ class MTPDhelp_appUpdate; class MTPhelp_inviteText; class MTPDhelp_inviteText; -class MTPinputGeoChat; -class MTPDinputGeoChat; - -class MTPgeoChatMessage; -class MTPDgeoChatMessageEmpty; -class MTPDgeoChatMessage; -class MTPDgeoChatMessageService; - -class MTPgeochats_statedMessage; -class MTPDgeochats_statedMessage; - -class MTPgeochats_located; -class MTPDgeochats_located; - -class MTPgeochats_messages; -class MTPDgeochats_messages; -class MTPDgeochats_messagesSlice; - class MTPencryptedChat; class MTPDencryptedChatEmpty; class MTPDencryptedChatWaiting; @@ -1179,7 +1124,6 @@ typedef MTPBoxed MTPImportedContact; typedef MTPBoxed MTPContactBlocked; typedef MTPBoxed MTPContactSuggested; typedef MTPBoxed MTPContactStatus; -typedef MTPBoxed MTPChatLocated; typedef MTPBoxed MTPcontacts_Link; typedef MTPBoxed MTPcontacts_Contacts; typedef MTPBoxed MTPcontacts_ImportedContacts; @@ -1187,7 +1131,6 @@ typedef MTPBoxed MTPcontacts_Blocked; typedef MTPBoxed MTPcontacts_Suggested; typedef MTPBoxed MTPmessages_Dialogs; typedef MTPBoxed MTPmessages_Messages; -typedef MTPBoxed MTPmessages_SentMessage; typedef MTPBoxed MTPmessages_Chats; typedef MTPBoxed MTPmessages_ChatFull; typedef MTPBoxed MTPmessages_AffectedHistory; @@ -1204,11 +1147,6 @@ typedef MTPBoxed MTPConfig; typedef MTPBoxed MTPNearestDc; typedef MTPBoxed MTPhelp_AppUpdate; typedef MTPBoxed MTPhelp_InviteText; -typedef MTPBoxed MTPInputGeoChat; -typedef MTPBoxed MTPGeoChatMessage; -typedef MTPBoxed MTPgeochats_StatedMessage; -typedef MTPBoxed MTPgeochats_Located; -typedef MTPBoxed MTPgeochats_Messages; typedef MTPBoxed MTPEncryptedChat; typedef MTPBoxed MTPInputEncryptedChat; typedef MTPBoxed MTPEncryptedFile; @@ -2453,8 +2391,8 @@ private: friend MTPinputMedia MTP_inputMediaPhoto(const MTPInputPhoto &_id, const MTPstring &_caption); friend MTPinputMedia MTP_inputMediaGeoPoint(const MTPInputGeoPoint &_geo_point); friend MTPinputMedia MTP_inputMediaContact(const MTPstring &_phone_number, const MTPstring &_first_name, const MTPstring &_last_name); - friend MTPinputMedia MTP_inputMediaUploadedVideo(const MTPInputFile &_file, MTPint _duration, MTPint _w, MTPint _h, const MTPstring &_caption); - friend MTPinputMedia MTP_inputMediaUploadedThumbVideo(const MTPInputFile &_file, const MTPInputFile &_thumb, MTPint _duration, MTPint _w, MTPint _h, const MTPstring &_caption); + friend MTPinputMedia MTP_inputMediaUploadedVideo(const MTPInputFile &_file, MTPint _duration, MTPint _w, MTPint _h, const MTPstring &_mime_type, const MTPstring &_caption); + friend MTPinputMedia MTP_inputMediaUploadedThumbVideo(const MTPInputFile &_file, const MTPInputFile &_thumb, MTPint _duration, MTPint _w, MTPint _h, const MTPstring &_mime_type, const MTPstring &_caption); friend MTPinputMedia MTP_inputMediaVideo(const MTPInputVideo &_id, const MTPstring &_caption); friend MTPinputMedia MTP_inputMediaUploadedAudio(const MTPInputFile &_file, MTPint _duration, const MTPstring &_mime_type); friend MTPinputMedia MTP_inputMediaAudio(const MTPInputAudio &_id); @@ -3118,18 +3056,6 @@ public: return *(const MTPDchatForbidden*)data; } - MTPDgeoChat &_geoChat() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geoChat) throw mtpErrorWrongTypeId(_type, mtpc_geoChat); - split(); - return *(MTPDgeoChat*)data; - } - const MTPDgeoChat &c_geoChat() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geoChat) throw mtpErrorWrongTypeId(_type, mtpc_geoChat); - return *(const MTPDgeoChat*)data; - } - uint32 innerLength() const; mtpTypeId type() const; void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); @@ -3142,12 +3068,10 @@ private: explicit MTPchat(MTPDchatEmpty *_data); explicit MTPchat(MTPDchat *_data); explicit MTPchat(MTPDchatForbidden *_data); - explicit MTPchat(MTPDgeoChat *_data); friend MTPchat MTP_chatEmpty(MTPint _id); friend MTPchat MTP_chat(MTPint _id, const MTPstring &_title, const MTPChatPhoto &_photo, MTPint _participants_count, MTPint _date, MTPBool _left, MTPint _version); friend MTPchat MTP_chatForbidden(MTPint _id, const MTPstring &_title, MTPint _date); - friend MTPchat MTP_geoChat(MTPint _id, const MTPlong &_access_hash, const MTPstring &_title, const MTPstring &_address, const MTPstring &_venue, const MTPGeoPoint &_geo, const MTPChatPhoto &_photo, MTPint _participants_count, MTPint _date, MTPBool _checked_in, MTPint _version); mtpTypeId _type; }; @@ -3574,18 +3498,6 @@ public: return *(const MTPDmessageActionChatDeleteUser*)data; } - MTPDmessageActionGeoChatCreate &_messageActionGeoChatCreate() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messageActionGeoChatCreate) throw mtpErrorWrongTypeId(_type, mtpc_messageActionGeoChatCreate); - split(); - return *(MTPDmessageActionGeoChatCreate*)data; - } - const MTPDmessageActionGeoChatCreate &c_messageActionGeoChatCreate() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messageActionGeoChatCreate) throw mtpErrorWrongTypeId(_type, mtpc_messageActionGeoChatCreate); - return *(const MTPDmessageActionGeoChatCreate*)data; - } - MTPDmessageActionChatJoinedByLink &_messageActionChatJoinedByLink() { if (!data) throw mtpErrorUninitialized(); if (_type != mtpc_messageActionChatJoinedByLink) throw mtpErrorWrongTypeId(_type, mtpc_messageActionChatJoinedByLink); @@ -3612,7 +3524,6 @@ private: explicit MTPmessageAction(MTPDmessageActionChatEditPhoto *_data); explicit MTPmessageAction(MTPDmessageActionChatAddUser *_data); explicit MTPmessageAction(MTPDmessageActionChatDeleteUser *_data); - explicit MTPmessageAction(MTPDmessageActionGeoChatCreate *_data); explicit MTPmessageAction(MTPDmessageActionChatJoinedByLink *_data); friend MTPmessageAction MTP_messageActionEmpty(); @@ -3622,8 +3533,6 @@ private: friend MTPmessageAction MTP_messageActionChatDeletePhoto(); friend MTPmessageAction MTP_messageActionChatAddUser(MTPint _user_id); friend MTPmessageAction MTP_messageActionChatDeleteUser(MTPint _user_id); - friend MTPmessageAction MTP_messageActionGeoChatCreate(const MTPstring &_title, const MTPstring &_address); - friend MTPmessageAction MTP_messageActionGeoChatCheckin(); friend MTPmessageAction MTP_messageActionChatJoinedByLink(MTPint _inviter_id); mtpTypeId _type; @@ -4030,18 +3939,6 @@ public: return *(const MTPDinputNotifyPeer*)data; } - MTPDinputNotifyGeoChatPeer &_inputNotifyGeoChatPeer() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_inputNotifyGeoChatPeer) throw mtpErrorWrongTypeId(_type, mtpc_inputNotifyGeoChatPeer); - split(); - return *(MTPDinputNotifyGeoChatPeer*)data; - } - const MTPDinputNotifyGeoChatPeer &c_inputNotifyGeoChatPeer() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_inputNotifyGeoChatPeer) throw mtpErrorWrongTypeId(_type, mtpc_inputNotifyGeoChatPeer); - return *(const MTPDinputNotifyGeoChatPeer*)data; - } - uint32 innerLength() const; mtpTypeId type() const; void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); @@ -4052,13 +3949,11 @@ public: private: explicit MTPinputNotifyPeer(mtpTypeId type); explicit MTPinputNotifyPeer(MTPDinputNotifyPeer *_data); - explicit MTPinputNotifyPeer(MTPDinputNotifyGeoChatPeer *_data); friend MTPinputNotifyPeer MTP_inputNotifyPeer(const MTPInputPeer &_peer); friend MTPinputNotifyPeer MTP_inputNotifyUsers(); friend MTPinputNotifyPeer MTP_inputNotifyChats(); friend MTPinputNotifyPeer MTP_inputNotifyAll(); - friend MTPinputNotifyPeer MTP_inputNotifyGeoChatPeer(const MTPInputGeoChat &_peer); mtpTypeId _type; }; @@ -4420,37 +4315,6 @@ private: }; typedef MTPBoxed MTPContactStatus; -class MTPchatLocated : private mtpDataOwner { -public: - MTPchatLocated(); - MTPchatLocated(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_chatLocated) : mtpDataOwner(0) { - read(from, end, cons); - } - - MTPDchatLocated &_chatLocated() { - if (!data) throw mtpErrorUninitialized(); - split(); - return *(MTPDchatLocated*)data; - } - const MTPDchatLocated &c_chatLocated() const { - if (!data) throw mtpErrorUninitialized(); - return *(const MTPDchatLocated*)data; - } - - uint32 innerLength() const; - mtpTypeId type() const; - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_chatLocated); - void write(mtpBuffer &to) const; - - typedef void ResponseType; - -private: - explicit MTPchatLocated(MTPDchatLocated *_data); - - friend MTPchatLocated MTP_chatLocated(MTPint _chat_id, MTPint _distance); -}; -typedef MTPBoxed MTPChatLocated; - class MTPcontacts_link : private mtpDataOwner { public: MTPcontacts_link(); @@ -4735,57 +4599,6 @@ private: }; typedef MTPBoxed MTPmessages_Messages; -class MTPmessages_sentMessage : private mtpDataOwner { -public: - MTPmessages_sentMessage() : mtpDataOwner(0), _type(0) { - } - MTPmessages_sentMessage(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { - read(from, end, cons); - } - - MTPDmessages_sentMessage &_messages_sentMessage() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_sentMessage) throw mtpErrorWrongTypeId(_type, mtpc_messages_sentMessage); - split(); - return *(MTPDmessages_sentMessage*)data; - } - const MTPDmessages_sentMessage &c_messages_sentMessage() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_sentMessage) throw mtpErrorWrongTypeId(_type, mtpc_messages_sentMessage); - return *(const MTPDmessages_sentMessage*)data; - } - - MTPDmessages_sentMessageLink &_messages_sentMessageLink() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_sentMessageLink) throw mtpErrorWrongTypeId(_type, mtpc_messages_sentMessageLink); - split(); - return *(MTPDmessages_sentMessageLink*)data; - } - const MTPDmessages_sentMessageLink &c_messages_sentMessageLink() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_sentMessageLink) throw mtpErrorWrongTypeId(_type, mtpc_messages_sentMessageLink); - return *(const MTPDmessages_sentMessageLink*)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 MTPmessages_sentMessage(mtpTypeId type); - explicit MTPmessages_sentMessage(MTPDmessages_sentMessage *_data); - explicit MTPmessages_sentMessage(MTPDmessages_sentMessageLink *_data); - - friend MTPmessages_sentMessage MTP_messages_sentMessage(MTPint _id, MTPint _date, const MTPMessageMedia &_media, const MTPVector &_entities, MTPint _pts, MTPint _pts_count); - friend MTPmessages_sentMessage MTP_messages_sentMessageLink(MTPint _id, MTPint _date, const MTPMessageMedia &_media, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq); - - mtpTypeId _type; -}; -typedef MTPBoxed MTPmessages_SentMessage; - class MTPmessages_chats : private mtpDataOwner { public: MTPmessages_chats(); @@ -5063,18 +4876,6 @@ public: return *(const MTPDupdateNewAuthorization*)data; } - MTPDupdateNewGeoChatMessage &_updateNewGeoChatMessage() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_updateNewGeoChatMessage) throw mtpErrorWrongTypeId(_type, mtpc_updateNewGeoChatMessage); - split(); - return *(MTPDupdateNewGeoChatMessage*)data; - } - const MTPDupdateNewGeoChatMessage &c_updateNewGeoChatMessage() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_updateNewGeoChatMessage) throw mtpErrorWrongTypeId(_type, mtpc_updateNewGeoChatMessage); - return *(const MTPDupdateNewGeoChatMessage*)data; - } - MTPDupdateNewEncryptedMessage &_updateNewEncryptedMessage() { if (!data) throw mtpErrorUninitialized(); if (_type != mtpc_updateNewEncryptedMessage) throw mtpErrorWrongTypeId(_type, mtpc_updateNewEncryptedMessage); @@ -5288,7 +5089,6 @@ private: explicit MTPupdate(MTPDupdateContactRegistered *_data); explicit MTPupdate(MTPDupdateContactLink *_data); explicit MTPupdate(MTPDupdateNewAuthorization *_data); - explicit MTPupdate(MTPDupdateNewGeoChatMessage *_data); explicit MTPupdate(MTPDupdateNewEncryptedMessage *_data); explicit MTPupdate(MTPDupdateEncryptedChatTyping *_data); explicit MTPupdate(MTPDupdateEncryption *_data); @@ -5318,7 +5118,6 @@ private: friend MTPupdate MTP_updateContactRegistered(MTPint _user_id, MTPint _date); friend MTPupdate MTP_updateContactLink(MTPint _user_id, const MTPContactLink &_my_link, const MTPContactLink &_foreign_link); friend MTPupdate MTP_updateNewAuthorization(const MTPlong &_auth_key_id, MTPint _date, const MTPstring &_device, const MTPstring &_location); - friend MTPupdate MTP_updateNewGeoChatMessage(const MTPGeoChatMessage &_message); friend MTPupdate MTP_updateNewEncryptedMessage(const MTPEncryptedMessage &_message, MTPint _qts); friend MTPupdate MTP_updateEncryptedChatTyping(MTPint _chat_id); friend MTPupdate MTP_updateEncryption(const MTPEncryptedChat &_chat, MTPint _date); @@ -5504,6 +5303,18 @@ public: return *(const MTPDupdates*)data; } + MTPDupdateShortSentMessage &_updateShortSentMessage() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_updateShortSentMessage) throw mtpErrorWrongTypeId(_type, mtpc_updateShortSentMessage); + split(); + return *(MTPDupdateShortSentMessage*)data; + } + const MTPDupdateShortSentMessage &c_updateShortSentMessage() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_updateShortSentMessage) throw mtpErrorWrongTypeId(_type, mtpc_updateShortSentMessage); + return *(const MTPDupdateShortSentMessage*)data; + } + uint32 innerLength() const; mtpTypeId type() const; void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); @@ -5518,6 +5329,7 @@ private: explicit MTPupdates(MTPDupdateShort *_data); explicit MTPupdates(MTPDupdatesCombined *_data); explicit MTPupdates(MTPDupdates *_data); + explicit MTPupdates(MTPDupdateShortSentMessage *_data); friend MTPupdates MTP_updatesTooLong(); friend MTPupdates MTP_updateShortMessage(MTPint _flags, MTPint _id, MTPint _user_id, const MTPstring &_message, MTPint _pts, MTPint _pts_count, MTPint _date, MTPint _fwd_from_id, MTPint _fwd_date, MTPint _reply_to_msg_id, const MTPVector &_entities); @@ -5525,6 +5337,7 @@ private: friend MTPupdates MTP_updateShort(const MTPUpdate &_update, MTPint _date); friend MTPupdates MTP_updatesCombined(const MTPVector &_updates, const MTPVector &_users, const MTPVector &_chats, MTPint _date, MTPint _seq_start, MTPint _seq); friend MTPupdates MTP_updates(const MTPVector &_updates, const MTPVector &_users, const MTPVector &_chats, MTPint _date, MTPint _seq); + friend MTPupdates MTP_updateShortSentMessage(MTPint _flags, MTPint _id, MTPint _pts, MTPint _pts_count, MTPint _date, const MTPMessageMedia &_media, const MTPVector &_entities); mtpTypeId _type; }; @@ -5805,215 +5618,6 @@ private: }; typedef MTPBoxed MTPhelp_InviteText; -class MTPinputGeoChat : private mtpDataOwner { -public: - MTPinputGeoChat(); - MTPinputGeoChat(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_inputGeoChat) : mtpDataOwner(0) { - read(from, end, cons); - } - - MTPDinputGeoChat &_inputGeoChat() { - if (!data) throw mtpErrorUninitialized(); - split(); - return *(MTPDinputGeoChat*)data; - } - const MTPDinputGeoChat &c_inputGeoChat() const { - if (!data) throw mtpErrorUninitialized(); - return *(const MTPDinputGeoChat*)data; - } - - uint32 innerLength() const; - mtpTypeId type() const; - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_inputGeoChat); - void write(mtpBuffer &to) const; - - typedef void ResponseType; - -private: - explicit MTPinputGeoChat(MTPDinputGeoChat *_data); - - friend MTPinputGeoChat MTP_inputGeoChat(MTPint _chat_id, const MTPlong &_access_hash); -}; -typedef MTPBoxed MTPInputGeoChat; - -class MTPgeoChatMessage : private mtpDataOwner { -public: - MTPgeoChatMessage() : mtpDataOwner(0), _type(0) { - } - MTPgeoChatMessage(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { - read(from, end, cons); - } - - MTPDgeoChatMessageEmpty &_geoChatMessageEmpty() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geoChatMessageEmpty) throw mtpErrorWrongTypeId(_type, mtpc_geoChatMessageEmpty); - split(); - return *(MTPDgeoChatMessageEmpty*)data; - } - const MTPDgeoChatMessageEmpty &c_geoChatMessageEmpty() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geoChatMessageEmpty) throw mtpErrorWrongTypeId(_type, mtpc_geoChatMessageEmpty); - return *(const MTPDgeoChatMessageEmpty*)data; - } - - MTPDgeoChatMessage &_geoChatMessage() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geoChatMessage) throw mtpErrorWrongTypeId(_type, mtpc_geoChatMessage); - split(); - return *(MTPDgeoChatMessage*)data; - } - const MTPDgeoChatMessage &c_geoChatMessage() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geoChatMessage) throw mtpErrorWrongTypeId(_type, mtpc_geoChatMessage); - return *(const MTPDgeoChatMessage*)data; - } - - MTPDgeoChatMessageService &_geoChatMessageService() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geoChatMessageService) throw mtpErrorWrongTypeId(_type, mtpc_geoChatMessageService); - split(); - return *(MTPDgeoChatMessageService*)data; - } - const MTPDgeoChatMessageService &c_geoChatMessageService() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geoChatMessageService) throw mtpErrorWrongTypeId(_type, mtpc_geoChatMessageService); - return *(const MTPDgeoChatMessageService*)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 MTPgeoChatMessage(mtpTypeId type); - explicit MTPgeoChatMessage(MTPDgeoChatMessageEmpty *_data); - explicit MTPgeoChatMessage(MTPDgeoChatMessage *_data); - explicit MTPgeoChatMessage(MTPDgeoChatMessageService *_data); - - friend MTPgeoChatMessage MTP_geoChatMessageEmpty(MTPint _chat_id, MTPint _id); - friend MTPgeoChatMessage MTP_geoChatMessage(MTPint _chat_id, MTPint _id, MTPint _from_id, MTPint _date, const MTPstring &_message, const MTPMessageMedia &_media); - friend MTPgeoChatMessage MTP_geoChatMessageService(MTPint _chat_id, MTPint _id, MTPint _from_id, MTPint _date, const MTPMessageAction &_action); - - mtpTypeId _type; -}; -typedef MTPBoxed MTPGeoChatMessage; - -class MTPgeochats_statedMessage : private mtpDataOwner { -public: - MTPgeochats_statedMessage(); - MTPgeochats_statedMessage(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_statedMessage) : mtpDataOwner(0) { - read(from, end, cons); - } - - MTPDgeochats_statedMessage &_geochats_statedMessage() { - if (!data) throw mtpErrorUninitialized(); - split(); - return *(MTPDgeochats_statedMessage*)data; - } - const MTPDgeochats_statedMessage &c_geochats_statedMessage() const { - if (!data) throw mtpErrorUninitialized(); - return *(const MTPDgeochats_statedMessage*)data; - } - - uint32 innerLength() const; - mtpTypeId type() const; - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_statedMessage); - void write(mtpBuffer &to) const; - - typedef void ResponseType; - -private: - explicit MTPgeochats_statedMessage(MTPDgeochats_statedMessage *_data); - - friend MTPgeochats_statedMessage MTP_geochats_statedMessage(const MTPGeoChatMessage &_message, const MTPVector &_chats, const MTPVector &_users, MTPint _seq); -}; -typedef MTPBoxed MTPgeochats_StatedMessage; - -class MTPgeochats_located : private mtpDataOwner { -public: - MTPgeochats_located(); - MTPgeochats_located(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_located) : mtpDataOwner(0) { - read(from, end, cons); - } - - MTPDgeochats_located &_geochats_located() { - if (!data) throw mtpErrorUninitialized(); - split(); - return *(MTPDgeochats_located*)data; - } - const MTPDgeochats_located &c_geochats_located() const { - if (!data) throw mtpErrorUninitialized(); - return *(const MTPDgeochats_located*)data; - } - - uint32 innerLength() const; - mtpTypeId type() const; - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_located); - void write(mtpBuffer &to) const; - - typedef void ResponseType; - -private: - explicit MTPgeochats_located(MTPDgeochats_located *_data); - - friend MTPgeochats_located MTP_geochats_located(const MTPVector &_results, const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users); -}; -typedef MTPBoxed MTPgeochats_Located; - -class MTPgeochats_messages : private mtpDataOwner { -public: - MTPgeochats_messages() : mtpDataOwner(0), _type(0) { - } - MTPgeochats_messages(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { - read(from, end, cons); - } - - MTPDgeochats_messages &_geochats_messages() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geochats_messages) throw mtpErrorWrongTypeId(_type, mtpc_geochats_messages); - split(); - return *(MTPDgeochats_messages*)data; - } - const MTPDgeochats_messages &c_geochats_messages() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geochats_messages) throw mtpErrorWrongTypeId(_type, mtpc_geochats_messages); - return *(const MTPDgeochats_messages*)data; - } - - MTPDgeochats_messagesSlice &_geochats_messagesSlice() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geochats_messagesSlice) throw mtpErrorWrongTypeId(_type, mtpc_geochats_messagesSlice); - split(); - return *(MTPDgeochats_messagesSlice*)data; - } - const MTPDgeochats_messagesSlice &c_geochats_messagesSlice() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_geochats_messagesSlice) throw mtpErrorWrongTypeId(_type, mtpc_geochats_messagesSlice); - return *(const MTPDgeochats_messagesSlice*)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 MTPgeochats_messages(mtpTypeId type); - explicit MTPgeochats_messages(MTPDgeochats_messages *_data); - explicit MTPgeochats_messages(MTPDgeochats_messagesSlice *_data); - - friend MTPgeochats_messages MTP_geochats_messages(const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users); - friend MTPgeochats_messages MTP_geochats_messagesSlice(MTPint _count, const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users); - - mtpTypeId _type; -}; -typedef MTPBoxed MTPgeochats_Messages; - class MTPencryptedChat : private mtpDataOwner { public: MTPencryptedChat() : mtpDataOwner(0), _type(0) { @@ -7385,7 +6989,7 @@ private: friend MTPwebPage MTP_webPageEmpty(const MTPlong &_id); friend MTPwebPage MTP_webPagePending(const MTPlong &_id, MTPint _date); - friend MTPwebPage MTP_webPage(MTPint _flags, const MTPlong &_id, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_site_name, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _embed_width, MTPint _embed_height, MTPint _duration, const MTPstring &_author); + friend MTPwebPage MTP_webPage(MTPint _flags, const MTPlong &_id, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_site_name, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _embed_width, MTPint _embed_height, MTPint _duration, const MTPstring &_author, const MTPDocument &_document); mtpTypeId _type; }; @@ -8693,13 +8297,14 @@ class MTPDinputMediaUploadedVideo : public mtpDataImpl { -public: - MTPDgeoChat() { - } - MTPDgeoChat(MTPint _id, const MTPlong &_access_hash, const MTPstring &_title, const MTPstring &_address, const MTPstring &_venue, const MTPGeoPoint &_geo, const MTPChatPhoto &_photo, MTPint _participants_count, MTPint _date, MTPBool _checked_in, MTPint _version) : vid(_id), vaccess_hash(_access_hash), vtitle(_title), vaddress(_address), vvenue(_venue), vgeo(_geo), vphoto(_photo), vparticipants_count(_participants_count), vdate(_date), vchecked_in(_checked_in), vversion(_version) { - } - - MTPint vid; - MTPlong vaccess_hash; - MTPstring vtitle; - MTPstring vaddress; - MTPstring vvenue; - MTPGeoPoint vgeo; - MTPChatPhoto vphoto; - MTPint vparticipants_count; - MTPint vdate; - MTPBool vchecked_in; - MTPint vversion; -}; - class MTPDchatFull : public mtpDataImpl { public: MTPDchatFull() { @@ -9215,6 +8801,7 @@ public: flag_fwd_from_id = (1 << 2), flag_fwd_date = (1 << 2), flag_reply_to_msg_id = (1 << 3), + flag_media = (1 << 9), flag_reply_markup = (1 << 6), flag_entities = (1 << 7), }; @@ -9222,6 +8809,7 @@ public: bool has_fwd_from_id() const { return vflags.v & flag_fwd_from_id; } bool has_fwd_date() const { return vflags.v & flag_fwd_date; } bool has_reply_to_msg_id() const { return vflags.v & flag_reply_to_msg_id; } + bool has_media() const { return vflags.v & flag_media; } bool has_reply_markup() const { return vflags.v & flag_reply_markup; } bool has_entities() const { return vflags.v & flag_entities; } }; @@ -9381,17 +8969,6 @@ public: MTPint vuser_id; }; -class MTPDmessageActionGeoChatCreate : public mtpDataImpl { -public: - MTPDmessageActionGeoChatCreate() { - } - MTPDmessageActionGeoChatCreate(const MTPstring &_title, const MTPstring &_address) : vtitle(_title), vaddress(_address) { - } - - MTPstring vtitle; - MTPstring vaddress; -}; - class MTPDmessageActionChatJoinedByLink : public mtpDataImpl { public: MTPDmessageActionChatJoinedByLink() { @@ -9584,16 +9161,6 @@ public: MTPInputPeer vpeer; }; -class MTPDinputNotifyGeoChatPeer : public mtpDataImpl { -public: - MTPDinputNotifyGeoChatPeer() { - } - MTPDinputNotifyGeoChatPeer(const MTPInputGeoChat &_peer) : vpeer(_peer) { - } - - MTPInputGeoChat vpeer; -}; - class MTPDinputPeerNotifySettings : public mtpDataImpl { public: MTPDinputPeerNotifySettings() { @@ -9716,17 +9283,6 @@ public: MTPUserStatus vstatus; }; -class MTPDchatLocated : public mtpDataImpl { -public: - MTPDchatLocated() { - } - MTPDchatLocated(MTPint _chat_id, MTPint _distance) : vchat_id(_chat_id), vdistance(_distance) { - } - - MTPint vchat_id; - MTPint vdistance; -}; - class MTPDcontacts_link : public mtpDataImpl { public: MTPDcontacts_link() { @@ -9848,37 +9404,6 @@ public: MTPVector vusers; }; -class MTPDmessages_sentMessage : public mtpDataImpl { -public: - MTPDmessages_sentMessage() { - } - MTPDmessages_sentMessage(MTPint _id, MTPint _date, const MTPMessageMedia &_media, const MTPVector &_entities, MTPint _pts, MTPint _pts_count) : vid(_id), vdate(_date), vmedia(_media), ventities(_entities), vpts(_pts), vpts_count(_pts_count) { - } - - MTPint vid; - MTPint vdate; - MTPMessageMedia vmedia; - MTPVector ventities; - MTPint vpts; - MTPint vpts_count; -}; - -class MTPDmessages_sentMessageLink : public mtpDataImpl { -public: - MTPDmessages_sentMessageLink() { - } - MTPDmessages_sentMessageLink(MTPint _id, MTPint _date, const MTPMessageMedia &_media, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq) : vid(_id), vdate(_date), vmedia(_media), vpts(_pts), vpts_count(_pts_count), vlinks(_links), vseq(_seq) { - } - - MTPint vid; - MTPint vdate; - MTPMessageMedia vmedia; - MTPint vpts; - MTPint vpts_count; - MTPVector vlinks; - MTPint vseq; -}; - class MTPDmessages_chats : public mtpDataImpl { public: MTPDmessages_chats() { @@ -10054,16 +9579,6 @@ public: MTPstring vlocation; }; -class MTPDupdateNewGeoChatMessage : public mtpDataImpl { -public: - MTPDupdateNewGeoChatMessage() { - } - MTPDupdateNewGeoChatMessage(const MTPGeoChatMessage &_message) : vmessage(_message) { - } - - MTPGeoChatMessage vmessage; -}; - class MTPDupdateNewEncryptedMessage : public mtpDataImpl { public: MTPDupdateNewEncryptedMessage() { @@ -10408,6 +9923,30 @@ public: MTPint vseq; }; +class MTPDupdateShortSentMessage : public mtpDataImpl { +public: + MTPDupdateShortSentMessage() { + } + MTPDupdateShortSentMessage(MTPint _flags, MTPint _id, MTPint _pts, MTPint _pts_count, MTPint _date, const MTPMessageMedia &_media, const MTPVector &_entities) : vflags(_flags), vid(_id), vpts(_pts), vpts_count(_pts_count), vdate(_date), vmedia(_media), ventities(_entities) { + } + + MTPint vflags; + MTPint vid; + MTPint vpts; + MTPint vpts_count; + MTPint vdate; + MTPMessageMedia vmedia; + MTPVector ventities; + + enum { + flag_media = (1 << 9), + flag_entities = (1 << 7), + }; + + bool has_media() const { return vflags.v & flag_media; } + bool has_entities() const { return vflags.v & flag_entities; } +}; + class MTPDphotos_photos : public mtpDataImpl { public: MTPDphotos_photos() { @@ -10529,108 +10068,6 @@ public: MTPstring vmessage; }; -class MTPDinputGeoChat : public mtpDataImpl { -public: - MTPDinputGeoChat() { - } - MTPDinputGeoChat(MTPint _chat_id, const MTPlong &_access_hash) : vchat_id(_chat_id), vaccess_hash(_access_hash) { - } - - MTPint vchat_id; - MTPlong vaccess_hash; -}; - -class MTPDgeoChatMessageEmpty : public mtpDataImpl { -public: - MTPDgeoChatMessageEmpty() { - } - MTPDgeoChatMessageEmpty(MTPint _chat_id, MTPint _id) : vchat_id(_chat_id), vid(_id) { - } - - MTPint vchat_id; - MTPint vid; -}; - -class MTPDgeoChatMessage : public mtpDataImpl { -public: - MTPDgeoChatMessage() { - } - MTPDgeoChatMessage(MTPint _chat_id, MTPint _id, MTPint _from_id, MTPint _date, const MTPstring &_message, const MTPMessageMedia &_media) : vchat_id(_chat_id), vid(_id), vfrom_id(_from_id), vdate(_date), vmessage(_message), vmedia(_media) { - } - - MTPint vchat_id; - MTPint vid; - MTPint vfrom_id; - MTPint vdate; - MTPstring vmessage; - MTPMessageMedia vmedia; -}; - -class MTPDgeoChatMessageService : public mtpDataImpl { -public: - MTPDgeoChatMessageService() { - } - MTPDgeoChatMessageService(MTPint _chat_id, MTPint _id, MTPint _from_id, MTPint _date, const MTPMessageAction &_action) : vchat_id(_chat_id), vid(_id), vfrom_id(_from_id), vdate(_date), vaction(_action) { - } - - MTPint vchat_id; - MTPint vid; - MTPint vfrom_id; - MTPint vdate; - MTPMessageAction vaction; -}; - -class MTPDgeochats_statedMessage : public mtpDataImpl { -public: - MTPDgeochats_statedMessage() { - } - MTPDgeochats_statedMessage(const MTPGeoChatMessage &_message, const MTPVector &_chats, const MTPVector &_users, MTPint _seq) : vmessage(_message), vchats(_chats), vusers(_users), vseq(_seq) { - } - - MTPGeoChatMessage vmessage; - MTPVector vchats; - MTPVector vusers; - MTPint vseq; -}; - -class MTPDgeochats_located : public mtpDataImpl { -public: - MTPDgeochats_located() { - } - MTPDgeochats_located(const MTPVector &_results, const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users) : vresults(_results), vmessages(_messages), vchats(_chats), vusers(_users) { - } - - MTPVector vresults; - MTPVector vmessages; - MTPVector vchats; - MTPVector vusers; -}; - -class MTPDgeochats_messages : public mtpDataImpl { -public: - MTPDgeochats_messages() { - } - MTPDgeochats_messages(const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users) : vmessages(_messages), vchats(_chats), vusers(_users) { - } - - MTPVector vmessages; - MTPVector vchats; - MTPVector vusers; -}; - -class MTPDgeochats_messagesSlice : public mtpDataImpl { -public: - MTPDgeochats_messagesSlice() { - } - MTPDgeochats_messagesSlice(MTPint _count, const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users) : vcount(_count), vmessages(_messages), vchats(_chats), vusers(_users) { - } - - MTPint vcount; - MTPVector vmessages; - MTPVector vchats; - MTPVector vusers; -}; - class MTPDencryptedChatEmpty : public mtpDataImpl { public: MTPDencryptedChatEmpty() { @@ -11193,7 +10630,7 @@ class MTPDwebPage : public mtpDataImpl { public: MTPDwebPage() { } - MTPDwebPage(MTPint _flags, const MTPlong &_id, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_site_name, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _embed_width, MTPint _embed_height, MTPint _duration, const MTPstring &_author) : vflags(_flags), vid(_id), vurl(_url), vdisplay_url(_display_url), vtype(_type), vsite_name(_site_name), vtitle(_title), vdescription(_description), vphoto(_photo), vembed_url(_embed_url), vembed_type(_embed_type), vembed_width(_embed_width), vembed_height(_embed_height), vduration(_duration), vauthor(_author) { + MTPDwebPage(MTPint _flags, const MTPlong &_id, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_site_name, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _embed_width, MTPint _embed_height, MTPint _duration, const MTPstring &_author, const MTPDocument &_document) : vflags(_flags), vid(_id), vurl(_url), vdisplay_url(_display_url), vtype(_type), vsite_name(_site_name), vtitle(_title), vdescription(_description), vphoto(_photo), vembed_url(_embed_url), vembed_type(_embed_type), vembed_width(_embed_width), vembed_height(_embed_height), vduration(_duration), vauthor(_author), vdocument(_document) { } MTPint vflags; @@ -11211,6 +10648,7 @@ public: MTPint vembed_height; MTPint vduration; MTPstring vauthor; + MTPDocument vdocument; enum { flag_type = (1 << 0), @@ -11224,6 +10662,7 @@ public: flag_embed_height = (1 << 6), flag_duration = (1 << 7), flag_author = (1 << 8), + flag_document = (1 << 9), }; bool has_type() const { return vflags.v & flag_type; } @@ -11237,6 +10676,7 @@ public: bool has_embed_height() const { return vflags.v & flag_embed_height; } bool has_duration() const { return vflags.v & flag_duration; } bool has_author() const { return vflags.v & flag_author; } + bool has_document() const { return vflags.v & flag_document; } }; class MTPDauthorization : public mtpDataImpl { @@ -13847,7 +13287,7 @@ public: if (has_entities()) ventities.write(to); } - typedef MTPmessages_SentMessage ResponseType; + typedef MTPUpdates ResponseType; }; class MTPmessages_SendMessage : public MTPBoxed { public: @@ -14883,546 +14323,6 @@ public: } }; -class MTPgeochats_getLocated { // RPC method 'geochats.getLocated' -public: - MTPInputGeoPoint vgeo_point; - MTPint vradius; - MTPint vlimit; - - MTPgeochats_getLocated() { - } - MTPgeochats_getLocated(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_getLocated) { - read(from, end, cons); - } - MTPgeochats_getLocated(const MTPInputGeoPoint &_geo_point, MTPint _radius, MTPint _limit) : vgeo_point(_geo_point), vradius(_radius), vlimit(_limit) { - } - - uint32 innerLength() const { - return vgeo_point.innerLength() + vradius.innerLength() + vlimit.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_getLocated; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_getLocated) { - vgeo_point.read(from, end); - vradius.read(from, end); - vlimit.read(from, end); - } - void write(mtpBuffer &to) const { - vgeo_point.write(to); - vradius.write(to); - vlimit.write(to); - } - - typedef MTPgeochats_Located ResponseType; -}; -class MTPgeochats_GetLocated : public MTPBoxed { -public: - MTPgeochats_GetLocated() { - } - MTPgeochats_GetLocated(const MTPgeochats_getLocated &v) : MTPBoxed(v) { - } - MTPgeochats_GetLocated(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_GetLocated(const MTPInputGeoPoint &_geo_point, MTPint _radius, MTPint _limit) : MTPBoxed(MTPgeochats_getLocated(_geo_point, _radius, _limit)) { - } -}; - -class MTPgeochats_getRecents { // RPC method 'geochats.getRecents' -public: - MTPint voffset; - MTPint vlimit; - - MTPgeochats_getRecents() { - } - MTPgeochats_getRecents(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_getRecents) { - read(from, end, cons); - } - MTPgeochats_getRecents(MTPint _offset, MTPint _limit) : voffset(_offset), vlimit(_limit) { - } - - uint32 innerLength() const { - return voffset.innerLength() + vlimit.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_getRecents; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_getRecents) { - voffset.read(from, end); - vlimit.read(from, end); - } - void write(mtpBuffer &to) const { - voffset.write(to); - vlimit.write(to); - } - - typedef MTPgeochats_Messages ResponseType; -}; -class MTPgeochats_GetRecents : public MTPBoxed { -public: - MTPgeochats_GetRecents() { - } - MTPgeochats_GetRecents(const MTPgeochats_getRecents &v) : MTPBoxed(v) { - } - MTPgeochats_GetRecents(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_GetRecents(MTPint _offset, MTPint _limit) : MTPBoxed(MTPgeochats_getRecents(_offset, _limit)) { - } -}; - -class MTPgeochats_checkin { // RPC method 'geochats.checkin' -public: - MTPInputGeoChat vpeer; - - MTPgeochats_checkin() { - } - MTPgeochats_checkin(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_checkin) { - read(from, end, cons); - } - MTPgeochats_checkin(const MTPInputGeoChat &_peer) : vpeer(_peer) { - } - - uint32 innerLength() const { - return vpeer.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_checkin; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_checkin) { - vpeer.read(from, end); - } - void write(mtpBuffer &to) const { - vpeer.write(to); - } - - typedef MTPgeochats_StatedMessage ResponseType; -}; -class MTPgeochats_Checkin : public MTPBoxed { -public: - MTPgeochats_Checkin() { - } - MTPgeochats_Checkin(const MTPgeochats_checkin &v) : MTPBoxed(v) { - } - MTPgeochats_Checkin(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_Checkin(const MTPInputGeoChat &_peer) : MTPBoxed(MTPgeochats_checkin(_peer)) { - } -}; - -class MTPgeochats_getFullChat { // RPC method 'geochats.getFullChat' -public: - MTPInputGeoChat vpeer; - - MTPgeochats_getFullChat() { - } - MTPgeochats_getFullChat(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_getFullChat) { - read(from, end, cons); - } - MTPgeochats_getFullChat(const MTPInputGeoChat &_peer) : vpeer(_peer) { - } - - uint32 innerLength() const { - return vpeer.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_getFullChat; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_getFullChat) { - vpeer.read(from, end); - } - void write(mtpBuffer &to) const { - vpeer.write(to); - } - - typedef MTPmessages_ChatFull ResponseType; -}; -class MTPgeochats_GetFullChat : public MTPBoxed { -public: - MTPgeochats_GetFullChat() { - } - MTPgeochats_GetFullChat(const MTPgeochats_getFullChat &v) : MTPBoxed(v) { - } - MTPgeochats_GetFullChat(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_GetFullChat(const MTPInputGeoChat &_peer) : MTPBoxed(MTPgeochats_getFullChat(_peer)) { - } -}; - -class MTPgeochats_editChatTitle { // RPC method 'geochats.editChatTitle' -public: - MTPInputGeoChat vpeer; - MTPstring vtitle; - MTPstring vaddress; - - MTPgeochats_editChatTitle() { - } - MTPgeochats_editChatTitle(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_editChatTitle) { - read(from, end, cons); - } - MTPgeochats_editChatTitle(const MTPInputGeoChat &_peer, const MTPstring &_title, const MTPstring &_address) : vpeer(_peer), vtitle(_title), vaddress(_address) { - } - - uint32 innerLength() const { - return vpeer.innerLength() + vtitle.innerLength() + vaddress.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_editChatTitle; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_editChatTitle) { - vpeer.read(from, end); - vtitle.read(from, end); - vaddress.read(from, end); - } - void write(mtpBuffer &to) const { - vpeer.write(to); - vtitle.write(to); - vaddress.write(to); - } - - typedef MTPgeochats_StatedMessage ResponseType; -}; -class MTPgeochats_EditChatTitle : public MTPBoxed { -public: - MTPgeochats_EditChatTitle() { - } - MTPgeochats_EditChatTitle(const MTPgeochats_editChatTitle &v) : MTPBoxed(v) { - } - MTPgeochats_EditChatTitle(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_EditChatTitle(const MTPInputGeoChat &_peer, const MTPstring &_title, const MTPstring &_address) : MTPBoxed(MTPgeochats_editChatTitle(_peer, _title, _address)) { - } -}; - -class MTPgeochats_editChatPhoto { // RPC method 'geochats.editChatPhoto' -public: - MTPInputGeoChat vpeer; - MTPInputChatPhoto vphoto; - - MTPgeochats_editChatPhoto() { - } - MTPgeochats_editChatPhoto(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_editChatPhoto) { - read(from, end, cons); - } - MTPgeochats_editChatPhoto(const MTPInputGeoChat &_peer, const MTPInputChatPhoto &_photo) : vpeer(_peer), vphoto(_photo) { - } - - uint32 innerLength() const { - return vpeer.innerLength() + vphoto.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_editChatPhoto; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_editChatPhoto) { - vpeer.read(from, end); - vphoto.read(from, end); - } - void write(mtpBuffer &to) const { - vpeer.write(to); - vphoto.write(to); - } - - typedef MTPgeochats_StatedMessage ResponseType; -}; -class MTPgeochats_EditChatPhoto : public MTPBoxed { -public: - MTPgeochats_EditChatPhoto() { - } - MTPgeochats_EditChatPhoto(const MTPgeochats_editChatPhoto &v) : MTPBoxed(v) { - } - MTPgeochats_EditChatPhoto(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_EditChatPhoto(const MTPInputGeoChat &_peer, const MTPInputChatPhoto &_photo) : MTPBoxed(MTPgeochats_editChatPhoto(_peer, _photo)) { - } -}; - -class MTPgeochats_search { // RPC method 'geochats.search' -public: - MTPInputGeoChat vpeer; - MTPstring vq; - MTPMessagesFilter vfilter; - MTPint vmin_date; - MTPint vmax_date; - MTPint voffset; - MTPint vmax_id; - MTPint vlimit; - - MTPgeochats_search() { - } - MTPgeochats_search(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_search) { - read(from, end, cons); - } - MTPgeochats_search(const MTPInputGeoChat &_peer, const MTPstring &_q, const MTPMessagesFilter &_filter, MTPint _min_date, MTPint _max_date, MTPint _offset, MTPint _max_id, MTPint _limit) : vpeer(_peer), vq(_q), vfilter(_filter), vmin_date(_min_date), vmax_date(_max_date), voffset(_offset), vmax_id(_max_id), vlimit(_limit) { - } - - uint32 innerLength() const { - return vpeer.innerLength() + vq.innerLength() + vfilter.innerLength() + vmin_date.innerLength() + vmax_date.innerLength() + voffset.innerLength() + vmax_id.innerLength() + vlimit.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_search; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_search) { - vpeer.read(from, end); - vq.read(from, end); - vfilter.read(from, end); - vmin_date.read(from, end); - vmax_date.read(from, end); - voffset.read(from, end); - vmax_id.read(from, end); - vlimit.read(from, end); - } - void write(mtpBuffer &to) const { - vpeer.write(to); - vq.write(to); - vfilter.write(to); - vmin_date.write(to); - vmax_date.write(to); - voffset.write(to); - vmax_id.write(to); - vlimit.write(to); - } - - typedef MTPgeochats_Messages ResponseType; -}; -class MTPgeochats_Search : public MTPBoxed { -public: - MTPgeochats_Search() { - } - MTPgeochats_Search(const MTPgeochats_search &v) : MTPBoxed(v) { - } - MTPgeochats_Search(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_Search(const MTPInputGeoChat &_peer, const MTPstring &_q, const MTPMessagesFilter &_filter, MTPint _min_date, MTPint _max_date, MTPint _offset, MTPint _max_id, MTPint _limit) : MTPBoxed(MTPgeochats_search(_peer, _q, _filter, _min_date, _max_date, _offset, _max_id, _limit)) { - } -}; - -class MTPgeochats_getHistory { // RPC method 'geochats.getHistory' -public: - MTPInputGeoChat vpeer; - MTPint voffset; - MTPint vmax_id; - MTPint vlimit; - - MTPgeochats_getHistory() { - } - MTPgeochats_getHistory(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_getHistory) { - read(from, end, cons); - } - MTPgeochats_getHistory(const MTPInputGeoChat &_peer, MTPint _offset, MTPint _max_id, MTPint _limit) : vpeer(_peer), voffset(_offset), vmax_id(_max_id), vlimit(_limit) { - } - - uint32 innerLength() const { - return vpeer.innerLength() + voffset.innerLength() + vmax_id.innerLength() + vlimit.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_getHistory; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_getHistory) { - vpeer.read(from, end); - voffset.read(from, end); - vmax_id.read(from, end); - vlimit.read(from, end); - } - void write(mtpBuffer &to) const { - vpeer.write(to); - voffset.write(to); - vmax_id.write(to); - vlimit.write(to); - } - - typedef MTPgeochats_Messages ResponseType; -}; -class MTPgeochats_GetHistory : public MTPBoxed { -public: - MTPgeochats_GetHistory() { - } - MTPgeochats_GetHistory(const MTPgeochats_getHistory &v) : MTPBoxed(v) { - } - MTPgeochats_GetHistory(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_GetHistory(const MTPInputGeoChat &_peer, MTPint _offset, MTPint _max_id, MTPint _limit) : MTPBoxed(MTPgeochats_getHistory(_peer, _offset, _max_id, _limit)) { - } -}; - -class MTPgeochats_setTyping { // RPC method 'geochats.setTyping' -public: - MTPInputGeoChat vpeer; - MTPBool vtyping; - - MTPgeochats_setTyping() { - } - MTPgeochats_setTyping(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_setTyping) { - read(from, end, cons); - } - MTPgeochats_setTyping(const MTPInputGeoChat &_peer, MTPBool _typing) : vpeer(_peer), vtyping(_typing) { - } - - uint32 innerLength() const { - return vpeer.innerLength() + vtyping.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_setTyping; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_setTyping) { - vpeer.read(from, end); - vtyping.read(from, end); - } - void write(mtpBuffer &to) const { - vpeer.write(to); - vtyping.write(to); - } - - typedef MTPBool ResponseType; -}; -class MTPgeochats_SetTyping : public MTPBoxed { -public: - MTPgeochats_SetTyping() { - } - MTPgeochats_SetTyping(const MTPgeochats_setTyping &v) : MTPBoxed(v) { - } - MTPgeochats_SetTyping(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_SetTyping(const MTPInputGeoChat &_peer, MTPBool _typing) : MTPBoxed(MTPgeochats_setTyping(_peer, _typing)) { - } -}; - -class MTPgeochats_sendMessage { // RPC method 'geochats.sendMessage' -public: - MTPInputGeoChat vpeer; - MTPstring vmessage; - MTPlong vrandom_id; - - MTPgeochats_sendMessage() { - } - MTPgeochats_sendMessage(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_sendMessage) { - read(from, end, cons); - } - MTPgeochats_sendMessage(const MTPInputGeoChat &_peer, const MTPstring &_message, const MTPlong &_random_id) : vpeer(_peer), vmessage(_message), vrandom_id(_random_id) { - } - - uint32 innerLength() const { - return vpeer.innerLength() + vmessage.innerLength() + vrandom_id.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_sendMessage; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_sendMessage) { - vpeer.read(from, end); - vmessage.read(from, end); - vrandom_id.read(from, end); - } - void write(mtpBuffer &to) const { - vpeer.write(to); - vmessage.write(to); - vrandom_id.write(to); - } - - typedef MTPgeochats_StatedMessage ResponseType; -}; -class MTPgeochats_SendMessage : public MTPBoxed { -public: - MTPgeochats_SendMessage() { - } - MTPgeochats_SendMessage(const MTPgeochats_sendMessage &v) : MTPBoxed(v) { - } - MTPgeochats_SendMessage(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_SendMessage(const MTPInputGeoChat &_peer, const MTPstring &_message, const MTPlong &_random_id) : MTPBoxed(MTPgeochats_sendMessage(_peer, _message, _random_id)) { - } -}; - -class MTPgeochats_sendMedia { // RPC method 'geochats.sendMedia' -public: - MTPInputGeoChat vpeer; - MTPInputMedia vmedia; - MTPlong vrandom_id; - - MTPgeochats_sendMedia() { - } - MTPgeochats_sendMedia(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_sendMedia) { - read(from, end, cons); - } - MTPgeochats_sendMedia(const MTPInputGeoChat &_peer, const MTPInputMedia &_media, const MTPlong &_random_id) : vpeer(_peer), vmedia(_media), vrandom_id(_random_id) { - } - - uint32 innerLength() const { - return vpeer.innerLength() + vmedia.innerLength() + vrandom_id.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_sendMedia; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_sendMedia) { - vpeer.read(from, end); - vmedia.read(from, end); - vrandom_id.read(from, end); - } - void write(mtpBuffer &to) const { - vpeer.write(to); - vmedia.write(to); - vrandom_id.write(to); - } - - typedef MTPgeochats_StatedMessage ResponseType; -}; -class MTPgeochats_SendMedia : public MTPBoxed { -public: - MTPgeochats_SendMedia() { - } - MTPgeochats_SendMedia(const MTPgeochats_sendMedia &v) : MTPBoxed(v) { - } - MTPgeochats_SendMedia(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_SendMedia(const MTPInputGeoChat &_peer, const MTPInputMedia &_media, const MTPlong &_random_id) : MTPBoxed(MTPgeochats_sendMedia(_peer, _media, _random_id)) { - } -}; - -class MTPgeochats_createGeoChat { // RPC method 'geochats.createGeoChat' -public: - MTPstring vtitle; - MTPInputGeoPoint vgeo_point; - MTPstring vaddress; - MTPstring vvenue; - - MTPgeochats_createGeoChat() { - } - MTPgeochats_createGeoChat(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_createGeoChat) { - read(from, end, cons); - } - MTPgeochats_createGeoChat(const MTPstring &_title, const MTPInputGeoPoint &_geo_point, const MTPstring &_address, const MTPstring &_venue) : vtitle(_title), vgeo_point(_geo_point), vaddress(_address), vvenue(_venue) { - } - - uint32 innerLength() const { - return vtitle.innerLength() + vgeo_point.innerLength() + vaddress.innerLength() + vvenue.innerLength(); - } - mtpTypeId type() const { - return mtpc_geochats_createGeoChat; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_geochats_createGeoChat) { - vtitle.read(from, end); - vgeo_point.read(from, end); - vaddress.read(from, end); - vvenue.read(from, end); - } - void write(mtpBuffer &to) const { - vtitle.write(to); - vgeo_point.write(to); - vaddress.write(to); - vvenue.write(to); - } - - typedef MTPgeochats_StatedMessage ResponseType; -}; -class MTPgeochats_CreateGeoChat : public MTPBoxed { -public: - MTPgeochats_CreateGeoChat() { - } - MTPgeochats_CreateGeoChat(const MTPgeochats_createGeoChat &v) : MTPBoxed(v) { - } - MTPgeochats_CreateGeoChat(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPgeochats_CreateGeoChat(const MTPstring &_title, const MTPInputGeoPoint &_geo_point, const MTPstring &_address, const MTPstring &_venue) : MTPBoxed(MTPgeochats_createGeoChat(_title, _geo_point, _address, _venue)) { - } -}; - class MTPmessages_getDhConfig { // RPC method 'messages.getDhConfig' public: MTPint vversion; @@ -18609,11 +17509,11 @@ inline uint32 MTPinputMedia::innerLength() const { } case mtpc_inputMediaUploadedVideo: { const MTPDinputMediaUploadedVideo &v(c_inputMediaUploadedVideo()); - return v.vfile.innerLength() + v.vduration.innerLength() + v.vw.innerLength() + v.vh.innerLength() + v.vcaption.innerLength(); + return v.vfile.innerLength() + v.vduration.innerLength() + v.vw.innerLength() + v.vh.innerLength() + v.vmime_type.innerLength() + v.vcaption.innerLength(); } case mtpc_inputMediaUploadedThumbVideo: { const MTPDinputMediaUploadedThumbVideo &v(c_inputMediaUploadedThumbVideo()); - return v.vfile.innerLength() + v.vthumb.innerLength() + v.vduration.innerLength() + v.vw.innerLength() + v.vh.innerLength() + v.vcaption.innerLength(); + return v.vfile.innerLength() + v.vthumb.innerLength() + v.vduration.innerLength() + v.vw.innerLength() + v.vh.innerLength() + v.vmime_type.innerLength() + v.vcaption.innerLength(); } case mtpc_inputMediaVideo: { const MTPDinputMediaVideo &v(c_inputMediaVideo()); @@ -18685,6 +17585,7 @@ inline void MTPinputMedia::read(const mtpPrime *&from, const mtpPrime *end, mtpT v.vduration.read(from, end); v.vw.read(from, end); v.vh.read(from, end); + v.vmime_type.read(from, end); v.vcaption.read(from, end); } break; case mtpc_inputMediaUploadedThumbVideo: _type = cons; { @@ -18695,6 +17596,7 @@ inline void MTPinputMedia::read(const mtpPrime *&from, const mtpPrime *end, mtpT v.vduration.read(from, end); v.vw.read(from, end); v.vh.read(from, end); + v.vmime_type.read(from, end); v.vcaption.read(from, end); } break; case mtpc_inputMediaVideo: _type = cons; { @@ -18775,6 +17677,7 @@ inline void MTPinputMedia::write(mtpBuffer &to) const { v.vduration.write(to); v.vw.write(to); v.vh.write(to); + v.vmime_type.write(to); v.vcaption.write(to); } break; case mtpc_inputMediaUploadedThumbVideo: { @@ -18784,6 +17687,7 @@ inline void MTPinputMedia::write(mtpBuffer &to) const { v.vduration.write(to); v.vw.write(to); v.vh.write(to); + v.vmime_type.write(to); v.vcaption.write(to); } break; case mtpc_inputMediaVideo: { @@ -18888,11 +17792,11 @@ inline MTPinputMedia MTP_inputMediaGeoPoint(const MTPInputGeoPoint &_geo_point) inline MTPinputMedia MTP_inputMediaContact(const MTPstring &_phone_number, const MTPstring &_first_name, const MTPstring &_last_name) { return MTPinputMedia(new MTPDinputMediaContact(_phone_number, _first_name, _last_name)); } -inline MTPinputMedia MTP_inputMediaUploadedVideo(const MTPInputFile &_file, MTPint _duration, MTPint _w, MTPint _h, const MTPstring &_caption) { - return MTPinputMedia(new MTPDinputMediaUploadedVideo(_file, _duration, _w, _h, _caption)); +inline MTPinputMedia MTP_inputMediaUploadedVideo(const MTPInputFile &_file, MTPint _duration, MTPint _w, MTPint _h, const MTPstring &_mime_type, const MTPstring &_caption) { + return MTPinputMedia(new MTPDinputMediaUploadedVideo(_file, _duration, _w, _h, _mime_type, _caption)); } -inline MTPinputMedia MTP_inputMediaUploadedThumbVideo(const MTPInputFile &_file, const MTPInputFile &_thumb, MTPint _duration, MTPint _w, MTPint _h, const MTPstring &_caption) { - return MTPinputMedia(new MTPDinputMediaUploadedThumbVideo(_file, _thumb, _duration, _w, _h, _caption)); +inline MTPinputMedia MTP_inputMediaUploadedThumbVideo(const MTPInputFile &_file, const MTPInputFile &_thumb, MTPint _duration, MTPint _w, MTPint _h, const MTPstring &_mime_type, const MTPstring &_caption) { + return MTPinputMedia(new MTPDinputMediaUploadedThumbVideo(_file, _thumb, _duration, _w, _h, _mime_type, _caption)); } inline MTPinputMedia MTP_inputMediaVideo(const MTPInputVideo &_id, const MTPstring &_caption) { return MTPinputMedia(new MTPDinputMediaVideo(_id, _caption)); @@ -19798,10 +18702,6 @@ inline uint32 MTPchat::innerLength() const { const MTPDchatForbidden &v(c_chatForbidden()); return v.vid.innerLength() + v.vtitle.innerLength() + v.vdate.innerLength(); } - case mtpc_geoChat: { - const MTPDgeoChat &v(c_geoChat()); - return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vtitle.innerLength() + v.vaddress.innerLength() + v.vvenue.innerLength() + v.vgeo.innerLength() + v.vphoto.innerLength() + v.vparticipants_count.innerLength() + v.vdate.innerLength() + v.vchecked_in.innerLength() + v.vversion.innerLength(); - } } return 0; } @@ -19835,21 +18735,6 @@ inline void MTPchat::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId v.vtitle.read(from, end); v.vdate.read(from, end); } break; - case mtpc_geoChat: _type = cons; { - if (!data) setData(new MTPDgeoChat()); - MTPDgeoChat &v(_geoChat()); - v.vid.read(from, end); - v.vaccess_hash.read(from, end); - v.vtitle.read(from, end); - v.vaddress.read(from, end); - v.vvenue.read(from, end); - v.vgeo.read(from, end); - v.vphoto.read(from, end); - v.vparticipants_count.read(from, end); - v.vdate.read(from, end); - v.vchecked_in.read(from, end); - v.vversion.read(from, end); - } break; default: throw mtpErrorUnexpected(cons, "MTPchat"); } } @@ -19875,20 +18760,6 @@ inline void MTPchat::write(mtpBuffer &to) const { v.vtitle.write(to); v.vdate.write(to); } break; - case mtpc_geoChat: { - const MTPDgeoChat &v(c_geoChat()); - v.vid.write(to); - v.vaccess_hash.write(to); - v.vtitle.write(to); - v.vaddress.write(to); - v.vvenue.write(to); - v.vgeo.write(to); - v.vphoto.write(to); - v.vparticipants_count.write(to); - v.vdate.write(to); - v.vchecked_in.write(to); - v.vversion.write(to); - } break; } } inline MTPchat::MTPchat(mtpTypeId type) : mtpDataOwner(0), _type(type) { @@ -19896,7 +18767,6 @@ inline MTPchat::MTPchat(mtpTypeId type) : mtpDataOwner(0), _type(type) { case mtpc_chatEmpty: setData(new MTPDchatEmpty()); break; case mtpc_chat: setData(new MTPDchat()); break; case mtpc_chatForbidden: setData(new MTPDchatForbidden()); break; - case mtpc_geoChat: setData(new MTPDgeoChat()); break; default: throw mtpErrorBadTypeId(type, "MTPchat"); } } @@ -19906,8 +18776,6 @@ inline MTPchat::MTPchat(MTPDchat *_data) : mtpDataOwner(_data), _type(mtpc_chat) } inline MTPchat::MTPchat(MTPDchatForbidden *_data) : mtpDataOwner(_data), _type(mtpc_chatForbidden) { } -inline MTPchat::MTPchat(MTPDgeoChat *_data) : mtpDataOwner(_data), _type(mtpc_geoChat) { -} inline MTPchat MTP_chatEmpty(MTPint _id) { return MTPchat(new MTPDchatEmpty(_id)); } @@ -19917,9 +18785,6 @@ inline MTPchat MTP_chat(MTPint _id, const MTPstring &_title, const MTPChatPhoto inline MTPchat MTP_chatForbidden(MTPint _id, const MTPstring &_title, MTPint _date) { return MTPchat(new MTPDchatForbidden(_id, _title, _date)); } -inline MTPchat MTP_geoChat(MTPint _id, const MTPlong &_access_hash, const MTPstring &_title, const MTPstring &_address, const MTPstring &_venue, const MTPGeoPoint &_geo, const MTPChatPhoto &_photo, MTPint _participants_count, MTPint _date, MTPBool _checked_in, MTPint _version) { - return MTPchat(new MTPDgeoChat(_id, _access_hash, _title, _address, _venue, _geo, _photo, _participants_count, _date, _checked_in, _version)); -} inline MTPchatFull::MTPchatFull() : mtpDataOwner(new MTPDchatFull()) { } @@ -20117,7 +18982,7 @@ inline uint32 MTPmessage::innerLength() const { } case mtpc_message: { const MTPDmessage &v(c_message()); - return v.vflags.innerLength() + v.vid.innerLength() + v.vfrom_id.innerLength() + v.vto_id.innerLength() + (v.has_fwd_from_id() ? v.vfwd_from_id.innerLength() : 0) + (v.has_fwd_date() ? v.vfwd_date.innerLength() : 0) + (v.has_reply_to_msg_id() ? v.vreply_to_msg_id.innerLength() : 0) + v.vdate.innerLength() + v.vmessage.innerLength() + v.vmedia.innerLength() + (v.has_reply_markup() ? v.vreply_markup.innerLength() : 0) + (v.has_entities() ? v.ventities.innerLength() : 0); + return v.vflags.innerLength() + v.vid.innerLength() + v.vfrom_id.innerLength() + v.vto_id.innerLength() + (v.has_fwd_from_id() ? v.vfwd_from_id.innerLength() : 0) + (v.has_fwd_date() ? v.vfwd_date.innerLength() : 0) + (v.has_reply_to_msg_id() ? v.vreply_to_msg_id.innerLength() : 0) + v.vdate.innerLength() + v.vmessage.innerLength() + (v.has_media() ? v.vmedia.innerLength() : 0) + (v.has_reply_markup() ? v.vreply_markup.innerLength() : 0) + (v.has_entities() ? v.ventities.innerLength() : 0); } case mtpc_messageService: { const MTPDmessageService &v(c_messageService()); @@ -20150,7 +19015,7 @@ inline void MTPmessage::read(const mtpPrime *&from, const mtpPrime *end, mtpType if (v.has_reply_to_msg_id()) { v.vreply_to_msg_id.read(from, end); } else { v.vreply_to_msg_id = MTPint(); } v.vdate.read(from, end); v.vmessage.read(from, end); - v.vmedia.read(from, end); + if (v.has_media()) { v.vmedia.read(from, end); } else { v.vmedia = MTPMessageMedia(); } if (v.has_reply_markup()) { v.vreply_markup.read(from, end); } else { v.vreply_markup = MTPReplyMarkup(); } if (v.has_entities()) { v.ventities.read(from, end); } else { v.ventities = MTPVector(); } } break; @@ -20184,7 +19049,7 @@ inline void MTPmessage::write(mtpBuffer &to) const { if (v.has_reply_to_msg_id()) v.vreply_to_msg_id.write(to); v.vdate.write(to); v.vmessage.write(to); - v.vmedia.write(to); + if (v.has_media()) v.vmedia.write(to); if (v.has_reply_markup()) v.vreply_markup.write(to); if (v.has_entities()) v.ventities.write(to); } break; @@ -20450,10 +19315,6 @@ inline uint32 MTPmessageAction::innerLength() const { const MTPDmessageActionChatDeleteUser &v(c_messageActionChatDeleteUser()); return v.vuser_id.innerLength(); } - case mtpc_messageActionGeoChatCreate: { - const MTPDmessageActionGeoChatCreate &v(c_messageActionGeoChatCreate()); - return v.vtitle.innerLength() + v.vaddress.innerLength(); - } case mtpc_messageActionChatJoinedByLink: { const MTPDmessageActionChatJoinedByLink &v(c_messageActionChatJoinedByLink()); return v.vinviter_id.innerLength(); @@ -20496,13 +19357,6 @@ inline void MTPmessageAction::read(const mtpPrime *&from, const mtpPrime *end, m MTPDmessageActionChatDeleteUser &v(_messageActionChatDeleteUser()); v.vuser_id.read(from, end); } break; - case mtpc_messageActionGeoChatCreate: _type = cons; { - if (!data) setData(new MTPDmessageActionGeoChatCreate()); - MTPDmessageActionGeoChatCreate &v(_messageActionGeoChatCreate()); - v.vtitle.read(from, end); - v.vaddress.read(from, end); - } break; - case mtpc_messageActionGeoChatCheckin: _type = cons; break; case mtpc_messageActionChatJoinedByLink: _type = cons; { if (!data) setData(new MTPDmessageActionChatJoinedByLink()); MTPDmessageActionChatJoinedByLink &v(_messageActionChatJoinedByLink()); @@ -20534,11 +19388,6 @@ inline void MTPmessageAction::write(mtpBuffer &to) const { const MTPDmessageActionChatDeleteUser &v(c_messageActionChatDeleteUser()); v.vuser_id.write(to); } break; - case mtpc_messageActionGeoChatCreate: { - const MTPDmessageActionGeoChatCreate &v(c_messageActionGeoChatCreate()); - v.vtitle.write(to); - v.vaddress.write(to); - } break; case mtpc_messageActionChatJoinedByLink: { const MTPDmessageActionChatJoinedByLink &v(c_messageActionChatJoinedByLink()); v.vinviter_id.write(to); @@ -20554,8 +19403,6 @@ inline MTPmessageAction::MTPmessageAction(mtpTypeId type) : mtpDataOwner(0), _ty case mtpc_messageActionChatDeletePhoto: break; case mtpc_messageActionChatAddUser: setData(new MTPDmessageActionChatAddUser()); break; case mtpc_messageActionChatDeleteUser: setData(new MTPDmessageActionChatDeleteUser()); break; - case mtpc_messageActionGeoChatCreate: setData(new MTPDmessageActionGeoChatCreate()); break; - case mtpc_messageActionGeoChatCheckin: break; case mtpc_messageActionChatJoinedByLink: setData(new MTPDmessageActionChatJoinedByLink()); break; default: throw mtpErrorBadTypeId(type, "MTPmessageAction"); } @@ -20570,8 +19417,6 @@ inline MTPmessageAction::MTPmessageAction(MTPDmessageActionChatAddUser *_data) : } inline MTPmessageAction::MTPmessageAction(MTPDmessageActionChatDeleteUser *_data) : mtpDataOwner(_data), _type(mtpc_messageActionChatDeleteUser) { } -inline MTPmessageAction::MTPmessageAction(MTPDmessageActionGeoChatCreate *_data) : mtpDataOwner(_data), _type(mtpc_messageActionGeoChatCreate) { -} inline MTPmessageAction::MTPmessageAction(MTPDmessageActionChatJoinedByLink *_data) : mtpDataOwner(_data), _type(mtpc_messageActionChatJoinedByLink) { } inline MTPmessageAction MTP_messageActionEmpty() { @@ -20595,12 +19440,6 @@ inline MTPmessageAction MTP_messageActionChatAddUser(MTPint _user_id) { inline MTPmessageAction MTP_messageActionChatDeleteUser(MTPint _user_id) { return MTPmessageAction(new MTPDmessageActionChatDeleteUser(_user_id)); } -inline MTPmessageAction MTP_messageActionGeoChatCreate(const MTPstring &_title, const MTPstring &_address) { - return MTPmessageAction(new MTPDmessageActionGeoChatCreate(_title, _address)); -} -inline MTPmessageAction MTP_messageActionGeoChatCheckin() { - return MTPmessageAction(mtpc_messageActionGeoChatCheckin); -} inline MTPmessageAction MTP_messageActionChatJoinedByLink(MTPint _inviter_id) { return MTPmessageAction(new MTPDmessageActionChatJoinedByLink(_inviter_id)); } @@ -21103,10 +19942,6 @@ inline uint32 MTPinputNotifyPeer::innerLength() const { const MTPDinputNotifyPeer &v(c_inputNotifyPeer()); return v.vpeer.innerLength(); } - case mtpc_inputNotifyGeoChatPeer: { - const MTPDinputNotifyGeoChatPeer &v(c_inputNotifyGeoChatPeer()); - return v.vpeer.innerLength(); - } } return 0; } @@ -21125,11 +19960,6 @@ inline void MTPinputNotifyPeer::read(const mtpPrime *&from, const mtpPrime *end, case mtpc_inputNotifyUsers: _type = cons; break; case mtpc_inputNotifyChats: _type = cons; break; case mtpc_inputNotifyAll: _type = cons; break; - case mtpc_inputNotifyGeoChatPeer: _type = cons; { - if (!data) setData(new MTPDinputNotifyGeoChatPeer()); - MTPDinputNotifyGeoChatPeer &v(_inputNotifyGeoChatPeer()); - v.vpeer.read(from, end); - } break; default: throw mtpErrorUnexpected(cons, "MTPinputNotifyPeer"); } } @@ -21139,10 +19969,6 @@ inline void MTPinputNotifyPeer::write(mtpBuffer &to) const { const MTPDinputNotifyPeer &v(c_inputNotifyPeer()); v.vpeer.write(to); } break; - case mtpc_inputNotifyGeoChatPeer: { - const MTPDinputNotifyGeoChatPeer &v(c_inputNotifyGeoChatPeer()); - v.vpeer.write(to); - } break; } } inline MTPinputNotifyPeer::MTPinputNotifyPeer(mtpTypeId type) : mtpDataOwner(0), _type(type) { @@ -21151,14 +19977,11 @@ inline MTPinputNotifyPeer::MTPinputNotifyPeer(mtpTypeId type) : mtpDataOwner(0), case mtpc_inputNotifyUsers: break; case mtpc_inputNotifyChats: break; case mtpc_inputNotifyAll: break; - case mtpc_inputNotifyGeoChatPeer: setData(new MTPDinputNotifyGeoChatPeer()); break; default: throw mtpErrorBadTypeId(type, "MTPinputNotifyPeer"); } } inline MTPinputNotifyPeer::MTPinputNotifyPeer(MTPDinputNotifyPeer *_data) : mtpDataOwner(_data), _type(mtpc_inputNotifyPeer) { } -inline MTPinputNotifyPeer::MTPinputNotifyPeer(MTPDinputNotifyGeoChatPeer *_data) : mtpDataOwner(_data), _type(mtpc_inputNotifyGeoChatPeer) { -} inline MTPinputNotifyPeer MTP_inputNotifyPeer(const MTPInputPeer &_peer) { return MTPinputNotifyPeer(new MTPDinputNotifyPeer(_peer)); } @@ -21171,9 +19994,6 @@ inline MTPinputNotifyPeer MTP_inputNotifyChats() { inline MTPinputNotifyPeer MTP_inputNotifyAll() { return MTPinputNotifyPeer(mtpc_inputNotifyAll); } -inline MTPinputNotifyPeer MTP_inputNotifyGeoChatPeer(const MTPInputGeoChat &_peer) { - return MTPinputNotifyPeer(new MTPDinputNotifyGeoChatPeer(_peer)); -} inline uint32 MTPinputPeerNotifyEvents::innerLength() const { return 0; @@ -21584,35 +20404,6 @@ inline MTPcontactStatus MTP_contactStatus(MTPint _user_id, const MTPUserStatus & return MTPcontactStatus(new MTPDcontactStatus(_user_id, _status)); } -inline MTPchatLocated::MTPchatLocated() : mtpDataOwner(new MTPDchatLocated()) { -} - -inline uint32 MTPchatLocated::innerLength() const { - const MTPDchatLocated &v(c_chatLocated()); - return v.vchat_id.innerLength() + v.vdistance.innerLength(); -} -inline mtpTypeId MTPchatLocated::type() const { - return mtpc_chatLocated; -} -inline void MTPchatLocated::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != mtpc_chatLocated) throw mtpErrorUnexpected(cons, "MTPchatLocated"); - - if (!data) setData(new MTPDchatLocated()); - MTPDchatLocated &v(_chatLocated()); - v.vchat_id.read(from, end); - v.vdistance.read(from, end); -} -inline void MTPchatLocated::write(mtpBuffer &to) const { - const MTPDchatLocated &v(c_chatLocated()); - v.vchat_id.write(to); - v.vdistance.write(to); -} -inline MTPchatLocated::MTPchatLocated(MTPDchatLocated *_data) : mtpDataOwner(_data) { -} -inline MTPchatLocated MTP_chatLocated(MTPint _chat_id, MTPint _distance) { - return MTPchatLocated(new MTPDchatLocated(_chat_id, _distance)); -} - inline MTPcontacts_link::MTPcontacts_link() : mtpDataOwner(new MTPDcontacts_link()) { } @@ -21974,91 +20765,6 @@ inline MTPmessages_messages MTP_messages_messagesSlice(MTPint _count, const MTPV return MTPmessages_messages(new MTPDmessages_messagesSlice(_count, _messages, _chats, _users)); } -inline uint32 MTPmessages_sentMessage::innerLength() const { - switch (_type) { - case mtpc_messages_sentMessage: { - const MTPDmessages_sentMessage &v(c_messages_sentMessage()); - return v.vid.innerLength() + v.vdate.innerLength() + v.vmedia.innerLength() + v.ventities.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength(); - } - case mtpc_messages_sentMessageLink: { - const MTPDmessages_sentMessageLink &v(c_messages_sentMessageLink()); - return v.vid.innerLength() + v.vdate.innerLength() + v.vmedia.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength() + v.vlinks.innerLength() + v.vseq.innerLength(); - } - } - return 0; -} -inline mtpTypeId MTPmessages_sentMessage::type() const { - if (!_type) throw mtpErrorUninitialized(); - return _type; -} -inline void MTPmessages_sentMessage::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != _type) setData(0); - switch (cons) { - case mtpc_messages_sentMessage: _type = cons; { - if (!data) setData(new MTPDmessages_sentMessage()); - MTPDmessages_sentMessage &v(_messages_sentMessage()); - v.vid.read(from, end); - v.vdate.read(from, end); - v.vmedia.read(from, end); - v.ventities.read(from, end); - v.vpts.read(from, end); - v.vpts_count.read(from, end); - } break; - case mtpc_messages_sentMessageLink: _type = cons; { - if (!data) setData(new MTPDmessages_sentMessageLink()); - MTPDmessages_sentMessageLink &v(_messages_sentMessageLink()); - v.vid.read(from, end); - v.vdate.read(from, end); - v.vmedia.read(from, end); - v.vpts.read(from, end); - v.vpts_count.read(from, end); - v.vlinks.read(from, end); - v.vseq.read(from, end); - } break; - default: throw mtpErrorUnexpected(cons, "MTPmessages_sentMessage"); - } -} -inline void MTPmessages_sentMessage::write(mtpBuffer &to) const { - switch (_type) { - case mtpc_messages_sentMessage: { - const MTPDmessages_sentMessage &v(c_messages_sentMessage()); - v.vid.write(to); - v.vdate.write(to); - v.vmedia.write(to); - v.ventities.write(to); - v.vpts.write(to); - v.vpts_count.write(to); - } break; - case mtpc_messages_sentMessageLink: { - const MTPDmessages_sentMessageLink &v(c_messages_sentMessageLink()); - v.vid.write(to); - v.vdate.write(to); - v.vmedia.write(to); - v.vpts.write(to); - v.vpts_count.write(to); - v.vlinks.write(to); - v.vseq.write(to); - } break; - } -} -inline MTPmessages_sentMessage::MTPmessages_sentMessage(mtpTypeId type) : mtpDataOwner(0), _type(type) { - switch (type) { - case mtpc_messages_sentMessage: setData(new MTPDmessages_sentMessage()); break; - case mtpc_messages_sentMessageLink: setData(new MTPDmessages_sentMessageLink()); break; - default: throw mtpErrorBadTypeId(type, "MTPmessages_sentMessage"); - } -} -inline MTPmessages_sentMessage::MTPmessages_sentMessage(MTPDmessages_sentMessage *_data) : mtpDataOwner(_data), _type(mtpc_messages_sentMessage) { -} -inline MTPmessages_sentMessage::MTPmessages_sentMessage(MTPDmessages_sentMessageLink *_data) : mtpDataOwner(_data), _type(mtpc_messages_sentMessageLink) { -} -inline MTPmessages_sentMessage MTP_messages_sentMessage(MTPint _id, MTPint _date, const MTPMessageMedia &_media, const MTPVector &_entities, MTPint _pts, MTPint _pts_count) { - return MTPmessages_sentMessage(new MTPDmessages_sentMessage(_id, _date, _media, _entities, _pts, _pts_count)); -} -inline MTPmessages_sentMessage MTP_messages_sentMessageLink(MTPint _id, MTPint _date, const MTPMessageMedia &_media, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq) { - return MTPmessages_sentMessage(new MTPDmessages_sentMessageLink(_id, _date, _media, _pts, _pts_count, _links, _seq)); -} - inline MTPmessages_chats::MTPmessages_chats() : mtpDataOwner(new MTPDmessages_chats()) { } @@ -22265,10 +20971,6 @@ inline uint32 MTPupdate::innerLength() const { const MTPDupdateNewAuthorization &v(c_updateNewAuthorization()); return v.vauth_key_id.innerLength() + v.vdate.innerLength() + v.vdevice.innerLength() + v.vlocation.innerLength(); } - case mtpc_updateNewGeoChatMessage: { - const MTPDupdateNewGeoChatMessage &v(c_updateNewGeoChatMessage()); - return v.vmessage.innerLength(); - } case mtpc_updateNewEncryptedMessage: { const MTPDupdateNewEncryptedMessage &v(c_updateNewEncryptedMessage()); return v.vmessage.innerLength() + v.vqts.innerLength(); @@ -22424,11 +21126,6 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI v.vdevice.read(from, end); v.vlocation.read(from, end); } break; - case mtpc_updateNewGeoChatMessage: _type = cons; { - if (!data) setData(new MTPDupdateNewGeoChatMessage()); - MTPDupdateNewGeoChatMessage &v(_updateNewGeoChatMessage()); - v.vmessage.read(from, end); - } break; case mtpc_updateNewEncryptedMessage: _type = cons; { if (!data) setData(new MTPDupdateNewEncryptedMessage()); MTPDupdateNewEncryptedMessage &v(_updateNewEncryptedMessage()); @@ -22607,10 +21304,6 @@ inline void MTPupdate::write(mtpBuffer &to) const { v.vdevice.write(to); v.vlocation.write(to); } break; - case mtpc_updateNewGeoChatMessage: { - const MTPDupdateNewGeoChatMessage &v(c_updateNewGeoChatMessage()); - v.vmessage.write(to); - } break; case mtpc_updateNewEncryptedMessage: { const MTPDupdateNewEncryptedMessage &v(c_updateNewEncryptedMessage()); v.vmessage.write(to); @@ -22715,7 +21408,6 @@ inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) { case mtpc_updateContactRegistered: setData(new MTPDupdateContactRegistered()); break; case mtpc_updateContactLink: setData(new MTPDupdateContactLink()); break; case mtpc_updateNewAuthorization: setData(new MTPDupdateNewAuthorization()); break; - case mtpc_updateNewGeoChatMessage: setData(new MTPDupdateNewGeoChatMessage()); break; case mtpc_updateNewEncryptedMessage: setData(new MTPDupdateNewEncryptedMessage()); break; case mtpc_updateEncryptedChatTyping: setData(new MTPDupdateEncryptedChatTyping()); break; case mtpc_updateEncryption: setData(new MTPDupdateEncryption()); break; @@ -22759,8 +21451,6 @@ inline MTPupdate::MTPupdate(MTPDupdateContactLink *_data) : mtpDataOwner(_data), } inline MTPupdate::MTPupdate(MTPDupdateNewAuthorization *_data) : mtpDataOwner(_data), _type(mtpc_updateNewAuthorization) { } -inline MTPupdate::MTPupdate(MTPDupdateNewGeoChatMessage *_data) : mtpDataOwner(_data), _type(mtpc_updateNewGeoChatMessage) { -} inline MTPupdate::MTPupdate(MTPDupdateNewEncryptedMessage *_data) : mtpDataOwner(_data), _type(mtpc_updateNewEncryptedMessage) { } inline MTPupdate::MTPupdate(MTPDupdateEncryptedChatTyping *_data) : mtpDataOwner(_data), _type(mtpc_updateEncryptedChatTyping) { @@ -22829,9 +21519,6 @@ inline MTPupdate MTP_updateContactLink(MTPint _user_id, const MTPContactLink &_m inline MTPupdate MTP_updateNewAuthorization(const MTPlong &_auth_key_id, MTPint _date, const MTPstring &_device, const MTPstring &_location) { return MTPupdate(new MTPDupdateNewAuthorization(_auth_key_id, _date, _device, _location)); } -inline MTPupdate MTP_updateNewGeoChatMessage(const MTPGeoChatMessage &_message) { - return MTPupdate(new MTPDupdateNewGeoChatMessage(_message)); -} inline MTPupdate MTP_updateNewEncryptedMessage(const MTPEncryptedMessage &_message, MTPint _qts) { return MTPupdate(new MTPDupdateNewEncryptedMessage(_message, _qts)); } @@ -23042,6 +21729,10 @@ inline uint32 MTPupdates::innerLength() const { const MTPDupdates &v(c_updates()); return v.vupdates.innerLength() + v.vusers.innerLength() + v.vchats.innerLength() + v.vdate.innerLength() + v.vseq.innerLength(); } + case mtpc_updateShortSentMessage: { + const MTPDupdateShortSentMessage &v(c_updateShortSentMessage()); + return v.vflags.innerLength() + v.vid.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength() + v.vdate.innerLength() + (v.has_media() ? v.vmedia.innerLength() : 0) + (v.has_entities() ? v.ventities.innerLength() : 0); + } } return 0; } @@ -23109,6 +21800,17 @@ inline void MTPupdates::read(const mtpPrime *&from, const mtpPrime *end, mtpType v.vdate.read(from, end); v.vseq.read(from, end); } break; + case mtpc_updateShortSentMessage: _type = cons; { + if (!data) setData(new MTPDupdateShortSentMessage()); + MTPDupdateShortSentMessage &v(_updateShortSentMessage()); + v.vflags.read(from, end); + v.vid.read(from, end); + v.vpts.read(from, end); + v.vpts_count.read(from, end); + v.vdate.read(from, end); + if (v.has_media()) { v.vmedia.read(from, end); } else { v.vmedia = MTPMessageMedia(); } + if (v.has_entities()) { v.ventities.read(from, end); } else { v.ventities = MTPVector(); } + } break; default: throw mtpErrorUnexpected(cons, "MTPupdates"); } } @@ -23165,6 +21867,16 @@ inline void MTPupdates::write(mtpBuffer &to) const { v.vdate.write(to); v.vseq.write(to); } break; + case mtpc_updateShortSentMessage: { + const MTPDupdateShortSentMessage &v(c_updateShortSentMessage()); + v.vflags.write(to); + v.vid.write(to); + v.vpts.write(to); + v.vpts_count.write(to); + v.vdate.write(to); + if (v.has_media()) v.vmedia.write(to); + if (v.has_entities()) v.ventities.write(to); + } break; } } inline MTPupdates::MTPupdates(mtpTypeId type) : mtpDataOwner(0), _type(type) { @@ -23175,6 +21887,7 @@ inline MTPupdates::MTPupdates(mtpTypeId type) : mtpDataOwner(0), _type(type) { case mtpc_updateShort: setData(new MTPDupdateShort()); break; case mtpc_updatesCombined: setData(new MTPDupdatesCombined()); break; case mtpc_updates: setData(new MTPDupdates()); break; + case mtpc_updateShortSentMessage: setData(new MTPDupdateShortSentMessage()); break; default: throw mtpErrorBadTypeId(type, "MTPupdates"); } } @@ -23188,6 +21901,8 @@ inline MTPupdates::MTPupdates(MTPDupdatesCombined *_data) : mtpDataOwner(_data), } inline MTPupdates::MTPupdates(MTPDupdates *_data) : mtpDataOwner(_data), _type(mtpc_updates) { } +inline MTPupdates::MTPupdates(MTPDupdateShortSentMessage *_data) : mtpDataOwner(_data), _type(mtpc_updateShortSentMessage) { +} inline MTPupdates MTP_updatesTooLong() { return MTPupdates(mtpc_updatesTooLong); } @@ -23206,6 +21921,9 @@ inline MTPupdates MTP_updatesCombined(const MTPVector &_updates, cons inline MTPupdates MTP_updates(const MTPVector &_updates, const MTPVector &_users, const MTPVector &_chats, MTPint _date, MTPint _seq) { return MTPupdates(new MTPDupdates(_updates, _users, _chats, _date, _seq)); } +inline MTPupdates MTP_updateShortSentMessage(MTPint _flags, MTPint _id, MTPint _pts, MTPint _pts_count, MTPint _date, const MTPMessageMedia &_media, const MTPVector &_entities) { + return MTPupdates(new MTPDupdateShortSentMessage(_flags, _id, _pts, _pts_count, _date, _media, _entities)); +} inline uint32 MTPphotos_photos::innerLength() const { switch (_type) { @@ -23543,276 +22261,6 @@ inline MTPhelp_inviteText MTP_help_inviteText(const MTPstring &_message) { return MTPhelp_inviteText(new MTPDhelp_inviteText(_message)); } -inline MTPinputGeoChat::MTPinputGeoChat() : mtpDataOwner(new MTPDinputGeoChat()) { -} - -inline uint32 MTPinputGeoChat::innerLength() const { - const MTPDinputGeoChat &v(c_inputGeoChat()); - return v.vchat_id.innerLength() + v.vaccess_hash.innerLength(); -} -inline mtpTypeId MTPinputGeoChat::type() const { - return mtpc_inputGeoChat; -} -inline void MTPinputGeoChat::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != mtpc_inputGeoChat) throw mtpErrorUnexpected(cons, "MTPinputGeoChat"); - - if (!data) setData(new MTPDinputGeoChat()); - MTPDinputGeoChat &v(_inputGeoChat()); - v.vchat_id.read(from, end); - v.vaccess_hash.read(from, end); -} -inline void MTPinputGeoChat::write(mtpBuffer &to) const { - const MTPDinputGeoChat &v(c_inputGeoChat()); - v.vchat_id.write(to); - v.vaccess_hash.write(to); -} -inline MTPinputGeoChat::MTPinputGeoChat(MTPDinputGeoChat *_data) : mtpDataOwner(_data) { -} -inline MTPinputGeoChat MTP_inputGeoChat(MTPint _chat_id, const MTPlong &_access_hash) { - return MTPinputGeoChat(new MTPDinputGeoChat(_chat_id, _access_hash)); -} - -inline uint32 MTPgeoChatMessage::innerLength() const { - switch (_type) { - case mtpc_geoChatMessageEmpty: { - const MTPDgeoChatMessageEmpty &v(c_geoChatMessageEmpty()); - return v.vchat_id.innerLength() + v.vid.innerLength(); - } - case mtpc_geoChatMessage: { - const MTPDgeoChatMessage &v(c_geoChatMessage()); - return v.vchat_id.innerLength() + v.vid.innerLength() + v.vfrom_id.innerLength() + v.vdate.innerLength() + v.vmessage.innerLength() + v.vmedia.innerLength(); - } - case mtpc_geoChatMessageService: { - const MTPDgeoChatMessageService &v(c_geoChatMessageService()); - return v.vchat_id.innerLength() + v.vid.innerLength() + v.vfrom_id.innerLength() + v.vdate.innerLength() + v.vaction.innerLength(); - } - } - return 0; -} -inline mtpTypeId MTPgeoChatMessage::type() const { - if (!_type) throw mtpErrorUninitialized(); - return _type; -} -inline void MTPgeoChatMessage::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != _type) setData(0); - switch (cons) { - case mtpc_geoChatMessageEmpty: _type = cons; { - if (!data) setData(new MTPDgeoChatMessageEmpty()); - MTPDgeoChatMessageEmpty &v(_geoChatMessageEmpty()); - v.vchat_id.read(from, end); - v.vid.read(from, end); - } break; - case mtpc_geoChatMessage: _type = cons; { - if (!data) setData(new MTPDgeoChatMessage()); - MTPDgeoChatMessage &v(_geoChatMessage()); - v.vchat_id.read(from, end); - v.vid.read(from, end); - v.vfrom_id.read(from, end); - v.vdate.read(from, end); - v.vmessage.read(from, end); - v.vmedia.read(from, end); - } break; - case mtpc_geoChatMessageService: _type = cons; { - if (!data) setData(new MTPDgeoChatMessageService()); - MTPDgeoChatMessageService &v(_geoChatMessageService()); - v.vchat_id.read(from, end); - v.vid.read(from, end); - v.vfrom_id.read(from, end); - v.vdate.read(from, end); - v.vaction.read(from, end); - } break; - default: throw mtpErrorUnexpected(cons, "MTPgeoChatMessage"); - } -} -inline void MTPgeoChatMessage::write(mtpBuffer &to) const { - switch (_type) { - case mtpc_geoChatMessageEmpty: { - const MTPDgeoChatMessageEmpty &v(c_geoChatMessageEmpty()); - v.vchat_id.write(to); - v.vid.write(to); - } break; - case mtpc_geoChatMessage: { - const MTPDgeoChatMessage &v(c_geoChatMessage()); - v.vchat_id.write(to); - v.vid.write(to); - v.vfrom_id.write(to); - v.vdate.write(to); - v.vmessage.write(to); - v.vmedia.write(to); - } break; - case mtpc_geoChatMessageService: { - const MTPDgeoChatMessageService &v(c_geoChatMessageService()); - v.vchat_id.write(to); - v.vid.write(to); - v.vfrom_id.write(to); - v.vdate.write(to); - v.vaction.write(to); - } break; - } -} -inline MTPgeoChatMessage::MTPgeoChatMessage(mtpTypeId type) : mtpDataOwner(0), _type(type) { - switch (type) { - case mtpc_geoChatMessageEmpty: setData(new MTPDgeoChatMessageEmpty()); break; - case mtpc_geoChatMessage: setData(new MTPDgeoChatMessage()); break; - case mtpc_geoChatMessageService: setData(new MTPDgeoChatMessageService()); break; - default: throw mtpErrorBadTypeId(type, "MTPgeoChatMessage"); - } -} -inline MTPgeoChatMessage::MTPgeoChatMessage(MTPDgeoChatMessageEmpty *_data) : mtpDataOwner(_data), _type(mtpc_geoChatMessageEmpty) { -} -inline MTPgeoChatMessage::MTPgeoChatMessage(MTPDgeoChatMessage *_data) : mtpDataOwner(_data), _type(mtpc_geoChatMessage) { -} -inline MTPgeoChatMessage::MTPgeoChatMessage(MTPDgeoChatMessageService *_data) : mtpDataOwner(_data), _type(mtpc_geoChatMessageService) { -} -inline MTPgeoChatMessage MTP_geoChatMessageEmpty(MTPint _chat_id, MTPint _id) { - return MTPgeoChatMessage(new MTPDgeoChatMessageEmpty(_chat_id, _id)); -} -inline MTPgeoChatMessage MTP_geoChatMessage(MTPint _chat_id, MTPint _id, MTPint _from_id, MTPint _date, const MTPstring &_message, const MTPMessageMedia &_media) { - return MTPgeoChatMessage(new MTPDgeoChatMessage(_chat_id, _id, _from_id, _date, _message, _media)); -} -inline MTPgeoChatMessage MTP_geoChatMessageService(MTPint _chat_id, MTPint _id, MTPint _from_id, MTPint _date, const MTPMessageAction &_action) { - return MTPgeoChatMessage(new MTPDgeoChatMessageService(_chat_id, _id, _from_id, _date, _action)); -} - -inline MTPgeochats_statedMessage::MTPgeochats_statedMessage() : mtpDataOwner(new MTPDgeochats_statedMessage()) { -} - -inline uint32 MTPgeochats_statedMessage::innerLength() const { - const MTPDgeochats_statedMessage &v(c_geochats_statedMessage()); - return v.vmessage.innerLength() + v.vchats.innerLength() + v.vusers.innerLength() + v.vseq.innerLength(); -} -inline mtpTypeId MTPgeochats_statedMessage::type() const { - return mtpc_geochats_statedMessage; -} -inline void MTPgeochats_statedMessage::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != mtpc_geochats_statedMessage) throw mtpErrorUnexpected(cons, "MTPgeochats_statedMessage"); - - if (!data) setData(new MTPDgeochats_statedMessage()); - MTPDgeochats_statedMessage &v(_geochats_statedMessage()); - v.vmessage.read(from, end); - v.vchats.read(from, end); - v.vusers.read(from, end); - v.vseq.read(from, end); -} -inline void MTPgeochats_statedMessage::write(mtpBuffer &to) const { - const MTPDgeochats_statedMessage &v(c_geochats_statedMessage()); - v.vmessage.write(to); - v.vchats.write(to); - v.vusers.write(to); - v.vseq.write(to); -} -inline MTPgeochats_statedMessage::MTPgeochats_statedMessage(MTPDgeochats_statedMessage *_data) : mtpDataOwner(_data) { -} -inline MTPgeochats_statedMessage MTP_geochats_statedMessage(const MTPGeoChatMessage &_message, const MTPVector &_chats, const MTPVector &_users, MTPint _seq) { - return MTPgeochats_statedMessage(new MTPDgeochats_statedMessage(_message, _chats, _users, _seq)); -} - -inline MTPgeochats_located::MTPgeochats_located() : mtpDataOwner(new MTPDgeochats_located()) { -} - -inline uint32 MTPgeochats_located::innerLength() const { - const MTPDgeochats_located &v(c_geochats_located()); - return v.vresults.innerLength() + v.vmessages.innerLength() + v.vchats.innerLength() + v.vusers.innerLength(); -} -inline mtpTypeId MTPgeochats_located::type() const { - return mtpc_geochats_located; -} -inline void MTPgeochats_located::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != mtpc_geochats_located) throw mtpErrorUnexpected(cons, "MTPgeochats_located"); - - if (!data) setData(new MTPDgeochats_located()); - MTPDgeochats_located &v(_geochats_located()); - v.vresults.read(from, end); - v.vmessages.read(from, end); - v.vchats.read(from, end); - v.vusers.read(from, end); -} -inline void MTPgeochats_located::write(mtpBuffer &to) const { - const MTPDgeochats_located &v(c_geochats_located()); - v.vresults.write(to); - v.vmessages.write(to); - v.vchats.write(to); - v.vusers.write(to); -} -inline MTPgeochats_located::MTPgeochats_located(MTPDgeochats_located *_data) : mtpDataOwner(_data) { -} -inline MTPgeochats_located MTP_geochats_located(const MTPVector &_results, const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users) { - return MTPgeochats_located(new MTPDgeochats_located(_results, _messages, _chats, _users)); -} - -inline uint32 MTPgeochats_messages::innerLength() const { - switch (_type) { - case mtpc_geochats_messages: { - const MTPDgeochats_messages &v(c_geochats_messages()); - return v.vmessages.innerLength() + v.vchats.innerLength() + v.vusers.innerLength(); - } - case mtpc_geochats_messagesSlice: { - const MTPDgeochats_messagesSlice &v(c_geochats_messagesSlice()); - return v.vcount.innerLength() + v.vmessages.innerLength() + v.vchats.innerLength() + v.vusers.innerLength(); - } - } - return 0; -} -inline mtpTypeId MTPgeochats_messages::type() const { - if (!_type) throw mtpErrorUninitialized(); - return _type; -} -inline void MTPgeochats_messages::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != _type) setData(0); - switch (cons) { - case mtpc_geochats_messages: _type = cons; { - if (!data) setData(new MTPDgeochats_messages()); - MTPDgeochats_messages &v(_geochats_messages()); - v.vmessages.read(from, end); - v.vchats.read(from, end); - v.vusers.read(from, end); - } break; - case mtpc_geochats_messagesSlice: _type = cons; { - if (!data) setData(new MTPDgeochats_messagesSlice()); - MTPDgeochats_messagesSlice &v(_geochats_messagesSlice()); - v.vcount.read(from, end); - v.vmessages.read(from, end); - v.vchats.read(from, end); - v.vusers.read(from, end); - } break; - default: throw mtpErrorUnexpected(cons, "MTPgeochats_messages"); - } -} -inline void MTPgeochats_messages::write(mtpBuffer &to) const { - switch (_type) { - case mtpc_geochats_messages: { - const MTPDgeochats_messages &v(c_geochats_messages()); - v.vmessages.write(to); - v.vchats.write(to); - v.vusers.write(to); - } break; - case mtpc_geochats_messagesSlice: { - const MTPDgeochats_messagesSlice &v(c_geochats_messagesSlice()); - v.vcount.write(to); - v.vmessages.write(to); - v.vchats.write(to); - v.vusers.write(to); - } break; - } -} -inline MTPgeochats_messages::MTPgeochats_messages(mtpTypeId type) : mtpDataOwner(0), _type(type) { - switch (type) { - case mtpc_geochats_messages: setData(new MTPDgeochats_messages()); break; - case mtpc_geochats_messagesSlice: setData(new MTPDgeochats_messagesSlice()); break; - default: throw mtpErrorBadTypeId(type, "MTPgeochats_messages"); - } -} -inline MTPgeochats_messages::MTPgeochats_messages(MTPDgeochats_messages *_data) : mtpDataOwner(_data), _type(mtpc_geochats_messages) { -} -inline MTPgeochats_messages::MTPgeochats_messages(MTPDgeochats_messagesSlice *_data) : mtpDataOwner(_data), _type(mtpc_geochats_messagesSlice) { -} -inline MTPgeochats_messages MTP_geochats_messages(const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users) { - return MTPgeochats_messages(new MTPDgeochats_messages(_messages, _chats, _users)); -} -inline MTPgeochats_messages MTP_geochats_messagesSlice(MTPint _count, const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users) { - return MTPgeochats_messages(new MTPDgeochats_messagesSlice(_count, _messages, _chats, _users)); -} - inline uint32 MTPencryptedChat::innerLength() const { switch (_type) { case mtpc_encryptedChatEmpty: { @@ -25547,7 +23995,7 @@ inline uint32 MTPwebPage::innerLength() const { } case mtpc_webPage: { const MTPDwebPage &v(c_webPage()); - return v.vflags.innerLength() + v.vid.innerLength() + v.vurl.innerLength() + v.vdisplay_url.innerLength() + (v.has_type() ? v.vtype.innerLength() : 0) + (v.has_site_name() ? v.vsite_name.innerLength() : 0) + (v.has_title() ? v.vtitle.innerLength() : 0) + (v.has_description() ? v.vdescription.innerLength() : 0) + (v.has_photo() ? v.vphoto.innerLength() : 0) + (v.has_embed_url() ? v.vembed_url.innerLength() : 0) + (v.has_embed_type() ? v.vembed_type.innerLength() : 0) + (v.has_embed_width() ? v.vembed_width.innerLength() : 0) + (v.has_embed_height() ? v.vembed_height.innerLength() : 0) + (v.has_duration() ? v.vduration.innerLength() : 0) + (v.has_author() ? v.vauthor.innerLength() : 0); + return v.vflags.innerLength() + v.vid.innerLength() + v.vurl.innerLength() + v.vdisplay_url.innerLength() + (v.has_type() ? v.vtype.innerLength() : 0) + (v.has_site_name() ? v.vsite_name.innerLength() : 0) + (v.has_title() ? v.vtitle.innerLength() : 0) + (v.has_description() ? v.vdescription.innerLength() : 0) + (v.has_photo() ? v.vphoto.innerLength() : 0) + (v.has_embed_url() ? v.vembed_url.innerLength() : 0) + (v.has_embed_type() ? v.vembed_type.innerLength() : 0) + (v.has_embed_width() ? v.vembed_width.innerLength() : 0) + (v.has_embed_height() ? v.vembed_height.innerLength() : 0) + (v.has_duration() ? v.vduration.innerLength() : 0) + (v.has_author() ? v.vauthor.innerLength() : 0) + (v.has_document() ? v.vdocument.innerLength() : 0); } } return 0; @@ -25588,6 +24036,7 @@ inline void MTPwebPage::read(const mtpPrime *&from, const mtpPrime *end, mtpType if (v.has_embed_height()) { v.vembed_height.read(from, end); } else { v.vembed_height = MTPint(); } if (v.has_duration()) { v.vduration.read(from, end); } else { v.vduration = MTPint(); } if (v.has_author()) { v.vauthor.read(from, end); } else { v.vauthor = MTPstring(); } + if (v.has_document()) { v.vdocument.read(from, end); } else { v.vdocument = MTPDocument(); } } break; default: throw mtpErrorUnexpected(cons, "MTPwebPage"); } @@ -25620,6 +24069,7 @@ inline void MTPwebPage::write(mtpBuffer &to) const { if (v.has_embed_height()) v.vembed_height.write(to); if (v.has_duration()) v.vduration.write(to); if (v.has_author()) v.vauthor.write(to); + if (v.has_document()) v.vdocument.write(to); } break; } } @@ -25643,8 +24093,8 @@ inline MTPwebPage MTP_webPageEmpty(const MTPlong &_id) { inline MTPwebPage MTP_webPagePending(const MTPlong &_id, MTPint _date) { return MTPwebPage(new MTPDwebPagePending(_id, _date)); } -inline MTPwebPage MTP_webPage(MTPint _flags, const MTPlong &_id, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_site_name, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _embed_width, MTPint _embed_height, MTPint _duration, const MTPstring &_author) { - return MTPwebPage(new MTPDwebPage(_flags, _id, _url, _display_url, _type, _site_name, _title, _description, _photo, _embed_url, _embed_type, _embed_width, _embed_height, _duration, _author)); +inline MTPwebPage MTP_webPage(MTPint _flags, const MTPlong &_id, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_site_name, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _embed_width, MTPint _embed_height, MTPint _duration, const MTPstring &_author, const MTPDocument &_document) { + return MTPwebPage(new MTPDwebPage(_flags, _id, _url, _display_url, _type, _site_name, _title, _description, _photo, _embed_url, _embed_type, _embed_width, _embed_height, _duration, _author, _document)); } inline MTPauthorization::MTPauthorization() : mtpDataOwner(new MTPDauthorization()) { diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl index 440d0eb3f..66803e904 100644 --- a/Telegram/SourceFiles/mtproto/scheme.tl +++ b/Telegram/SourceFiles/mtproto/scheme.tl @@ -146,8 +146,8 @@ inputMediaUploadedPhoto#f7aff1c0 file:InputFile caption:string = InputMedia; inputMediaPhoto#e9bfb4f3 id:InputPhoto caption:string = InputMedia; inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia; inputMediaContact#a6e45987 phone_number:string first_name:string last_name:string = InputMedia; -inputMediaUploadedVideo#e13fd4bc file:InputFile duration:int w:int h:int caption:string = InputMedia; -inputMediaUploadedThumbVideo#96fb97dc file:InputFile thumb:InputFile duration:int w:int h:int caption:string = InputMedia; +inputMediaUploadedVideo#82713fdf file:InputFile duration:int w:int h:int mime_type:string caption:string = InputMedia; +inputMediaUploadedThumbVideo#7780ddf9 file:InputFile thumb:InputFile duration:int w:int h:int mime_type:string caption:string = InputMedia; inputMediaVideo#936a4ebd id:InputVideo caption:string = InputMedia; inputChatPhotoEmpty#1ca48f57 = InputChatPhoto; @@ -212,7 +212,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto; chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto; messageEmpty#83e5de54 id:int = Message; -message#f07814c8 flags:# id:int from_id:int to_id:Peer fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int date:int message:string media:MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector = Message; +message#2bebfa86 flags:# id:int from_id:int to_id:Peer fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector = Message; messageService#1d86f70e flags:int id:int from_id:int to_id:Peer date:int action:MessageAction = Message; messageMediaEmpty#3ded6320 = MessageMedia; @@ -283,8 +283,6 @@ contactSuggested#3de191a1 user_id:int mutual_contacts:int = ContactSuggested; contactStatus#d3680c61 user_id:int status:UserStatus = ContactStatus; -chatLocated#3631cf4c chat_id:int distance:int = ChatLocated; - contacts.link#3ace484c my_link:ContactLink foreign_link:ContactLink user:User = contacts.Link; contacts.contactsNotModified#b74ba9d2 = contacts.Contacts; @@ -303,8 +301,6 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector messages:Vector< messages.messages#8c718e87 messages:Vector chats:Vector users:Vector = messages.Messages; messages.messagesSlice#b446ae3 count:int messages:Vector chats:Vector users:Vector = messages.Messages; -messages.sentMessage#8a99d8e0 id:int date:int media:MessageMedia entities:Vector pts:int pts_count:int = messages.SentMessage; - messages.chats#64ff9fd5 chats:Vector = messages.Chats; messages.chatFull#e5d7d19c full_chat:ChatFull chats:Vector users:Vector = messages.ChatFull; @@ -365,30 +361,6 @@ help.noAppUpdate#c45a6536 = help.AppUpdate; help.inviteText#18cb9f78 message:string = help.InviteText; -messages.sentMessageLink#35a1a663 id:int date:int media:MessageMedia pts:int pts_count:int links:Vector seq:int = messages.SentMessage; - -inputGeoChat#74d456fa chat_id:int access_hash:long = InputGeoChat; - -inputNotifyGeoChatPeer#4d8ddec8 peer:InputGeoChat = InputNotifyPeer; - -geoChat#75eaea5a id:int access_hash:long title:string address:string venue:string geo:GeoPoint photo:ChatPhoto participants_count:int date:int checked_in:Bool version:int = Chat; - -geoChatMessageEmpty#60311a9b chat_id:int id:int = GeoChatMessage; -geoChatMessage#4505f8e1 chat_id:int id:int from_id:int date:int message:string media:MessageMedia = GeoChatMessage; -geoChatMessageService#d34fa24e chat_id:int id:int from_id:int date:int action:MessageAction = GeoChatMessage; - -geochats.statedMessage#17b1578b message:GeoChatMessage chats:Vector users:Vector seq:int = geochats.StatedMessage; - -geochats.located#48feb267 results:Vector messages:Vector chats:Vector users:Vector = geochats.Located; - -geochats.messages#d1526db1 messages:Vector chats:Vector users:Vector = geochats.Messages; -geochats.messagesSlice#bc5863e8 count:int messages:Vector chats:Vector users:Vector = geochats.Messages; - -messageActionGeoChatCreate#6f038ebc title:string address:string = MessageAction; -messageActionGeoChatCheckin#c7d53de = MessageAction; - -updateNewGeoChatMessage#5a68e3f7 message:GeoChatMessage = Update; - wallPaperSolid#63117f24 id:int title:string bg_color:int color:int = WallPaper; updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update; @@ -546,7 +518,7 @@ updateWebPage#2cc36971 webpage:WebPage = Update; webPageEmpty#eb1477e8 id:long = WebPage; webPagePending#c586da1c id:long date:int = WebPage; -webPage#a31ea0b5 flags:# id:long url:string display_url:string type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string = WebPage; +webPage#ca820ed7 flags:# id:long url:string display_url:string type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document = WebPage; messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia; @@ -621,6 +593,8 @@ messageEntityCode#28a20571 offset:int length:int = MessageEntity; messageEntityPre#73924be0 offset:int length:int language:string = MessageEntity; messageEntityTextUrl#76a6d327 offset:int length:int url:string = MessageEntity; +updateShortSentMessage#11f1331c flags:# id:int pts:int pts_count:int date:int media:flags.9?MessageMedia entities:flags.7?Vector = Updates; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -672,7 +646,7 @@ messages.deleteHistory#f4f8fb61 peer:InputPeer offset:int = messages.AffectedHis messages.deleteMessages#a5f18925 id:Vector = messages.AffectedMessages; messages.receivedMessages#5a954c0 max_id:int = Vector; messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool; -messages.sendMessage#df12390 flags:# peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector = messages.SentMessage; +messages.sendMessage#fa88427a flags:# peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector = Updates; messages.sendMedia#c8f16791 flags:# peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia random_id:long reply_markup:flags.2?ReplyMarkup = Updates; messages.forwardMessages#55e1728d peer:InputPeer id:Vector random_id:Vector = Updates; messages.getChats#3c6aa187 id:Vector = messages.Chats; @@ -703,20 +677,6 @@ photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int messages.forwardMessage#33963bf9 peer:InputPeer id:int random_id:long = Updates; messages.sendBroadcast#bf73f4da contacts:Vector random_id:Vector message:string media:InputMedia = Updates; - -geochats.getLocated#7f192d8f geo_point:InputGeoPoint radius:int limit:int = geochats.Located; -geochats.getRecents#e1427e6f offset:int limit:int = geochats.Messages; -geochats.checkin#55b3e8fb peer:InputGeoChat = geochats.StatedMessage; -geochats.getFullChat#6722dd6f peer:InputGeoChat = messages.ChatFull; -geochats.editChatTitle#4c8e2273 peer:InputGeoChat title:string address:string = geochats.StatedMessage; -geochats.editChatPhoto#35d81a95 peer:InputGeoChat photo:InputChatPhoto = geochats.StatedMessage; -geochats.search#cfcdc44d peer:InputGeoChat q:string filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = geochats.Messages; -geochats.getHistory#b53f7a68 peer:InputGeoChat offset:int max_id:int limit:int = geochats.Messages; -geochats.setTyping#8b8a729 peer:InputGeoChat typing:Bool = Bool; -geochats.sendMessage#61b0044 peer:InputGeoChat message:string random_id:long = geochats.StatedMessage; -geochats.sendMedia#b8f0deff peer:InputGeoChat media:InputMedia random_id:long = geochats.StatedMessage; -geochats.createGeoChat#e092e16 title:string geo_point:InputGeoPoint address:string venue:string = geochats.StatedMessage; - messages.getDhConfig#26cf8950 version:int random_length:int = messages.DhConfig; messages.requestEncryption#f64daf43 user_id:InputUser random_id:int g_a:bytes = EncryptedChat; messages.acceptEncryption#3dbc0415 peer:InputEncryptedChat g_b:bytes key_fingerprint:long = EncryptedChat; diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index cbc3d25f9..813631424 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -27,6 +27,110 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "application.h" #include "gui/filedialog.h" +OverviewInner::CachedLink::CachedLink(HistoryItem *item) : titleWidth(0), page(0), pixw(0), pixh(0), text(st::msgMinWidth) { + QString msgText; + LinksInText msgLinks; + item->getTextWithLinks(msgText, msgLinks); + int32 from = 0, till = msgText.size(), lnk = msgLinks.size(); + for (int32 i = 0; i < lnk; ++i) { + if (msgLinks[i].type != LinkInTextUrl && msgLinks[i].type != LinkInTextCustomUrl && msgLinks[i].type != LinkInTextEmail) { + continue; + } + QString url = msgLinks[i].text, text = msgText.mid(msgLinks[i].offset, msgLinks[i].length); + urls.push_back(Link(url.isEmpty() ? text : url, text)); + } + while (lnk > 0 && till > from) { + --lnk; + if (msgLinks[lnk].type != LinkInTextUrl && msgLinks[lnk].type != LinkInTextCustomUrl && msgLinks[lnk].type != LinkInTextEmail) { + ++lnk; + break; + } + int32 afterLinkStart = msgLinks[lnk].offset + msgLinks[lnk].length; + if (till > afterLinkStart) { + if (!QRegularExpression(qsl("^[,.\\s_=+\\-;:`'\"\\(\\)\\[\\]\\{\\}<>*&^%\\$#@!\\\\/]+$")).match(msgText.mid(afterLinkStart, till - afterLinkStart)).hasMatch()) { + ++lnk; + break; + } + } + till = msgLinks[lnk].offset; + } + if (!lnk) { + if (QRegularExpression(qsl("^[,.\\s\\-;:`'\"\\(\\)\\[\\]\\{\\}<>*&^%\\$#@!\\\\/]+$")).match(msgText.mid(from, till - from)).hasMatch()) { + till = from; + } + } + + HistoryMedia *media = item->getMedia(); + page = (media && media->type() == MediaTypeWebPage) ? static_cast(media)->webpage() : 0; + if (from >= till && page) { + msgText = page->description; + from = 0; + till = msgText.size(); + } + if (till > from) { + TextParseOptions opts = { TextParseMultiline, int32(st::linksMaxWidth), 3 * st::msgFont->height, Qt::LayoutDirectionAuto }; + text.setText(st::msgFont, msgText.mid(from, till - from), opts); + } + int32 tw = 0, th = 0; + if (page && page->photo) { + if (!page->photo->full->loaded()) page->photo->medium->load(false, false); + + tw = convertScale(page->photo->medium->width()); + th = convertScale(page->photo->medium->height()); + } else if (page && page->doc) { + if (!page->doc->thumb->loaded()) page->doc->thumb->load(false, false); + + tw = convertScale(page->doc->thumb->width()); + th = convertScale(page->doc->thumb->height()); + } + if (tw > st::dlgPhotoSize) { + if (th > tw) { + th = th * st::dlgPhotoSize / tw; + tw = st::dlgPhotoSize; + } else if (th > st::dlgPhotoSize) { + tw = tw * st::dlgPhotoSize / th; + th = st::dlgPhotoSize; + } + } + pixw = tw; + pixh = th; + if (pixw < 1) pixw = 1; + if (pixh < 1) pixh = 1; + + if (page) { + title = page->title; + } + QVector parts = (page ? page->url : (urls.isEmpty() ? QString() : urls.at(0).url)).splitRef('/'); + if (!parts.isEmpty()) { + QStringRef domain = parts.at(0); + if (parts.size() > 2 && domain.endsWith(':') && parts.at(1).isEmpty()) { // http:// and others + domain = parts.at(2); + } + + parts = domain.split('@').back().split('.'); + if (parts.size() > 1) { + letter = parts.at(parts.size() - 2).at(0).toUpper(); + if (title.isEmpty()) { + title.reserve(parts.at(parts.size() - 2).size()); + title.append(letter).append(parts.at(parts.size() - 2).mid(1)); + } + } + } + titleWidth = st::webPageTitleFont->m.width(title); +} + +int32 OverviewInner::CachedLink::countHeight(int32 w) { + int32 result = 0; + if (!title.isEmpty()) { + result += st::webPageTitleFont->height; + } + if (!text.isEmpty()) { + result += qMin(3 * st::msgFont->height, text.countHeight(w - st::dlgPhotoSize - st::dlgPhotoPadding)); + } + result += urls.size() * st::msgFont->height; + return qMax(result, int(st::dlgPhotoSize)) + st::linksMargin * 2 + st::linksBorder; +} + // flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, const PeerData *peer, MediaOverviewType type) : QWidget(0) @@ -43,16 +147,29 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, const , _audioLeft(st::msgMargin.left()) , _audioWidth(st::msgMinWidth) , _audioHeight(st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom()) + , _linksLeft(st::linksSearchMargin.left()) + , _linksWidth(st::msgMinWidth) + , _search(this, st::dlgFilter, lang(lng_dlg_filter)) + , _cancelSearch(this, st::btnCancelSearch) + , _itemsToBeLoaded(LinksOverviewPerPage * 2) + , _inSearch(false) + , _searchFull(false) + , _searchRequest(0) + , _lastSearchId(0) + , _searchedCount(0) , _width(st::wndMinWidth) , _height(0) , _minHeight(0) , _addToY(0) , _cursor(style::cur_default) + , _cursorState(HistoryDefaultCursorState) , _dragAction(NoDrag) , _dragItem(0), _selectedMsgId(0) , _dragItemIndex(-1) , _mousedItem(0) , _mousedItemIndex(-1) + , _lnkOverIndex(0) + , _lnkDownIndex(0) , _dragWasInactive(false) , _dragSelFrom(0) , _dragSelTo(0) @@ -72,6 +189,8 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, const App::contextItem(0); + _linkTipTimer.setSingleShot(true); + connect(&_linkTipTimer, SIGNAL(timeout()), this, SLOT(showLinkTip())); _touchSelectTimer.setSingleShot(true); connect(&_touchSelectTimer, SIGNAL(timeout()), this, SLOT(onTouchSelect())); @@ -81,8 +200,18 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, const mediaOverviewUpdated(); setMouseTracking(true); - if (_type == OverviewAudioDocuments) { + connect(&_cancelSearch, SIGNAL(clicked()), this, SLOT(onCancelSearch())); + connect(&_search, SIGNAL(cancelled()), this, SLOT(onCancel())); + connect(&_search, SIGNAL(changed()), this, SLOT(onSearchUpdate())); + _searchTimer.setSingleShot(true); + connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages())); + + _cancelSearch.hide(); + if (_type == OverviewLinks) { + _search.show(); + } else { + _search.hide(); } } @@ -165,6 +294,93 @@ void OverviewInner::fixItemIndex(int32 ¤t, MsgId msgId) const { } } +void OverviewInner::searchReceived(bool fromStart, const MTPmessages_Messages &result, mtpRequestId req) { + if (fromStart && !_search.text().isEmpty()) { + SearchQueries::iterator i = _searchQueries.find(req); + if (i != _searchQueries.cend()) { + _searchCache[i.value()] = result; + _searchQueries.erase(i); + } + } + + if (_searchRequest == req) { + const QVector *messages = 0; + switch (result.type()) { + case mtpc_messages_messages: { + App::feedUsers(result.c_messages_messages().vusers); + App::feedChats(result.c_messages_messages().vchats); + messages = &result.c_messages_messages().vmessages.c_vector().v; + _searchedCount = messages->size(); + } break; + + case mtpc_messages_messagesSlice: { + App::feedUsers(result.c_messages_messagesSlice().vusers); + App::feedChats(result.c_messages_messagesSlice().vchats); + messages = &result.c_messages_messagesSlice().vmessages.c_vector().v; + _searchedCount = result.c_messages_messagesSlice().vcount.v; + } break; + } + if (messages) { + if (messages->isEmpty()) { + _searchFull = true; + } + if (fromStart) { + _searchResults.clear(); + _lastSearchId = 0; + _itemsToBeLoaded = LinksOverviewPerPage * 2; + } + for (QVector::const_iterator i = messages->cbegin(), e = messages->cend(); i != e; ++i) { + HistoryItem *item = App::histories().addToBack(*i, -1); + _searchResults.push_front(item->id); + _lastSearchId = item->id; + } + mediaOverviewUpdated(); + } + + _searchRequest = 0; + _overview->onScroll(); + } +} + +bool OverviewInner::searchFailed(const RPCError &error, mtpRequestId req) { + if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false; + + if (_searchRequest == req) { + _searchRequest = 0; + _searchFull = true; + } + return true; +} + +OverviewInner::CachedLink *OverviewInner::cachedLink(HistoryItem *item) { + CachedLinks::const_iterator i = _links.constFind(item->id); + if (i == _links.cend()) i = _links.insert(item->id, new CachedLink(item)); + return i.value(); +} + +QString OverviewInner::urlByIndex(MsgId msgid, int32 index, int32 lnkIndex, bool *fullShown) const { + fixItemIndex(index, msgid); + if (index < 0 || !_items[index].link) return QString(); + + if (lnkIndex < 0) { + if (fullShown) *fullShown = (_items[index].link->urls.size() == 1) && (_items[index].link->urls.at(0).width <= _linksWidth - (st::dlgPhotoSize + st::dlgPhotoPadding)); + if (_items[index].link->page) { + return _items[index].link->page->url; + } else if (!_items[index].link->urls.isEmpty()) { + return _items[index].link->urls.at(0).url; + } + } else if (lnkIndex > 0 && lnkIndex <= _items[index].link->urls.size()) { + if (fullShown) *fullShown = _items[index].link->urls.at(lnkIndex - 1).width <= _linksWidth - (st::dlgPhotoSize + st::dlgPhotoPadding); + return _items[index].link->urls.at(lnkIndex - 1).url; + } + return QString(); +} + +bool OverviewInner::urlIsEmail(const QString &url) const { + int32 at = url.indexOf('@'), slash = url.indexOf('/'); + return (at > 0) && (slash < 0 || slash > at); +} + bool OverviewInner::itemHasPoint(MsgId msgId, int32 index, int32 x, int32 y) const { fixItemIndex(index, msgId); if (index < 0) return false; @@ -177,6 +393,10 @@ bool OverviewInner::itemHasPoint(MsgId msgId, int32 index, int32 x, int32 y) con if (x >= _audioLeft && x < _audioLeft + _audioWidth && y >= 0 && y < _audioHeight) { return true; } + } else if (_type == OverviewLinks) { + if (x >= _linksLeft && x < _linksLeft + _linksWidth && y >= 0 && y < itemHeight(msgId, index)) { + return true; + } } else { HistoryItem *item = App::histItemById(msgId); HistoryMedia *media = item ? item->getMedia(true) : 0; @@ -201,6 +421,9 @@ int32 OverviewInner::itemHeight(MsgId msgId, int32 index) const { } fixItemIndex(index, msgId); + if (_type == OverviewLinks) { + return (index < 0) ? 0 : ((index + 1 < _items.size() ? _items[index + 1].y : (_height - _addToY)) - _items[index].y); + } return (index < 0) ? 0 : (_items[index].y - (index > 0 ? _items[index - 1].y : 0)); } @@ -249,11 +472,10 @@ void OverviewInner::updateMsg(MsgId itemId, int32 itemIndex) { update(int32(col * w), _addToY + int32(row * vsize), qCeil(w), vsize); } else if (_type == OverviewAudioDocuments) { update(_audioLeft, _addToY + int32(itemIndex * _audioHeight), _audioWidth, _audioHeight); + } else if (_type == OverviewLinks) { + update(_linksLeft, _addToY + _items[itemIndex].y, _linksWidth, itemHeight(itemId, itemIndex)); } else { - HistoryItem *item = App::histItemById(itemId); - HistoryMedia *media = item ? item->getMedia(true) : 0; - int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); - if (media) update(0, _addToY + _height - _items[itemIndex].y, _width, media->countHeight(item, w) + st::msgMargin.top() + st::msgMargin.bottom()); + update(0, _addToY + _height - _items[itemIndex].y, _width, itemHeight(itemId, itemIndex)); } } } @@ -377,6 +599,11 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but App::pressedLinkItem(App::hoveredLinkItem()); updateMsg(App::pressedLinkItem()); } + if (_lnkDownIndex != _lnkOverIndex) { + if (_dragItem) updateMsg(_dragItem, _dragItemIndex); + _lnkDownIndex = _lnkOverIndex; + if (_mousedItem) updateMsg(_mousedItem, _mousedItemIndex); + } _dragAction = NoDrag; _dragItem = _mousedItem; @@ -384,11 +611,11 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but _dragStartPos = mapMouseToItem(mapFromGlobal(screenPos), _dragItem, _dragItemIndex); _dragWasInactive = App::wnd()->inactivePress(); if (_dragWasInactive) App::wnd()->inactivePress(false); - if (textlnkDown() && _selected.isEmpty()) { + if ((textlnkDown() || _lnkDownIndex) && _selected.isEmpty()) { _dragAction = PrepareDrag; } else if (!_selected.isEmpty()) { if (_selected.cbegin().value() == FullItemSel) { - if (_selected.constFind(_dragItem) != _selected.cend() && textlnkDown()) { + if (_selected.constFind(_dragItem) != _selected.cend() && (textlnkDown() || _lnkDownIndex)) { _dragAction = PrepareDrag; // start items drag } else { _dragAction = PrepareSelect; // start items select @@ -399,7 +626,7 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but bool afterDragSymbol = false , uponSymbol = false; uint16 symbol = 0; if (!_dragWasInactive) { - if (textlnkDown()) { + if (textlnkDown() || _lnkDownIndex) { _dragSymbol = symbol; uint32 selStatus = (_dragSymbol << 16) | _dragSymbol; if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) { @@ -439,6 +666,7 @@ void OverviewInner::dragActionCancel() { void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton button) { TextLinkPtr needClick; + int32 needClickIndex = 0; dragActionUpdate(screenPos); @@ -447,6 +675,11 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu needClick = textlnkDown(); } } + if (_lnkOverIndex) { + if (_lnkDownIndex == _lnkOverIndex && _dragAction != Dragging && !_selMode) { + needClickIndex = _lnkDownIndex; + } + } if (textlnkDown()) { updateMsg(App::pressedLinkItem()); textlnkDown(TextLinkPtr()); @@ -456,11 +689,29 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu setCursor(_cursor); } } + if (_lnkDownIndex) { + updateMsg(_dragItem, _dragItemIndex); + _lnkDownIndex = 0; + if (!_lnkOverIndex && _cursor != style::cur_default) { + _cursor = style::cur_default; + setCursor(_cursor); + } + } if (needClick) { needClick->onClick(button); dragActionCancel(); return; } + if (needClickIndex) { + QString url = urlByIndex(_dragItem, _dragItemIndex, needClickIndex); + if (urlIsEmail(url)) { + EmailLink(url).onClick(button); + } else { + TextLink(url).onClick(button); + } + dragActionCancel(); + return; + } if (_dragAction == PrepareSelect && !needClick && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { SelectedItems::iterator i = _selected.find(_dragItem); if (i == _selected.cend() && _dragItem > 0) { @@ -525,6 +776,16 @@ void OverviewInner::onDragExec() { } else if (textlnkDown()) { sel = textlnkDown()->encoded(); if (!sel.isEmpty() && sel.at(0) != '/' && sel.at(0) != '@' && sel.at(0) != '#') { +// urls.push_back(QUrl::fromEncoded(sel.toUtf8())); // Google Chrome crashes in Mac OS X O_o + } + } else if (_lnkDownIndex) { + QString url = urlByIndex(_dragItem, _dragItemIndex, _lnkDownIndex); + if (urlIsEmail(url)) { + sel = EmailLink(url).encoded(); + } else { + sel = TextLink(url).encoded(); + } + if (!sel.isEmpty() && sel.at(0) != '/' && sel.at(0) != '@' && sel.at(0) != '#') { // urls.push_back(QUrl::fromEncoded(sel.toUtf8())); // Google Chrome crashes in Mac OS X O_o } } @@ -542,6 +803,7 @@ void OverviewInner::onDragExec() { } drag->setMimeData(mimeData); drag->exec(Qt::CopyAction); + dragActionUpdate(QCursor::pos()); return; } else { HistoryItem *pressedLnkItem = App::pressedLinkItem(), *pressedItem = App::pressedItem(); @@ -566,6 +828,7 @@ void OverviewInner::onDragExec() { drag->setMimeData(mimeData); drag->exec(Qt::CopyAction); + dragActionUpdate(QCursor::pos()); return; } } @@ -629,12 +892,22 @@ QPoint OverviewInner::mapMouseToItem(QPoint p, MsgId itemId, int32 itemIndex) { p.setY(p.y() - _addToY - row * (_vsize + st::overviewPhotoSkip) - st::overviewPhotoSkip); } else if (_type == OverviewAudioDocuments) { p.setY(p.y() - _addToY - itemIndex * _audioHeight); + } else if (_type == OverviewLinks) { + p.setY(p.y() - _addToY - _items[itemIndex].y); } else { p.setY(p.y() - _addToY - (_height - _items[itemIndex].y)); } return p; } +void OverviewInner::activate() { + if (_type == OverviewLinks) { + _search.setFocus(); + } else { + setFocus(); + } +} + void OverviewInner::clear() { _cached.clear(); } @@ -649,6 +922,27 @@ int32 OverviewInner::itemTop(MsgId msgId) const { return -1; } +void OverviewInner::preloadMore() { + if (_inSearch) { + if (!_searchRequest && !_searchFull) { + _searchRequest = MTP::send(MTPmessages_Search(_hist->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(_lastSearchId), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, !_lastSearchId), rpcFail(&OverviewInner::searchFailed)); + if (!_lastSearchId) { + _searchQueries.insert(_searchRequest, _searchQuery); + } + } + } else if (App::main()) { + App::main()->loadMediaBack(_hist->peer, _type, _type != OverviewLinks); + } +} + +bool OverviewInner::preloadLocal() { + if (_type != OverviewLinks) return false; + if (_itemsToBeLoaded >= _hist->_overview[_type].size()) return false; + _itemsToBeLoaded += LinksOverviewPerPage; + mediaOverviewUpdated(); + return true; +} + QPixmap OverviewInner::genPix(PhotoData *photo, int32 size) { size *= cIntRetinaFactor(); QImage img = (photo->full->loaded() ? photo->full : (photo->medium->loaded() ? photo->medium : photo->thumb))->pix().toImage(); @@ -680,6 +974,11 @@ void OverviewInner::paintEvent(QPaintEvent *e) { QPoint dogPos((_width - st::msgDogImg.pxWidth()) / 2, ((height() - st::msgDogImg.pxHeight()) * 4) / 9); p.drawPixmap(dogPos, *cChatDogImage()); return; + } else if (_inSearch && _searchResults.isEmpty() && _searchFull && !_searchTimer.isActive()) { + p.setFont(st::noContactsFont->f); + p.setPen(st::noContactsColor->p); + p.drawText(QRect(_linksLeft, _addToY, _linksWidth, _addToY), lng_search_found_results(lt_count, 0), style::al_center); + return; } int32 selfrom = -1, selto = -1; @@ -766,9 +1065,9 @@ void OverviewInner::paintEvent(QPaintEvent *e) { } if (sel == FullItemSel) { p.fillRect(QRect(pos.x(), pos.y(), _vsize, _vsize), st::overviewPhotoSelectOverlay->b); - p.drawPixmap(QPoint(pos.x() + _vsize - st::overviewPhotoChecked.pxWidth(), pos.y() + _vsize - st::overviewPhotoChecked.pxHeight()), App::sprite(), st::overviewPhotoChecked); + p.drawPixmap(QPoint(pos.x() + _vsize - st::overviewPhotoCheck.pxWidth(), pos.y() + _vsize - st::overviewPhotoCheck.pxHeight()), App::sprite(), st::overviewPhotoChecked); } else if (_selMode/* || (selfrom < count && selfrom <= selto && 0 <= selto)*/) { - p.drawPixmap(QPoint(pos.x() + _vsize - st::overviewPhotoChecked.pxWidth(), pos.y() + _vsize - st::overviewPhotoChecked.pxHeight()), App::sprite(), st::overviewPhotoCheck); + p.drawPixmap(QPoint(pos.x() + _vsize - st::overviewPhotoCheck.pxWidth(), pos.y() + _vsize - st::overviewPhotoCheck.pxHeight()), App::sprite(), st::overviewPhotoCheck); } } break; } @@ -800,6 +1099,97 @@ void OverviewInner::paintEvent(QPaintEvent *e) { static_cast(m)->drawInPlaylist(p, item, (sel == FullItemSel), ((_menu ? (App::contextItem() ? App::contextItem()->id : 0) : _selectedMsgId) == item->id), _audioWidth); p.translate(0, _audioHeight); } + } else if (_type == OverviewLinks) { + p.translate(_linksLeft, _addToY); + int32 y = 0, w = _linksWidth; + for (int32 i = 0, l = _items.size(); i < l; ++i) { + if (i + 1 == l || _addToY + _items[i + 1].y > r.top()) { + int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, top = st::linksMargin + st::linksBorder, curY = _items[i].y; + if (_addToY + curY >= r.bottom()) break; + + p.translate(0, curY - y); + if (_items[i].msgid) { // draw item + CachedLink *lnk = _items[i].link; + WebPageData *page = lnk->page; + if (page && page->photo) { + QPixmap pix; + if (page->photo->full->loaded()) { + pix = page->photo->full->pixSingle(lnk->pixw, lnk->pixh, st::dlgPhotoSize, st::dlgPhotoSize); + } else if (page->photo->medium->loaded()) { + pix = page->photo->medium->pixSingle(lnk->pixw, lnk->pixh, st::dlgPhotoSize, st::dlgPhotoSize); + } else { + pix = page->photo->thumb->pixBlurredSingle(lnk->pixw, lnk->pixh, st::dlgPhotoSize, st::dlgPhotoSize); + } + p.drawPixmap(0, top, pix); + } else if (page && page->doc && !page->doc->thumb->isNull()) { + p.drawPixmap(0, top, page->doc->thumb->pixSingle(lnk->pixw, lnk->pixh, st::dlgPhotoSize, st::dlgPhotoSize)); + } else { + int32 index = lnk->letter.isEmpty() ? 0 : (lnk->letter.at(0).unicode() % 4); + switch (index) { + case 0: App::roundRect(p, QRect(0, top, st::dlgPhotoSize, st::dlgPhotoSize), st::mvDocRedColor, DocRedCorners); break; + case 1: App::roundRect(p, QRect(0, top, st::dlgPhotoSize, st::dlgPhotoSize), st::mvDocYellowColor, DocYellowCorners); break; + case 2: App::roundRect(p, QRect(0, top, st::dlgPhotoSize, st::dlgPhotoSize), st::mvDocGreenColor, DocGreenCorners); break; + case 3: App::roundRect(p, QRect(0, top, st::dlgPhotoSize, st::dlgPhotoSize), st::mvDocBlueColor, DocBlueCorners); break; + } + + if (!lnk->letter.isEmpty()) { + p.setFont(st::linksLetterFont->f); + p.setPen(st::white->p); + p.drawText(QRect(0, top, st::dlgPhotoSize, st::dlgPhotoSize), lnk->letter, style::al_center); + } + } + + uint32 sel = 0; + if (i >= selfrom && i <= selto) { + sel = (_dragSelecting && _items[i].msgid > 0) ? FullItemSel : 0; + } else if (hasSel) { + SelectedItems::const_iterator j = _selected.constFind(_items[i].msgid); + if (j != selEnd) { + sel = j.value(); + } + } + if (sel == FullItemSel) { + App::roundRect(p, QRect(0, top, st::dlgPhotoSize, st::dlgPhotoSize), st::overviewPhotoSelectOverlay, PhotoSelectOverlayCorners); + p.drawPixmap(QPoint(st::dlgPhotoSize - st::linksPhotoCheck.pxWidth(), top + st::dlgPhotoSize - st::linksPhotoCheck.pxHeight()), App::sprite(), st::linksPhotoChecked); + } else if (_selMode/* || (selfrom < count && selfrom <= selto && 0 <= selto)*/) { + p.drawPixmap(QPoint(st::dlgPhotoSize - st::linksPhotoCheck.pxWidth(), top + st::dlgPhotoSize - st::linksPhotoCheck.pxHeight()), App::sprite(), st::linksPhotoCheck); + } + + if (!lnk->title.isEmpty() && lnk->text.isEmpty() && lnk->urls.size() == 1) { + top += (st::dlgPhotoSize - st::webPageTitleFont->height - st::msgFont->height) / 2; + } + + p.setPen(st::black->p); + p.setFont(st::webPageTitleFont->f); + if (!lnk->title.isEmpty()) { + p.drawText(left, top + st::webPageTitleFont->ascent, (_linksWidth - left < lnk->titleWidth) ? st::webPageTitleFont->m.elidedText(lnk->title, Qt::ElideRight, _linksWidth - left) : lnk->title); + top += st::webPageTitleFont->height; + } + p.setFont(st::msgFont->f); + if (!lnk->text.isEmpty()) { + lnk->text.drawElided(p, left, top, _linksWidth - left, 3); + top += qMin(st::msgFont->height * 3, lnk->text.countHeight(_linksWidth - left)); + } + + p.setPen(st::btnYesColor->p); + for (int32 j = 0, c = lnk->urls.size(); j < c; ++j) { + bool sel = (_mousedItem == _items[i].msgid && j + 1 == _lnkOverIndex); + if (sel) p.setFont(st::msgFont->underline()->f); + p.drawText(left, top + st::msgFont->ascent, (_linksWidth - left < lnk->urls[j].width) ? st::msgFont->m.elidedText(lnk->urls[j].text, Qt::ElideRight, _linksWidth - left) : lnk->urls[j].text); + if (sel) p.setFont(st::msgFont->f); + top += st::msgFont->height; + } + p.fillRect(left, _items[i].y - curY, _linksWidth - left, st::linksBorder, st::linksBorderColor->b); + } else { + QString str = langDayOfMonth(_items[i].date); + + p.setPen(st::linksDateColor->p); + p.setFont(st::msgFont->f); + p.drawText(0, st::linksDateMargin + st::msgFont->ascent, str); + } + y = curY; + } + } } else { p.translate(0, st::msgMargin.top() + _addToY); int32 y = 0, w = _width - st::msgMargin.left() - st::msgMargin.right(); @@ -876,9 +1266,11 @@ void OverviewInner::onUpdateSelected() { QPoint m(_overview->clampMousePosition(mousePos)); TextLinkPtr lnk; + int32 lnkIndex = 0; // for OverviewLinks HistoryItem *item = 0; int32 index = -1; int32 newsel = 0; + HistoryCursorState cursorState = HistoryDefaultCursorState; if (_type == OverviewPhotos) { float64 w = (float64(_width - st::overviewPhotoSkip) / _photosInRow); int32 inRow = int32((m.x() - (st::overviewPhotoSkip / 2)) / w), vsize = (_vsize + st::overviewPhotoSkip); @@ -888,8 +1280,6 @@ void OverviewInner::onUpdateSelected() { bool upon = true; int32 i = row * _photosInRow + inRow - _photosToAdd, count = _hist->_overview[_type].size(); - if (!count) return; - if (i < 0) { i = 0; upon = false; @@ -898,25 +1288,24 @@ void OverviewInner::onUpdateSelected() { i = count - 1; upon = false; } - MsgId msgid = _hist->_overview[_type][i]; - HistoryItem *histItem = App::histItemById(msgid); - if (histItem) { - item = histItem; - index = i; - if (upon && m.x() >= inRow * w + st::overviewPhotoSkip && m.x() < inRow * w + st::overviewPhotoSkip + _vsize) { - if (m.y() >= _addToY + row * vsize + st::overviewPhotoSkip && m.y() < _addToY + (row + 1) * vsize + st::overviewPhotoSkip) { - HistoryMedia *media = item->getMedia(true); - if (media && media->type() == MediaTypePhoto) { - lnk = static_cast(media)->lnk(); + if (i >= 0) { + MsgId msgid = _hist->_overview[_type][i]; + HistoryItem *histItem = App::histItemById(msgid); + if (histItem) { + item = histItem; + index = i; + if (upon && m.x() >= inRow * w + st::overviewPhotoSkip && m.x() < inRow * w + st::overviewPhotoSkip + _vsize) { + if (m.y() >= _addToY + row * vsize + st::overviewPhotoSkip && m.y() < _addToY + (row + 1) * vsize + st::overviewPhotoSkip) { + HistoryMedia *media = item->getMedia(true); + if (media && media->type() == MediaTypePhoto) { + lnk = static_cast(media)->lnk(); + } } } } - } else { - return; } } else if (_type == OverviewAudioDocuments) { int32 i = int32((m.y() - _addToY) / _audioHeight), count = _hist->_overview[_type].size(); - if (!count) return; bool upon = true; if (m.y() < _addToY) { @@ -927,42 +1316,82 @@ void OverviewInner::onUpdateSelected() { i = count - 1; upon = false; } - MsgId msgid = _hist->_overview[_type][i]; - HistoryItem *histItem = App::histItemById(msgid); - if (histItem) { - item = histItem; - index = i; - if (upon && m.x() >= _audioLeft && m.x() < _audioLeft + _audioWidth) { - HistoryMedia *media = item->getMedia(true); - if (media && media->type() == MediaTypeDocument) { - lnk = static_cast(media)->linkInPlaylist(); - newsel = item->id; + if (i >= 0) { + MsgId msgid = _hist->_overview[_type][i]; + HistoryItem *histItem = App::histItemById(msgid); + if (histItem) { + item = histItem; + index = i; + if (upon && m.x() >= _audioLeft && m.x() < _audioLeft + _audioWidth) { + HistoryMedia *media = item->getMedia(true); + if (media && media->type() == MediaTypeDocument) { + lnk = static_cast(media)->linkInPlaylist(); + newsel = item->id; + } } } - if (newsel != _selectedMsgId) { - updateMsg(App::histItemById(_selectedMsgId)); - _selectedMsgId = newsel; - updateMsg(item); + } + if (newsel != _selectedMsgId) { + if (_selectedMsgId) updateMsg(App::histItemById(_selectedMsgId)); + _selectedMsgId = newsel; + updateMsg(item); + } + } else if (_type == OverviewLinks) { + int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); + for (int32 i = 0, l = _items.size(); i < l; ++i) { + if ((i + 1 == l) || (_addToY + _items[i + 1].y > m.y())) { + int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, y = _addToY + _items[i].y; + if (!_items[i].msgid) { // day item + int32 h = 2 * st::linksDateMargin + st::msgFont->height;// itemHeight(_items[i].msgid, i); + if (i > 0 && ((y + h / 2) >= m.y() || i == _items.size() - 1)) { + --i; + if (!_items[i].msgid) break; // wtf + y = _addToY + _items[i].y; + } else if (i < _items.size() - 1 && ((y + h / 2) < m.y() || !i)) { + ++i; + if (!_items[i].msgid) break; // wtf + y = _addToY + _items[i].y; + } else { + break; // wtf + } + } + + HistoryItem *histItem = App::histItemById(_items[i].msgid); + if (histItem) { + item = histItem; + index = i; + + int32 top = y + st::linksMargin + st::linksBorder, left = _linksLeft + st::dlgPhotoSize + st::dlgPhotoPadding, w = _linksWidth - st::dlgPhotoSize - st::dlgPhotoPadding; + if (!_items[i].link->title.isEmpty() && _items[i].link->text.isEmpty() && _items[i].link->urls.size() == 1) { + top += (st::dlgPhotoSize - st::webPageTitleFont->height - st::msgFont->height) / 2; + } + if (QRect(_linksLeft, y + st::linksMargin + st::linksBorder, st::dlgPhotoSize, st::dlgPhotoSize).contains(m)) { + lnkIndex = -1; + } else if (!_items[i].link->title.isEmpty() && QRect(left, top, qMin(w, _items[i].link->titleWidth), st::webPageTitleFont->height).contains(m)) { + lnkIndex = -1; + } else { + if (!_items[i].link->title.isEmpty()) top += st::webPageTitleFont->height; + if (!_items[i].link->text.isEmpty()) top += qMin(st::msgFont->height * 3, _items[i].link->text.countHeight(w)); + for (int32 j = 0, c = _items[i].link->urls.size(); j < c; ++j) { + if (QRect(left, top, qMin(w, _items[i].link->urls[j].width), st::msgFont->height).contains(m)) { + lnkIndex = j + 1; + break; + } + top += st::msgFont->height; + } + } + } + break; } - } else { - if (newsel != _selectedMsgId) { - updateMsg(App::histItemById(_selectedMsgId)); - _selectedMsgId = newsel; - } - return; } } else { int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); - if (_items.isEmpty()) return; - for (int32 i = _items.size(); i > 0;) { --i; if (!i || (_addToY + _height - _items[i - 1].y > m.y())) { int32 y = _addToY + _height - _items[i].y; - if (item) break; - if (!_items[i].msgid) { // day item - int32 h = itemHeight(_items[i].msgid, i); + int32 h = st::msgServiceFont->height + st::msgServicePadding.top() + st::msgServicePadding.bottom() + st::msgServiceMargin.top() + st::msgServiceMargin.bottom(); // itemHeight(_items[i].msgid, i); if (i > 0 && ((y + h / 2) < m.y() || i == _items.size() - 1)) { --i; if (!_items[i].msgid) break; // wtf @@ -990,18 +1419,18 @@ void OverviewInner::onUpdateSelected() { } left += st::msgPhotoSkip; } - HistoryCursorState cursorState = HistoryDefaultCursorState; TextLinkPtr link; media->getState(link, cursorState, m.x() - left, m.y() - y - st::msgMargin.top(), item, w); if (link) lnk = link; } - } else { - return; } + break; } } } + MsgId oldMousedItem = _mousedItem; + int32 oldMousedItemIndex = _mousedItemIndex; _mousedItem = item ? item->id : 0; _mousedItemIndex = index; m = mapMouseToItem(m, _mousedItem, _mousedItemIndex); @@ -1014,14 +1443,31 @@ void OverviewInner::onUpdateSelected() { textlnkOver(lnk); App::hoveredLinkItem(lnk ? item : 0); updateMsg(App::hoveredLinkItem()); + QToolTip::hideText(); } else { App::mousedItem(item); } + if (lnkIndex != _lnkOverIndex || _mousedItem != oldMousedItem) { + lnkChanged = true; + if (oldMousedItem) updateMsg(App::histItemById(oldMousedItem)); + _lnkOverIndex = lnkIndex; + if (item) updateMsg(item); + QToolTip::hideText(); + } + if (_cursorState == HistoryInDateCursorState && cursorState != HistoryInDateCursorState) { + QToolTip::hideText(); + } + if (cursorState != _cursorState) { + _cursorState = cursorState; + } + if (lnk || lnkIndex || cursorState == HistoryInDateCursorState) { + _linkTipTimer.start(1000); + } fixItemIndex(_dragItemIndex, _dragItem); fixItemIndex(_mousedItemIndex, _mousedItem); if (_dragAction == NoDrag) { - if (lnk) { + if (lnk || lnkIndex) { cur = style::cur_pointer; } } else { @@ -1037,15 +1483,15 @@ void OverviewInner::onUpdateSelected() { _dragAction = Selecting; } } - cur = textlnkDown() ? style::cur_pointer : style::cur_default; + cur = (textlnkDown() || _lnkDownIndex) ? style::cur_pointer : style::cur_default; if (_dragAction == Selecting) { - if (_mousedItem == _dragItem && lnk && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + if (_mousedItem == _dragItem && (lnk || lnkIndex) && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { bool afterSymbol = false, uponSymbol = false; uint16 second = 0; _selected[_dragItem] = 0; updateDragSelection(0, -1, 0, -1, false); } else { - bool selectingDown = ((_type == OverviewPhotos || _type == OverviewAudioDocuments) ? (_mousedItemIndex > _dragItemIndex) : (_mousedItemIndex < _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && (_type == OverviewPhotos ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y()))); + bool selectingDown = ((_type == OverviewPhotos || _type == OverviewAudioDocuments || _type == OverviewLinks) ? (_mousedItemIndex > _dragItemIndex) : (_mousedItemIndex < _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && (_type == OverviewPhotos ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y()))); MsgId dragSelFrom = _dragItem, dragSelTo = _mousedItem; int32 dragSelFromIndex = _dragItemIndex, dragSelToIndex = _mousedItemIndex; if (!itemHasPoint(dragSelFrom, dragSelFromIndex, _dragStartPos.x(), _dragStartPos.y())) { // maybe exclude dragSelFrom @@ -1058,6 +1504,10 @@ void OverviewInner::onUpdateSelected() { if (_dragStartPos.y() >= itemHeight(dragSelFrom, dragSelFromIndex) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) { moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); } + } else if (_type == OverviewLinks) { + if (_dragStartPos.y() >= itemHeight(dragSelFrom, dragSelFromIndex) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) { + moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); + } } else { if (_dragStartPos.y() >= (itemHeight(dragSelFrom, dragSelFromIndex) - st::msgMargin.bottom()) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) { moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); @@ -1072,6 +1522,10 @@ void OverviewInner::onUpdateSelected() { if (_dragStartPos.y() < 0 || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) { moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); } + } else if (_type == OverviewLinks) { + if (_dragStartPos.y() < 0 || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) { + moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); + } } else { if (_dragStartPos.y() < st::msgMargin.top() || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) { moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); @@ -1089,6 +1543,10 @@ void OverviewInner::onUpdateSelected() { if (m.y() < 0) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); } + } else if (_type == OverviewLinks) { + if (m.y() < 0) { + moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1); + } } else { if (m.y() < st::msgMargin.top()) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); @@ -1100,6 +1558,10 @@ void OverviewInner::onUpdateSelected() { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); } } else if (_type == OverviewAudioDocuments) { + if (m.y() >= itemHeight(dragSelTo, dragSelToIndex)) { + moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1); + } + } else if (_type == OverviewLinks) { if (m.y() >= itemHeight(dragSelTo, dragSelToIndex)) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); } @@ -1125,7 +1587,7 @@ void OverviewInner::onUpdateSelected() { } else if (_dragAction == Dragging) { } - if (textlnkDown()) { + if (textlnkDown() || _lnkDownIndex) { cur = style::cur_pointer; } else if (_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { if (!_dragSelFrom || !_dragSelTo) { @@ -1145,6 +1607,27 @@ void OverviewInner::onUpdateSelected() { } } + +void OverviewInner::showLinkTip() { + TextLinkPtr lnk = textlnkOver(); + int32 dd = QApplication::startDragDistance(); + QPoint dp(mapFromGlobal(_dragPos)); + QRect r(dp.x() - dd, dp.y() - dd, 2 * dd, 2 * dd); + if (lnk && !lnk->fullDisplayed()) { + QToolTip::showText(_dragPos, lnk->readable(), this, r); + } else if (_lnkOverIndex) { + bool fullLink = false; + QString url = urlByIndex(_mousedItem, _mousedItemIndex, _lnkOverIndex, &fullLink); + if (!fullLink) { + QToolTip::showText(_dragPos, url, this, r); + } + } else if (_cursorState == HistoryInDateCursorState && _dragAction == NoDrag && _mousedItem) { + if (HistoryItem *item = App::histItemById(_mousedItem)) { + QToolTip::showText(_dragPos, item->date.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat)), this, r); + } + } +} + void OverviewInner::updateDragSelection(MsgId dragSelFrom, int32 dragSelFromIndex, MsgId dragSelTo, int32 dragSelToIndex, bool dragSelecting) { if (_dragSelFrom != dragSelFrom || _dragSelFromIndex != dragSelFromIndex || _dragSelTo != dragSelTo || _dragSelToIndex != dragSelToIndex || _dragSelecting != dragSelecting) { _dragSelFrom = dragSelFrom; @@ -1176,12 +1659,12 @@ void OverviewInner::mouseReleaseEvent(QMouseEvent *e) { } void OverviewInner::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) { - if (_selected.isEmpty() || e->key() == Qt::Key_Back) { - App::main()->showBackFromStack(); - } else { - _overview->onClearSelected(); - } + if ((_search.isHidden() || !_search.hasFocus()) && !_overview->isHidden() && e->key() == Qt::Key_Escape) { + onCancel(); + } else if (e->key() == Qt::Key_Back) { + App::main()->showBackFromStack(); + } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { + onSearchMessages(); } } @@ -1210,6 +1693,10 @@ void OverviewInner::resizeEvent(QResizeEvent *e) { _width = width(); _audioWidth = qMin(_width - st::profilePadding.left() - st::profilePadding.right(), int(st::profileMaxWidth)); _audioLeft = (_width - _audioWidth) / 2; + _linksWidth = qMin(_width - st::linksSearchMargin.left() - st::linksSearchMargin.right(), int(st::linksMaxWidth)); + _linksLeft = (_width - _linksWidth) / 2; + _search.setGeometry(_linksLeft, st::linksSearchMargin.top(), _linksWidth, _search.height()); + _cancelSearch.move(_linksLeft + _linksWidth - _cancelSearch.width(), _search.y()); showAll(true); onUpdateSelected(); update(); @@ -1226,13 +1713,21 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { dragActionUpdate(e->globalPos()); } + bool ignoreMousedItem = false; + if (_mousedItem > 0) { + QPoint m = mapMouseToItem(mapFromGlobal(e->globalPos()), _mousedItem, _mousedItemIndex); + if (m.y() < 0 || m.y() >= itemHeight(_mousedItem, _mousedItemIndex)) { + ignoreMousedItem = true; + } + } + // -2 - has full selected items, but not over, 0 - no selection, 2 - over full selected items int32 isUponSelected = 0, hasSelected = 0; if (!_selected.isEmpty()) { isUponSelected = -1; if (_selected.cbegin().value() == FullItemSel) { hasSelected = 2; - if (App::hoveredLinkItem() && _selected.constFind(App::hoveredLinkItem()->id) != _selected.cend()) { + if (!ignoreMousedItem && App::mousedItem() && _selected.constFind(App::mousedItem()->id) != _selected.cend()) { isUponSelected = 2; } else { isUponSelected = -2; @@ -1282,8 +1777,23 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { App::contextItem(App::hoveredLinkItem()); updateMsg(App::contextItem()); if (_selectedMsgId > 0) updateMsg(App::histItemById(_selectedMsgId)); - } else if (App::mousedItem() && App::mousedItem()->id == _mousedItem) { + } else if (!ignoreMousedItem && App::mousedItem() && App::mousedItem()->id == _mousedItem) { + _contextMenuUrl = _lnkOverIndex ? urlByIndex(_mousedItem, _mousedItemIndex, _lnkOverIndex) : QString(); _menu = new ContextMenu(_overview); + if ((_contextMenuLnk && dynamic_cast(_contextMenuLnk.data())) || (!_contextMenuUrl.isEmpty() && !urlIsEmail(_contextMenuUrl))) { + _menu->addAction(lang(lng_context_open_link), this, SLOT(openContextUrl()))->setEnabled(true); + _menu->addAction(lang(lng_context_copy_link), this, SLOT(copyContextUrl()))->setEnabled(true); + } else if ((_contextMenuLnk && dynamic_cast(_contextMenuLnk.data())) || (!_contextMenuUrl.isEmpty() && urlIsEmail(_contextMenuUrl))) { + _menu->addAction(lang(lng_context_open_email), this, SLOT(openContextUrl()))->setEnabled(true); + _menu->addAction(lang(lng_context_copy_email), this, SLOT(copyContextUrl()))->setEnabled(true); + } else if (_contextMenuLnk && dynamic_cast(_contextMenuLnk.data())) { + _menu->addAction(lang(lng_context_open_mention), this, SLOT(openContextUrl()))->setEnabled(true); + _menu->addAction(lang(lng_context_copy_mention), this, SLOT(copyContextUrl()))->setEnabled(true); + } else if (_contextMenuLnk && dynamic_cast(_contextMenuLnk.data())) { + _menu->addAction(lang(lng_context_open_hashtag), this, SLOT(openContextUrl()))->setEnabled(true); + _menu->addAction(lang(lng_context_copy_hashtag), this, SLOT(copyContextUrl()))->setEnabled(true); + } else { + } _menu->addAction(lang(lng_context_to_msg), this, SLOT(goToMessage()))->setEnabled(true); if (isUponSelected > 1) { _menu->addAction(lang(lng_context_forward_selected), _overview, SLOT(onForwardSelected())); @@ -1313,7 +1823,13 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeight) { if (width() == nwidth && minHeight == _minHeight) return scrollTop; _minHeight = minHeight; - _addToY = (_type == OverviewAudioDocuments) ? st::playlistPadding : ((_height < _minHeight) ? (_minHeight - _height) : 0); + if (_type == OverviewAudioDocuments) { + _addToY = st::playlistPadding; + } else if (_type == OverviewLinks) { + _addToY = st::linksSearchMargin.top() + _search.height() + st::linksSearchMargin.bottom(); + } else { + _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; + } if (_type == OverviewPhotos && _resizeIndex < 0) { _resizeIndex = _photosInRow * ((scrollTop + minHeight) / int32(_vsize + st::overviewPhotoSkip)) + _photosInRow - 1; _resizeSkip = (scrollTop + minHeight) - ((scrollTop + minHeight) / int32(_vsize + st::overviewPhotoSkip)) * int32(_vsize + st::overviewPhotoSkip); @@ -1344,9 +1860,16 @@ void OverviewInner::switchType(MediaOverviewType type) { _selected.clear(); _dragItemIndex = _mousedItemIndex = _dragSelFromIndex = _dragSelToIndex = -1; _dragItem = _mousedItem = _dragSelFrom = _dragSelTo = 0; + _lnkOverIndex = _lnkDownIndex = 0; _items.clear(); _cached.clear(); _type = type; + if (_type == OverviewLinks) { + _search.show(); + } else { + _search.hide(); + } + _cancelSearch.hide(); } mediaOverviewUpdated(); if (App::wnd()) App::wnd()->update(); @@ -1357,10 +1880,23 @@ void OverviewInner::setSelectMode(bool enabled) { } void OverviewInner::openContextUrl() { - HistoryItem *was = App::hoveredLinkItem(); - App::hoveredLinkItem(App::contextItem()); - _contextMenuLnk->onClick(Qt::LeftButton); - App::hoveredLinkItem(was); + if (_contextMenuLnk) { + HistoryItem *was = App::hoveredLinkItem(); + App::hoveredLinkItem(App::contextItem()); + _contextMenuLnk->onClick(Qt::LeftButton); + App::hoveredLinkItem(was); + } else if (urlIsEmail(_contextMenuUrl)) { + EmailLink(_contextMenuUrl).onClick(Qt::LeftButton); + } else { + TextLink(_contextMenuUrl).onClick(Qt::LeftButton); + } +} + +void OverviewInner::copyContextUrl() { + QString enc = _contextMenuLnk ? _contextMenuLnk->encoded() : _contextMenuUrl; + if (!enc.isEmpty()) { + QApplication::clipboard()->setText(enc); + } } void OverviewInner::goToMessage() { @@ -1433,9 +1969,88 @@ void OverviewInner::openContextFile() { if (lnkDocument) DocumentOpenLink(lnkDocument->document()).onClick(Qt::LeftButton); } +bool OverviewInner::onSearchMessages(bool searchCache) { + QString q = _search.text().trimmed(); + if (q.isEmpty()) { + if (_searchRequest) { + _searchRequest = 0; + } + return true; + } + if (searchCache) { + SearchCache::const_iterator i = _searchCache.constFind(q); + if (i != _searchCache.cend()) { + _searchQuery = q; + _searchFull = false; + _searchRequest = 0; + searchReceived(true, i.value(), 0); + return true; + } + } else if (_searchQuery != q) { + _searchQuery = q; + _searchFull = false; + _searchRequest = MTP::send(MTPmessages_Search(_hist->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, true), rpcFail(&OverviewInner::searchFailed)); + _searchQueries.insert(_searchRequest, _searchQuery); + } + return false; +} + +void OverviewInner::onNeedSearchMessages() { + if (!onSearchMessages(true)) { + _searchTimer.start(AutoSearchTimeout); + if (_inSearch && _searchFull && _searchResults.isEmpty()) { + parentWidget()->update(); + } + } +} + +void OverviewInner::onSearchUpdate() { + QString filterText = _search.text().trimmed(); + bool inSearch = !filterText.isEmpty(), changed = (inSearch != _inSearch); + _inSearch = inSearch; + + onNeedSearchMessages(); + + if (filterText.isEmpty()) { + _searchCache.clear(); + _searchQueries.clear(); + _searchQuery = QString(); + _searchResults.clear(); + _cancelSearch.hide(); + } else if (_cancelSearch.isHidden()) { + _cancelSearch.show(); + } + + if (changed) { + _itemsToBeLoaded = LinksOverviewPerPage * 2; + mediaOverviewUpdated(); + } + _overview->scrollReset(); +} + +void OverviewInner::onCancel() { + if (_selected.isEmpty()) { + if (onCancelSearch()) return; + App::main()->showBackFromStack(); + } else { + _overview->onClearSelected(); + } +} + +bool OverviewInner::onCancelSearch() { + if (_search.isHidden()) return false; + bool clearing = !_search.text().isEmpty(); + _cancelSearch.hide(); + _search.clear(); + _search.updatePlaceholder(); + onSearchUpdate(); + return clearing; +} + void OverviewInner::onMenuDestroy(QObject *obj) { if (_menu == obj) { _menu = 0; + dragActionUpdate(QCursor::pos()); updateMsg(App::contextItem()); if (_selectedMsgId > 0) updateMsg(App::histItemById(_selectedMsgId)); } @@ -1503,7 +2118,85 @@ void OverviewInner::onTouchScrollTimer() { void OverviewInner::mediaOverviewUpdated(bool fromResize) { int32 oldHeight = _height; - if (_type != OverviewPhotos && _type != OverviewAudioDocuments) { + if (_type == OverviewLinks) { + History::MediaOverview &o(_inSearch ? _searchResults : _hist->_overview[_type]); + int32 l = o.size(), tocheck = qMin(l, _itemsToBeLoaded); + _items.reserve(2 * l); // day items + + int32 y = 0, in = 0; + bool allGood = true; + QDate prevDate; + for (int32 i = 0; i < tocheck; ++i) { + MsgId msgid = o.at(l - i - 1); + if (allGood) { + if (_items.size() > in && _items.at(in).msgid == msgid) { + prevDate = _items.at(in).date; + if (fromResize) { + _items[in].y = y; + y += _items[in].link->countHeight(_linksWidth); + } else { + y = (in + 1 < _items.size()) ? _items.at(in + 1).y : _height; + } + ++in; + continue; + } + if (_items.size() > in + 1 && !_items.at(in).msgid && _items.at(in + 1).msgid == msgid) { // day item + if (fromResize) { + _items[in].y = y; + y += st::msgFont->height + st::linksDateMargin * 2 + st::linksBorder; + } + ++in; + prevDate = _items.at(in).date; + if (fromResize) { + _items[in].y = y; + y += _items[in].link->countHeight(_linksWidth); + } else { + y = (in + 1 < _items.size()) ? _items.at(in + 1).y : _height; + } + ++in; + continue; + } + allGood = false; + } + HistoryItem *item = App::histItemById(msgid); + + QDate date = item->date.date(); + if (!in || (in > 0 && date != prevDate)) { + if (_items.size() > in) { + _items[in].msgid = 0; + _items[in].date = date; + _items[in].y = y; + } else { + _items.push_back(CachedItem(0, date, y)); + } + y += st::msgFont->height + st::linksDateMargin * 2 + st::linksBorder; + ++in; + prevDate = date; + } + + if (_items.size() > in) { + _items[in] = CachedItem(item->id, item->date.date(), y); + _items[in].link = cachedLink(item); + y += _items[in].link->countHeight(_linksWidth); + } else { + _items.push_back(CachedItem(item->id, item->date.date(), y)); + _items.back().link = cachedLink(item); + y += _items.back().link->countHeight(_linksWidth); + } + ++in; + } + if (_items.size() != in) { + _items.resize(in); + } + if (_height != _addToY + y + st::linksSearchMargin.top()) { + _height = _addToY + y + st::linksSearchMargin.top(); + if (!fromResize) { + resize(width(), _minHeight > _height ? _minHeight : _height); + } + } + dragActionUpdate(QCursor::pos()); + update(); + } else if (_type != OverviewPhotos && _type != OverviewAudioDocuments) { History::MediaOverview &o(_hist->_overview[_type]); int32 l = o.size(); _items.reserve(2 * l); // day items @@ -1598,7 +2291,7 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { if (_height != y) { _height = y; if (!fromResize) { - _addToY = (_type == OverviewAudioDocuments) ? st::playlistPadding : ((_height < _minHeight) ? (_minHeight - _height) : 0); + _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; resize(width(), _minHeight > _height ? _minHeight : _height); } } @@ -1611,7 +2304,7 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { if (!fromResize) { resizeEvent(0); - if (_height != oldHeight) { + if (_height != oldHeight && _type != OverviewLinks) { _overview->scrollBy(_height - oldHeight); } } @@ -1630,6 +2323,19 @@ void OverviewInner::changingMsgId(HistoryItem *row, MsgId newId) { break; } } + if (_links.contains(row->id) && row->id != newId) { + if (_links.contains(newId)) { + for (CachedItems::iterator i = _items.begin(), e = _items.end(); i != e; ++i) { + if (i->msgid == newId && i->link) { + i->link = _links[row->id]; + break; + } + } + } + _links[newId] = _links[row->id]; + delete _links[row->id]; + _links.remove(row->id); + } for (CachedItems::iterator i = _items.begin(), e = _items.end(); i != e; ++i) { if (i->msgid == row->id) { i->msgid = newId; @@ -1665,7 +2371,7 @@ void OverviewInner::itemRemoved(HistoryItem *item) { } void OverviewInner::itemResized(HistoryItem *item, bool scrollToIt) { - if (_type != OverviewPhotos && _type != OverviewAudioDocuments) { + if (_type != OverviewPhotos && _type != OverviewAudioDocuments && _type != OverviewLinks) { HistoryMedia *media = item ? item->getMedia(true) : 0; if (!media) return; @@ -1718,12 +2424,17 @@ void OverviewInner::msgUpdated(const HistoryItem *msg) { if (index >= 0) { update(_audioLeft, _addToY + int32(index * _audioHeight), _audioWidth, _audioHeight); } + } else if (_type == OverviewLinks) { + for (int32 i = 0, l = _items.size(); i != l; ++i) { + if (_items[i].msgid == msgid) { + update(_linksLeft, _addToY + _items[i].y, _linksWidth, itemHeight(msgid, i)); + break; + } + } } else { for (int32 i = 0, l = _items.size(); i != l; ++i) { if (_items[i].msgid == msgid) { - HistoryMedia *media = msg->getMedia(true); - int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); - if (media) update(0, _addToY + _height - _items[i].y, _width, media->countHeight(msg, w) + st::msgMargin.top() + st::msgMargin.bottom()); + update(0, _addToY + _height - _items[i].y, _width, itemHeight(msgid, i)); break; } } @@ -1746,14 +2457,23 @@ void OverviewInner::showAll(bool recountHeights) { } int32 rows = ((_photosToAdd + count) / _photosInRow) + (((_photosToAdd + count) % _photosInRow) ? 1 : 0); newHeight = _height = (_vsize + st::overviewPhotoSkip) * rows + st::overviewPhotoSkip; + _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; } else if (_type == OverviewAudioDocuments) { int32 count = _hist->_overview[_type].size(), fullCount = _hist->_overviewCount[_type]; newHeight = _height = count * _audioHeight + 2 * st::playlistPadding; + _addToY = st::playlistPadding; + } else if (_type == OverviewLinks) { + if (recountHeights) { // recount heights because of texts + mediaOverviewUpdated(true); + } + newHeight = _height; + _addToY = st::linksSearchMargin.top() + _search.height() + st::linksSearchMargin.bottom(); } else { if (recountHeights && _type == OverviewVideos) { // recount heights because of captions mediaOverviewUpdated(true); } newHeight = _height; + _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; } _addToY = (_type == OverviewAudioDocuments) ? st::playlistPadding : ((_height < _minHeight) ? (_minHeight - _height) : 0); if (newHeight < _minHeight) { @@ -1766,6 +2486,10 @@ void OverviewInner::showAll(bool recountHeights) { OverviewInner::~OverviewInner() { _dragAction = NoDrag; + for (CachedLinks::const_iterator i = _links.cbegin(), e = _links.cend(); i != e; ++i) { + delete i.value(); + } + _links.clear(); } OverviewWidget::OverviewWidget(QWidget *parent, const PeerData *peer, MediaOverviewType type) : QWidget(parent) @@ -1801,10 +2525,16 @@ void OverviewWidget::clear() { void OverviewWidget::onScroll() { MTP::clearLoaderPriorities(); - if (_scroll.scrollTop() < _scroll.height() * 5) { - if (App::main()) { - App::main()->loadMediaBack(peer(), type(), true); + int32 preloadThreshold = _scroll.height() * 5; + bool needToPreload = false; + do { + needToPreload = (type() == OverviewLinks) ? (_scroll.scrollTop() + preloadThreshold > _scroll.scrollTopMax()) : (_scroll.scrollTop() < preloadThreshold); + if (!needToPreload || !_inner.preloadLocal()) { + break; } + } while (true); + if (needToPreload) { + _inner.preloadMore(); } if (!_noDropResizeIndex) { _inner.dropResizeIndex(); @@ -1836,7 +2566,7 @@ void OverviewWidget::paintEvent(QPaintEvent *e) { } QRect r(e->rect()); - if (type() == OverviewPhotos || type() == OverviewAudioDocuments) { + if (type() == OverviewPhotos || type() == OverviewAudioDocuments || type() == OverviewLinks) { p.fillRect(r, st::white->b); } else { bool hasTopBar = !App::main()->topBar()->isHidden(), hasPlayer = !App::main()->player()->isHidden(); @@ -1883,6 +2613,10 @@ void OverviewWidget::scrollBy(int32 add) { } } +void OverviewWidget::scrollReset() { + _scroll.scrollToY((type() == OverviewLinks) ? 0 : _scroll.scrollTopMax()); +} + void OverviewWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth) { if (animating() && _showing) { p.setOpacity(a_bgAlpha.current()); @@ -1919,6 +2653,10 @@ MediaOverviewType OverviewWidget::type() const { void OverviewWidget::switchType(MediaOverviewType type) { _selCount = 0; + + disconnect(&_scroll, SIGNAL(scrolled()), &_inner, SLOT(onUpdateSelected())); + disconnect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); + _inner.setSelectMode(false); _inner.switchType(type); switch (type) { @@ -1927,12 +2665,18 @@ void OverviewWidget::switchType(MediaOverviewType type) { case OverviewDocuments: _header = lang(lng_profile_files_header); break; case OverviewAudios: _header = lang(lng_profile_audios_header); break; case OverviewAudioDocuments: _header = lang(lng_profile_audio_files_header); break; + case OverviewLinks: _header = lang(lng_profile_shared_links_header); break; } noSelectingScroll(); App::main()->topBar()->showSelected(0); updateTopBarSelection(); - _scroll.scrollToY(_scroll.scrollTopMax()); + scrollReset(); + + connect(&_scroll, SIGNAL(scrolled()), &_inner, SLOT(onUpdateSelected())); + connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); + onScroll(); + activate(); } void OverviewWidget::updateTopBarSelection() { @@ -1945,7 +2689,7 @@ void OverviewWidget::updateTopBarSelection() { App::main()->topBar()->update(); } if (App::wnd() && !App::wnd()->layerShown()) { - _inner.setFocus(); + _inner.activate(); } update(); } @@ -1969,6 +2713,8 @@ int32 OverviewWidget::countBestScroll() const { return snap(top - int(_scroll.height() - (st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom())) / 2, 0, _scroll.scrollTopMax()); } } + } else if (type() == OverviewLinks) { + return 0; } return _scroll.scrollTopMax(); } @@ -1978,7 +2724,7 @@ void OverviewWidget::fastShow(bool back, int32 lastScrollTop) { resizeEvent(0); _scrollSetAfterShow = (lastScrollTop < 0 ? countBestScroll() : lastScrollTop); show(); - _inner.setFocus(); + _inner.activate(); doneShow(); } @@ -2001,7 +2747,7 @@ void OverviewWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimT anim::start(this); _showing = true; show(); - _inner.setFocus(); + _inner.activate(); App::main()->topBar()->update(); } @@ -2057,9 +2803,7 @@ void OverviewWidget::msgUpdated(PeerId p, const HistoryItem *msg) { } void OverviewWidget::itemRemoved(HistoryItem *row) { - if (row->history()->peer == peer()) { - _inner.itemRemoved(row); - } + _inner.itemRemoved(row); } void OverviewWidget::itemResized(HistoryItem *row, bool scrollToIt) { @@ -2083,7 +2827,7 @@ OverviewWidget::~OverviewWidget() { } void OverviewWidget::activate() { - _inner.setFocus(); + _inner.activate(); } QPoint OverviewWidget::clampMousePosition(QPoint point) { diff --git a/Telegram/SourceFiles/overviewwidget.h b/Telegram/SourceFiles/overviewwidget.h index 6c08d903b..bd7e96c03 100644 --- a/Telegram/SourceFiles/overviewwidget.h +++ b/Telegram/SourceFiles/overviewwidget.h @@ -25,9 +25,14 @@ public: OverviewInner(OverviewWidget *overview, ScrollArea *scroll, const PeerData *peer, MediaOverviewType type); + void activate(); + void clear(); int32 itemTop(MsgId msgId) const; + bool preloadLocal(); + void preloadMore(); + bool event(QEvent *e); void touchEvent(QTouchEvent *e); void paintEvent(QPaintEvent *e); @@ -73,8 +78,10 @@ public: public slots: void onUpdateSelected(); + void showLinkTip(); void openContextUrl(); + void copyContextUrl(); void cancelContextDownload(); void showContextInFolder(); void saveContextFile(); @@ -85,12 +92,19 @@ public slots: void forwardMessage(); void selectMessage(); + void onSearchUpdate(); + void onCancel(); + bool onCancelSearch(); + void onMenuDestroy(QObject *obj); void onTouchSelect(); void onTouchScrollTimer(); void onDragExec(); + bool onSearchMessages(bool searchCache = false); + void onNeedSearchMessages(); + private: void fixItemIndex(int32 ¤t, MsgId msgId) const; @@ -122,11 +136,11 @@ private: // photos int32 _photosInRow, _photosToAdd, _vsize; - typedef struct { + struct CachedSize { int32 vsize; bool medium; QPixmap pix; - } CachedSize; + }; typedef QMap CachedSizes; CachedSizes _cached; bool _selMode; @@ -134,23 +148,75 @@ private: // audio documents int32 _audioLeft, _audioWidth, _audioHeight; - // other - typedef struct _CachedItem { - _CachedItem() : msgid(0), y(0) { + // shared links + int32 _linksLeft, _linksWidth; + struct Link { + Link() : width(0) { } - _CachedItem(MsgId msgid, const QDate &date, int32 y) : msgid(msgid), date(date), y(y) { + Link(const QString &url, const QString &text) : url(url), text(text), width(st::msgFont->m.width(text)) { + } + QString url, text; + int32 width; + }; + struct CachedLink { + CachedLink() : titleWidth(0), page(0), pixw(0), pixh(0), text(st::msgMinWidth) { + } + CachedLink(HistoryItem *item); + int32 countHeight(int32 w); + + QString title, letter; + int32 titleWidth; + WebPageData *page; + int32 pixw, pixh; + Text text; + QVector urls; + }; + typedef QMap CachedLinks; + CachedLinks _links; + FlatInput _search; + IconedButton _cancelSearch; + QVector _results; + int32 _itemsToBeLoaded; + + QTimer _searchTimer; + QString _searchQuery; + bool _inSearch, _searchFull; + mtpRequestId _searchRequest; + History::MediaOverview _searchResults; + MsgId _lastSearchId; + int32 _searchedCount; + void searchReceived(bool fromStart, const MTPmessages_Messages &result, mtpRequestId req); + bool searchFailed(const RPCError &error, mtpRequestId req); + + typedef QMap SearchCache; + SearchCache _searchCache; + + typedef QMap SearchQueries; + SearchQueries _searchQueries; + + CachedLink *cachedLink(HistoryItem *item); + + // other + struct CachedItem { + CachedItem() : msgid(0), y(0) { + } + CachedItem(MsgId msgid, const QDate &date, int32 y) : msgid(msgid), date(date), y(y) { } MsgId msgid; QDate date; int32 y; - } CachedItem; + CachedLink *link; + }; typedef QVector CachedItems; CachedItems _items; int32 _width, _height, _minHeight, _addToY; + QTimer _linkTipTimer; + // selection support, like in HistoryWidget Qt::CursorShape _cursor; + HistoryCursorState _cursorState; typedef QMap SelectedItems; SelectedItems _selected; enum DragAction { @@ -166,9 +232,14 @@ private: int32 _dragItemIndex; MsgId _mousedItem; int32 _mousedItemIndex; + int32 _lnkOverIndex, _lnkDownIndex; // for OverviewLinks, 0 - none, -1 - photo or title, > 0 - lnk index uint16 _dragSymbol; bool _dragWasInactive; + QString urlByIndex(MsgId msgid, int32 index, int32 lnkIndex, bool *fullShown = 0) const; + bool urlIsEmail(const QString &url) const; + + QString _contextMenuUrl; TextLinkPtr _contextMenuLnk; MsgId _dragSelFrom, _dragSelTo; @@ -202,6 +273,7 @@ public: void contextMenuEvent(QContextMenuEvent *e); void scrollBy(int32 add); + void scrollReset(); void paintTopBar(QPainter &p, float64 over, int32 decreaseWidth); void topBarShadowParams(int32 &x, float64 &o); diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp index d5ee5fcaf..e7f1fca3c 100644 --- a/Telegram/SourceFiles/profilewidget.cpp +++ b/Telegram/SourceFiles/profilewidget.cpp @@ -59,10 +59,14 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee // shared media _allMediaTypes(false), _mediaShowAll(this, lang(lng_profile_show_all_types)), - _mediaPhotos(this, QString()), - _mediaVideos(this, QString()), - _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), // actions _searchInPeer(this, lang(lng_profile_search_messages)), @@ -86,7 +90,7 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee if (_peerUser->blocked == UserIsBlocked) { _blockUser.setText(lang(_peerUser->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user)); } - _phoneText = App::formatPhone(_peerUser->phone); + _phoneText = App::formatPhone(_peerUser->phone.isEmpty() ? App::phoneFromSharedContact(App::userFromPeer(_peerUser->id)) : _peerUser->phone); PhotoData *userPhoto = (_peerUser->photoId && _peerUser->photoId != UnknownPeerPhotoId) ? App::photo(_peerUser->photoId) : 0; if (userPhoto && userPhoto->date) { _photoLink = TextLinkPtr(new PhotoLink(userPhoto, _peer)); @@ -161,14 +165,11 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee // shared media connect(&_mediaShowAll, SIGNAL(clicked()), this, SLOT(onMediaShowAll())); - connect(&_mediaPhotos, SIGNAL(clicked()), this, SLOT(onMediaPhotos())); - connect(&_mediaVideos, SIGNAL(clicked()), this, SLOT(onMediaVideos())); - connect(&_mediaDocuments, SIGNAL(clicked()), this, SLOT(onMediaDocuments())); - connect(&_mediaAudios, SIGNAL(clicked()), this, SLOT(onMediaAudios())); - _mediaLinks[OverviewPhotos] = &_mediaPhotos; - _mediaLinks[OverviewVideos] = &_mediaVideos; - _mediaLinks[OverviewDocuments] = &_mediaDocuments; - _mediaLinks[OverviewAudios] = &_mediaAudios; + connect((_mediaButtons[OverviewPhotos] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaPhotos())); + connect((_mediaButtons[OverviewVideos] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaVideos())); + connect((_mediaButtons[OverviewDocuments] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaDocuments())); + connect((_mediaButtons[OverviewAudios] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaAudios())); + connect((_mediaButtons[OverviewLinks] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaLinks())); App::main()->preloadOverviews(_peer); // actions @@ -216,7 +217,7 @@ void ProfileInner::loadProfilePhotos(int32 yFrom) { int32 yTo = yFrom + (parentWidget() ? parentWidget()->height() : App::wnd()->height()) * 5; MTP::clearLoaderPriorities(); - int32 partfrom = _mediaAudios.y() + _mediaAudios.height() + st::profileHeaderSkip; + int32 partfrom = _mediaButtons[OverviewAudios]->y() + _mediaButtons[OverviewAudios]->height() + st::profileHeaderSkip; yFrom -= partfrom; yTo -= partfrom; @@ -361,6 +362,10 @@ void ProfileInner::onMediaAudios() { App::main()->showMediaOverview(_peer, OverviewAudios); } +void ProfileInner::onMediaLinks() { + App::main()->showMediaOverview(_peer, OverviewLinks); +} + void ProfileInner::onInvitationLink() { QApplication::clipboard()->setText(_peerChat->invitationUrl); App::wnd()->showLayer(new ConfirmBox(lang(lng_group_invite_copied), true)); @@ -437,7 +442,7 @@ void ProfileInner::peerUpdated(PeerData *data) { if (data == _peer) { PhotoData *photo = 0; if (_peerUser) { - _phoneText = App::formatPhone(_peerUser->phone); + _phoneText = App::formatPhone(_peerUser->phone.isEmpty() ? App::phoneFromSharedContact(App::userFromPeer(_peerUser->id)) : _peerUser->phone); if (_peerUser->photoId && _peerUser->photoId != UnknownPeerPhotoId) photo = App::photo(_peerUser->photoId); if (_wasBlocked != _peerUser->blocked) { _wasBlocked = _peerUser->blocked; @@ -652,7 +657,7 @@ void ProfileInner::paintEvent(QPaintEvent *e) { if (!_allMediaTypes) { break; } - top += _mediaLinks[i]->height() + st::setLittleSkip; + top += _mediaButtons[i]->height() + st::setLittleSkip; } } if (_allMediaTypes) { @@ -660,13 +665,13 @@ void ProfileInner::paintEvent(QPaintEvent *e) { top -= st::setLittleSkip; } else { p.drawText(_left, top + st::linkFont->ascent, lang(oneState < 0 ? lng_profile_loading : lng_profile_no_media)); - top += _mediaLinks[OverviewPhotos]->height(); + top += _mediaButtons[OverviewPhotos]->height(); } } else { if (!oneState) { p.drawText(_left, top + st::linkFont->ascent, lang(lng_profile_no_media)); } - top += _mediaLinks[OverviewPhotos]->height(); + top += _mediaButtons[OverviewPhotos]->height(); } // actions @@ -934,13 +939,23 @@ void ProfileInner::resizeEvent(QResizeEvent *e) { if (_allMediaTypes) { int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1); if (count > 0) { - if (wasCount) top += _mediaLinks[i]->height() + st::setLittleSkip; + if (wasCount) top += _mediaButtons[i]->height() + st::setLittleSkip; wasCount = count; } } - _mediaLinks[i]->move(_left, top); + _mediaButtons[i]->move(_left, top); + } + top += _mediaButtons[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 && App::userFromPeer(_peerUser->id) != MTP::authedId()) { + top += st::setSectionSkip; + _blockUser.move(_left, top); top += _blockUser.height(); } - top += _mediaLinks[OverviewPhotos]->height(); // actions top += st::profileHeaderSkip; @@ -1131,17 +1146,17 @@ void ProfileInner::showAll() { if (count > 0 || count < 0) { first = true; } else if (!_allMediaTypes) { - _mediaLinks[i]->hide(); + _mediaButtons[i]->hide(); continue; } if (count > 0) { - _mediaLinks[i]->setText(overviewLinkText(i, count)); - _mediaLinks[i]->show(); + _mediaButtons[i]->setText(overviewLinkText(i, count)); + _mediaButtons[i]->show(); } else { - _mediaLinks[i]->hide(); + _mediaButtons[i]->hide(); } } else { - _mediaLinks[i]->hide(); + _mediaButtons[i]->hide(); } } if (_allMediaTypes || !manyCounts) { @@ -1208,6 +1223,7 @@ QString ProfileInner::overviewLinkText(int32 type, int32 count) { case OverviewVideos: return lng_profile_videos(lt_count, count); case OverviewDocuments: return lng_profile_files(lt_count, count); case OverviewAudios: return lng_profile_audios(lt_count, count); + case OverviewLinks: return lng_profile_shared_links(lt_count, count); } return QString(); } diff --git a/Telegram/SourceFiles/profilewidget.h b/Telegram/SourceFiles/profilewidget.h index 5c742d31f..4c2d2ef18 100644 --- a/Telegram/SourceFiles/profilewidget.h +++ b/Telegram/SourceFiles/profilewidget.h @@ -92,6 +92,7 @@ public slots: void onMediaVideos(); void onMediaDocuments(); void onMediaAudios(); + void onMediaLinks(); void onMenuDestroy(QObject *obj); void onCopyPhone(); @@ -149,8 +150,8 @@ private: // shared media bool _allMediaTypes; - LinkButton _mediaShowAll, _mediaPhotos, _mediaVideos, _mediaDocuments, _mediaAudios; - LinkButton *_mediaLinks[OverviewCount]; + LinkButton _mediaShowAll; + LinkButton *_mediaButtons[OverviewCount]; QString overviewLinkText(int32 type, int32 count); // actions diff --git a/Telegram/SourceFiles/pspecific_linux.cpp b/Telegram/SourceFiles/pspecific_linux.cpp index 3c96e062b..2859c9067 100644 --- a/Telegram/SourceFiles/pspecific_linux.cpp +++ b/Telegram/SourceFiles/pspecific_linux.cpp @@ -252,8 +252,8 @@ namespace { #define GTK_ALPHA 3 QImage _trayIconImageGen() { - int32 counter = App::histories().unreadFull, counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; - bool muted = (App::histories().unreadMuted >= counter); + int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; + bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; if (_trayIconImage.isNull() || _trayIconImage.width() != _trayIconSize || muted != _trayIconMuted || counterSlice != _trayIconCount) { if (_trayIconImageBack.isNull() || _trayIconImageBack.width() != _trayIconSize) { _trayIconImageBack = App::wnd()->iconLarge().scaled(_trayIconSize, _trayIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); @@ -288,8 +288,8 @@ namespace { } QString _trayIconImageFile() { - int32 counter = App::histories().unreadFull, counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; - bool muted = (App::histories().unreadMuted >= counter); + int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; + bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; QString name = cWorkingDir() + qsl("tdata/ticons/ico%1_%2_%3.png").arg(muted ? "mute" : "").arg(_trayIconSize).arg(counterSlice); QFileInfo info(name); @@ -641,7 +641,7 @@ void PsMainWindow::psUpdateIndicator() { void PsMainWindow::psUpdateCounter() { setWindowIcon(wndIcon); - int32 counter = App::histories().unreadFull; + int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram")); if (_psUnityLauncherEntry) { @@ -665,8 +665,10 @@ void PsMainWindow::psUpdateCounter() { ps_gtk_status_icon_set_from_pixbuf(_trayIcon, _trayPixbuf); } } else if (trayIcon) { - int32 counter = App::histories().unreadFull; - style::color bg = (App::histories().unreadMuted < counter) ? st::counterBG : st::counterMuteBG; + int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); + bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; + + style::color bg = muted ? st::counterMuteBG : st::counterBG; QIcon iconSmall; iconSmall.addPixmap(QPixmap::fromImage(iconWithCounter(16, counter, bg, true), Qt::ColorOnly)); iconSmall.addPixmap(QPixmap::fromImage(iconWithCounter(32, counter, bg, true), Qt::ColorOnly)); diff --git a/Telegram/SourceFiles/pspecific_mac.cpp b/Telegram/SourceFiles/pspecific_mac.cpp index 0cac59f75..68e982f3b 100644 --- a/Telegram/SourceFiles/pspecific_mac.cpp +++ b/Telegram/SourceFiles/pspecific_mac.cpp @@ -174,7 +174,7 @@ void _placeCounter(QImage &img, int size, int count, style::color bg, style::col } void PsMainWindow::psUpdateCounter() { - int32 counter = App::histories().unreadFull; + int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram")); setWindowIcon(wndIcon); @@ -183,14 +183,16 @@ void PsMainWindow::psUpdateCounter() { _private.setWindowBadge(counter ? cnt : QString()); if (trayIcon) { - bool dm = objc_darkMode(), important = (App::histories().unreadMuted < counter); - style::color bg = important ? st::counterBG : st::counterMuteBG; + bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; + bool dm = objc_darkMode(); + + style::color bg = muted ? st::counterMuteBG : st::counterBG; QIcon icon; QImage img(psTrayIcon(dm)), imgsel(psTrayIcon(true)); img.detach(); imgsel.detach(); int32 size = cRetina() ? 44 : 22; - _placeCounter(img, size, counter, bg, (dm && !important) ? st::counterMacInvColor : st::counterColor); + _placeCounter(img, size, counter, bg, (dm && muted) ? st::counterMacInvColor : st::counterColor); _placeCounter(imgsel, size, counter, st::white, st::counterMacInvColor); icon.addPixmap(QPixmap::fromImage(img, Qt::ColorOnly)); icon.addPixmap(QPixmap::fromImage(imgsel, Qt::ColorOnly), QIcon::Selected); diff --git a/Telegram/SourceFiles/pspecific_wnd.cpp b/Telegram/SourceFiles/pspecific_wnd.cpp index aab2e04eb..3cba849fe 100644 --- a/Telegram/SourceFiles/pspecific_wnd.cpp +++ b/Telegram/SourceFiles/pspecific_wnd.cpp @@ -119,7 +119,7 @@ namespace { }; typedef QMap ToastImages; ToastImages toastImages; - bool toastImageCreated = false; + bool toastImageSaved = false; HWND createTaskbarHider() { HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); @@ -1117,8 +1117,10 @@ static HICON _qt_createHIcon(const QIcon &icon, int xSize, int ySize) { } void PsMainWindow::psUpdateCounter() { - int32 counter = App::histories().unreadFull; - style::color bg = (App::histories().unreadMuted < counter) ? st::counterBG : st::counterMuteBG; + int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); + bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; + + style::color bg = muted ? st::counterMuteBG : st::counterBG; 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)); @@ -2123,12 +2125,14 @@ bool psShowOpenWithMenu(int x, int y, const QString &file) { } void psOpenFile(const QString &name, bool openWith) { - std::wstring wname = QDir::toNativeSeparators(name).toStdWString(); + bool mailtoScheme = name.startsWith(qstr("mailto:")); + std::wstring wname = mailtoScheme ? name.toStdWString() : QDir::toNativeSeparators(name).toStdWString(); if (openWith && useOpenAs) { if (shOpenWithDialog) { OPENASINFO info; info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT | OAIF_EXEC; + if (mailtoScheme) info.oaifInFlags |= OAIF_FILE_IS_URI | OAIF_URL_PROTOCOL; info.pcszClass = NULL; info.pcszFile = wname.c_str(); shOpenWithDialog(0, &info); @@ -2149,7 +2153,7 @@ void psStart() { } void psFinish() { - if (toastImageCreated) { + if (toastImageSaved) { psDeleteDir(cWorkingDir() + qsl("tdata/temp")); } } @@ -2709,7 +2713,7 @@ QString toastImage(const StorageKey &key, PeerData *peer) { App::wnd()->iconLarge().save(v.path, "PNG"); } i = toastImages.insert(key, v); - toastImageCreated = true; + toastImageSaved = true; } return i->path; } @@ -2805,9 +2809,6 @@ bool CreateToast(PeerData *peer, int32 msgId, bool showpix, const QString &title if (j != i->cend()) { toastNotifier->Hide(j->p.Get()); i->erase(j); - if (i->isEmpty()) { - toastNotifications.erase(i); - } } } hr = toastNotifier->Show(toast.Get()); diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index da839b676..78790d5f0 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -40,6 +40,7 @@ QString gLangErrors; QString gDialogLastPath, gDialogHelperPath; // optimize QFileDialog bool gSoundNotify = true; +bool gIncludeMuted = true; bool gDesktopNotify = true; DBINotifyView gNotifyView = dbinvShowPreview; bool gWindowsNotifications = true; diff --git a/Telegram/SourceFiles/settings.h b/Telegram/SourceFiles/settings.h index 47c9a3610..ad36a2b1b 100644 --- a/Telegram/SourceFiles/settings.h +++ b/Telegram/SourceFiles/settings.h @@ -96,6 +96,7 @@ DeclareSetting(QPixmapPointer, ChatDogImage); DeclareSetting(bool, TileBackground); DeclareSetting(bool, SoundNotify); +DeclareSetting(bool, IncludeMuted); DeclareSetting(bool, NeedConfigResave); DeclareSetting(bool, DesktopNotify); DeclareSetting(DBINotifyView, NotifyView); diff --git a/Telegram/SourceFiles/settingswidget.cpp b/Telegram/SourceFiles/settingswidget.cpp index 84b53cf38..41a1ed9a6 100644 --- a/Telegram/SourceFiles/settingswidget.cpp +++ b/Telegram/SourceFiles/settingswidget.cpp @@ -124,12 +124,15 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), _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()), + _includeMuted(this, lang(lng_settings_include_muted), cIncludeMuted()), // general _changeLanguage(this, lang(lng_settings_change_lang)), + #ifndef TDESKTOP_DISABLE_AUTOUPDATE _autoUpdate(this, lang(lng_settings_auto_update), cAutoUpdate()), _checkNow(this, lang(lng_settings_check_now)), _restartNow(this, lang(lng_settings_update_now)), + #endif _supportTray(cSupportTray()), _workmodeTray(this, lang(lng_settings_workmode_tray), (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray)), @@ -223,12 +226,15 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), connect(&_messagePreview, SIGNAL(changed()), this, SLOT(onMessagePreview())); connect(&_windowsNotifications, SIGNAL(changed()), this, SLOT(onWindowsNotifications())); connect(&_soundNotify, SIGNAL(changed()), this, SLOT(onSoundNotify())); + connect(&_includeMuted, SIGNAL(changed()), this, SLOT(onIncludeMuted())); // general connect(&_changeLanguage, SIGNAL(clicked()), this, SLOT(onChangeLanguage())); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE connect(&_autoUpdate, SIGNAL(changed()), this, SLOT(onAutoUpdate())); connect(&_checkNow, SIGNAL(clicked()), this, SLOT(onCheckNow())); connect(&_restartNow, SIGNAL(clicked()), this, SLOT(onRestartNow())); + #endif connect(&_workmodeTray, SIGNAL(changed()), this, SLOT(onWorkmodeTray())); connect(&_workmodeWindow, SIGNAL(changed()), this, SLOT(onWorkmodeWindow())); @@ -246,11 +252,13 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), _newVersionText = lang(lng_settings_update_ready) + ' '; _newVersionWidth = st::linkFont->m.width(_newVersionText); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE connect(App::app(), SIGNAL(updateChecking()), this, SLOT(onUpdateChecking())); connect(App::app(), SIGNAL(updateLatest()), this, SLOT(onUpdateLatest())); connect(App::app(), SIGNAL(updateDownloading(qint64,qint64)), this, SLOT(onUpdateDownloading(qint64,qint64))); connect(App::app(), SIGNAL(updateReady()), this, SLOT(onUpdateReady())); connect(App::app(), SIGNAL(updateFailed()), this, SLOT(onUpdateFailed())); + #endif // chat options connect(&_replaceEmojis, SIGNAL(changed()), this, SLOT(onReplaceEmojis())); @@ -303,6 +311,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), updateOnlineDisplay(); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE switch (App::app()->updatingState()) { case Application::UpdatingDownload: setUpdatingState(UpdatingDownload, true); @@ -311,6 +320,9 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), case Application::UpdatingReady: setUpdatingState(UpdatingReady, true); break; default: setUpdatingState(UpdatingNone, true); break; } + #else + _updatingState = UpdatingNone; + #endif updateConnectionType(); @@ -421,7 +433,8 @@ void SettingsInner::paintEvent(QPaintEvent *e) { if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) { top += _windowsNotifications.height() + st::setSectionSkip; } - top += _soundNotify.height(); + top += _soundNotify.height() + st::setSectionSkip; + top += _includeMuted.height(); } // general @@ -430,6 +443,7 @@ void SettingsInner::paintEvent(QPaintEvent *e) { p.drawText(_left + st::setHeaderLeft, top + st::setHeaderTop + st::setHeaderFont->ascent, lang(lng_settings_section_general)); top += st::setHeaderSkip; + #ifndef TDESKTOP_DISABLE_AUTOUPDATE top += _autoUpdate.height(); QString textToDraw; if (cAutoUpdate()) { @@ -448,6 +462,7 @@ void SettingsInner::paintEvent(QPaintEvent *e) { p.setPen(st::setVersionColor->p); p.drawText(_left + st::setVersionLeft, top + st::setVersionTop + st::linkFont->ascent, textToDraw); top += st::setVersionHeight; + #endif if (cPlatform() == dbipWindows) { top += _workmodeTray.height() + st::setLittleSkip; @@ -650,16 +665,19 @@ void SettingsInner::resizeEvent(QResizeEvent *e) { if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) { _windowsNotifications.move(_left, top); top += _windowsNotifications.height() + st::setSectionSkip; } - _soundNotify.move(_left, top); top += _soundNotify.height(); + _soundNotify.move(_left, top); top += _soundNotify.height() + st::setSectionSkip; + _includeMuted.move(_left, top); top += _includeMuted.height(); } // general top += st::setHeaderSkip; _changeLanguage.move(_left + st::setWidth - _changeLanguage.width(), top - st::setHeaderSkip + st::setHeaderTop + st::setHeaderFont->ascent - st::linkFont->ascent); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE _autoUpdate.move(_left, top); _checkNow.move(_left + st::setWidth - _checkNow.width(), top + st::cbDefFlat.textTop); top += _autoUpdate.height(); _restartNow.move(_left + st::setWidth - _restartNow.width(), top + st::setVersionTop); top += st::setVersionHeight; + #endif if (cPlatform() == dbipWindows) { _workmodeTray.move(_left, top); top += _workmodeTray.height() + st::setLittleSkip; @@ -962,18 +980,22 @@ void SettingsInner::showAll() { _windowsNotifications.hide(); } _soundNotify.show(); + _includeMuted.show(); } else { _desktopNotify.hide(); _senderName.hide(); _messagePreview.hide(); _windowsNotifications.hide(); _soundNotify.hide(); + _includeMuted.hide(); } // general _changeLanguage.show(); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE _autoUpdate.show(); setUpdatingState(_updatingState, true); + #endif if (cPlatform() == dbipWindows) { _workmodeTray.show(); _workmodeWindow.show(); @@ -1219,6 +1241,7 @@ void SettingsInner::onUpdateLocalStorage() { update(); } +#ifndef TDESKTOP_DISABLE_AUTOUPDATE void SettingsInner::onAutoUpdate() { cSetAutoUpdate(!cAutoUpdate()); Local::writeSettings(); @@ -1244,8 +1267,10 @@ void SettingsInner::onCheckNow() { cSetLastUpdateCheck(0); App::app()->startUpdateCheck(); } +#endif void SettingsInner::onRestartNow() { + #ifndef TDESKTOP_DISABLE_AUTOUPDATE checkReadyUpdate(); if (_updatingState == UpdatingReady) { cSetRestartingUpdate(true); @@ -1253,6 +1278,10 @@ void SettingsInner::onRestartNow() { cSetRestarting(true); cSetRestartingToSettings(true); } + #else + cSetRestarting(true); + cSetRestartingToSettings(true); + #endif App::quit(); } @@ -1420,6 +1449,12 @@ void SettingsInner::onSoundNotify() { Local::writeUserSettings(); } +void SettingsInner::onIncludeMuted() { + cSetIncludeMuted(_includeMuted.checked()); + if (App::wnd()) App::wnd()->updateCounter(); + Local::writeUserSettings(); +} + void SettingsInner::onWindowsNotifications() { cSetWindowsNotifications(!cWindowsNotifications()); App::wnd()->notifyClearFast(); @@ -1636,6 +1671,7 @@ void SettingsInner::onTempDirClearFailed(int task) { update(); } +#ifndef TDESKTOP_DISABLE_AUTOUPDATE void SettingsInner::setUpdatingState(UpdatingState state, bool force) { if (_updatingState != state || force) { _updatingState = state; @@ -1689,6 +1725,7 @@ void SettingsInner::onUpdateReady() { void SettingsInner::onUpdateFailed() { setUpdatingState(UpdatingFail); } +#endif void SettingsInner::onPhotoUpdateStart() { showAll(); diff --git a/Telegram/SourceFiles/settingswidget.h b/Telegram/SourceFiles/settingswidget.h index faf500406..81de3b926 100644 --- a/Telegram/SourceFiles/settingswidget.h +++ b/Telegram/SourceFiles/settingswidget.h @@ -97,8 +97,10 @@ public slots: void onUpdatePhoto(); void onUpdatePhotoCancel(); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE void onAutoUpdate(); void onCheckNow(); + #endif void onRestartNow(); void onPasscode(); @@ -123,6 +125,7 @@ public slots: void onScaleChange(); void onSoundNotify(); + void onIncludeMuted(); void onDesktopNotify(); void onSenderName(); void onMessagePreview(); @@ -149,11 +152,13 @@ public slots: void onLocalStorageClear(); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE void onUpdateChecking(); void onUpdateLatest(); void onUpdateDownloading(qint64 ready, qint64 total); void onUpdateReady(); void onUpdateFailed(); + #endif void onShowSessions(); @@ -202,12 +207,14 @@ private: LinkButton _chooseUsername; // notifications - FlatCheckbox _desktopNotify, _senderName, _messagePreview, _windowsNotifications, _soundNotify; + FlatCheckbox _desktopNotify, _senderName, _messagePreview, _windowsNotifications, _soundNotify, _includeMuted; // general LinkButton _changeLanguage; + #ifndef TDESKTOP_DISABLE_AUTOUPDATE FlatCheckbox _autoUpdate; LinkButton _checkNow, _restartNow; + #endif bool _supportTray; // cSupportTray() value on settings create FlatCheckbox _workmodeTray, _workmodeWindow; FlatCheckbox _autoStart, _startMinimized, _sendToMenu; @@ -280,8 +287,10 @@ private: void offPasswordDone(const MTPBool &result); bool offPasswordFail(const RPCError &error); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE void setUpdatingState(UpdatingState state, bool force = false); void setDownloadProgress(qint64 ready, qint64 total); + #endif }; diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 86885d11e..584b3314e 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -774,8 +774,8 @@ QString DocumentData::already(bool check) { return location.name; } -WebPageData::WebPageData(const WebPageId &id, WebPageType type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, int32 duration, const QString &author, int32 pendingTill) : -id(id), type(type), url(url), displayUrl(displayUrl), siteName(siteName), title(title), description(description), duration(duration), author(author), photo(photo), pendingTill(pendingTill) { +WebPageData::WebPageData(const WebPageId &id, WebPageType type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill) : +id(id), type(type), url(url), displayUrl(displayUrl), siteName(siteName), title(title), description(description), duration(duration), author(author), photo(photo), doc(doc), pendingTill(pendingTill) { } void PeerLink::onClick(Qt::MouseButton button) const { diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index bbc1b41b3..32efe1053 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -548,6 +548,19 @@ struct DocumentData { if (sticker()) sticker()->img->forget(); replyPreview->forget(); } + ImagePtr makeReplyPreview() { + if (replyPreview->isNull() && !thumb->isNull()) { + if (thumb->loaded()) { + int w = thumb->width(), h = thumb->height(); + if (w <= 0) w = 1; + if (h <= 0) h = 1; + replyPreview = ImagePtr(w > h ? thumb->pix(w * st::msgReplyBarSize.height() / h, st::msgReplyBarSize.height()) : thumb->pix(st::msgReplyBarSize.height()), "PNG"); + } else { + thumb->load(); + } + } + return replyPreview; + } void save(const QString &toFile); @@ -687,7 +700,7 @@ inline WebPageType toWebPageType(const QString &type) { } struct WebPageData { - WebPageData(const WebPageId &id, WebPageType type = WebPageArticle, const QString &url = QString(), const QString &displayUrl = QString(), const QString &siteName = QString(), const QString &title = QString(), const QString &description = QString(), PhotoData *photo = 0, int32 duration = 0, const QString &author = QString(), int32 pendingTill = -1); + WebPageData(const WebPageId &id, WebPageType type = WebPageArticle, const QString &url = QString(), const QString &displayUrl = QString(), const QString &siteName = QString(), const QString &title = QString(), const QString &description = QString(), PhotoData *photo = 0, DocumentData *doc = 0, int32 duration = 0, const QString &author = QString(), int32 pendingTill = -1); void forget() { if (photo) photo->forget(); @@ -699,6 +712,7 @@ struct WebPageData { int32 duration; QString author; PhotoData *photo; + DocumentData *doc; int32 pendingTill; }; diff --git a/Telegram/SourceFiles/sysbuttons.cpp b/Telegram/SourceFiles/sysbuttons.cpp index 29e11ac69..039dbb883 100644 --- a/Telegram/SourceFiles/sysbuttons.cpp +++ b/Telegram/SourceFiles/sysbuttons.cpp @@ -143,7 +143,9 @@ UpdateBtn::UpdateBtn(QWidget *parent, Window *window, const QString &text) : Sys } void UpdateBtn::onClick() { + #ifndef TDESKTOP_DISABLE_AUTOUPDATE checkReadyUpdate(); + #endif if (App::app()->updatingState() == Application::UpdatingReady) { cSetRestartingUpdate(true); } else { diff --git a/Telegram/SourceFiles/title.cpp b/Telegram/SourceFiles/title.cpp index 564b7c7a5..bea4b9b56 100644 --- a/Telegram/SourceFiles/title.cpp +++ b/Telegram/SourceFiles/title.cpp @@ -80,7 +80,9 @@ TitleWidget::TitleWidget(Window *window) connect(&_contacts, SIGNAL(clicked()), this, SLOT(onContacts())); connect(&_about, SIGNAL(clicked()), this, SLOT(onAbout())); connect(wnd->windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(stateChanged(Qt::WindowState))); + #ifndef TDESKTOP_DISABLE_AUTOUPDATE connect(App::app(), SIGNAL(updateReady()), this, SLOT(showUpdateBtn())); + #endif if (cPlatform() != dbipWindows) { _minimize.hide(); @@ -256,8 +258,10 @@ void TitleWidget::updateWideMode() { void TitleWidget::updateCounter() { if (cWideMode() || !MTP::authedId()) return; - int32 counter = App::histories().unreadFull; - style::color bg = (App::histories().unreadMuted < counter) ? st::counterBG : st::counterMuteBG; + int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); + bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; + + style::color bg = muted ? st::counterMuteBG : st::counterBG; if (counter > 0) { int32 size = cRetina() ? -32 : -16; diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h index 976f40085..377f92238 100644 --- a/Telegram/SourceFiles/types.h +++ b/Telegram/SourceFiles/types.h @@ -275,6 +275,7 @@ enum DataBlockId { dbiTryIPv6 = 0x28, dbiSongVolume = 0x29, dbiWindowsNotifications = 0x30, + dbiIncludeMuted = 0x31, dbiEncryptedWithSalt = 333, dbiEncrypted = 444, diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist index 37e739bf7..d2f122b3b 100644 --- a/Telegram/Telegram.plist +++ b/Telegram/Telegram.plist @@ -11,7 +11,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.8.51 + 0.8.55 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) CFBundleSignature diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc index c9f1d53aa..1bef96184 100644 Binary files a/Telegram/Telegram.rc and b/Telegram/Telegram.rc differ diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index 7c366d53c..e70bb69f7 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -1477,6 +1477,20 @@ $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) + + Moc%27ing countrycodeinput.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -D_SCL_SECURE_NO_WARNINGS "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.5.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.5.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/gui/countrycodeinput.h" + Moc%27ing countrycodeinput.h... + Moc%27ing countrycodeinput.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\mpg123-1.22.1\ports\MSVC++" "-I.\..\..\Libraries\mpg123-1.22.1\src\libmpg123" "-I.\..\..\Libraries\faad2-2.7\include" "-I.\..\..\Libraries\faad2-2.7\common\mp4ff" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.5.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.5.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/gui/countrycodeinput.h" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.5.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.5.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/gui/countrycodeinput.h" + $(QTDIR)\bin\moc.exe;%(FullPath) + $(QTDIR)\bin\moc.exe;%(FullPath) + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing phoneinput.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp @@ -2151,4 +2165,4 @@ - \ No newline at end of file + diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj index 8e0a76647..885112ac8 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.51; + CURRENT_PROJECT_VERSION = 0.8.55; 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.51; + CURRENT_PROJECT_VERSION = 0.8.55; 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.51; + CURRENT_PROJECT_VERSION = 0.8.55; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 0.8; - DYLIB_CURRENT_VERSION = 0.8.51; + DYLIB_CURRENT_VERSION = 0.8.55; 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.51; + CURRENT_PROJECT_VERSION = 0.8.55; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 0.8; - DYLIB_CURRENT_VERSION = 0.8.51; + DYLIB_CURRENT_VERSION = 0.8.55; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; diff --git a/Telegram/UpdateLang.sh b/Telegram/UpdateLang.sh index b0e114eee..5f9a11dad 100755 --- a/Telegram/UpdateLang.sh +++ b/Telegram/UpdateLang.sh @@ -2,9 +2,11 @@ cd ../../ tx pull -fa cd translations/telegram-desktop.langstrings/ for file in *.strings; do - iconv -f "UTF-16LE" -t "UTF-8" "$file" > "../../tdesktop/Telegram/SourceFiles/langs/lang_$file.tmp" - awk '{ if (NR==1) sub(/^\xef\xbb\xbf/,""); sub(/ /,""); print }' "../../tdesktop/Telegram/SourceFiles/langs/lang_$file.tmp" > "../../tdesktop/Telegram/SourceFiles/langs/lang_$file" - rm "../../tdesktop/Telegram/SourceFiles/langs/lang_$file.tmp" + if [ "$file" != "es_419.strings" ]; then + iconv -f "UTF-16LE" -t "UTF-8" "$file" > "../../tdesktop/Telegram/SourceFiles/langs/lang_$file.tmp" + awk '{ if (NR==1) sub(/^\xef\xbb\xbf/,""); sub(/ /,""); print }' "../../tdesktop/Telegram/SourceFiles/langs/lang_$file.tmp" > "../../tdesktop/Telegram/SourceFiles/langs/lang_$file" + rm "../../tdesktop/Telegram/SourceFiles/langs/lang_$file.tmp" + fi done cd ../../tdesktop/Telegram/ touch SourceFiles/telegram.qrc diff --git a/Telegram/Version.sh b/Telegram/Version.sh index 497943c84..5ad51f6bd 100755 --- a/Telegram/Version.sh +++ b/Telegram/Version.sh @@ -1,2 +1,2 @@ -echo 0.8 8051 0.8.51 0 +echo 0.8 8055 0.8.55 0 # AppVersionStrMajor AppVersion AppVersionStr DevChannel diff --git a/Telegram/_qt_5_5_0_patch.diff b/Telegram/_qt_5_5_0_patch.diff index aed8c6268..534242a94 100644 --- a/Telegram/_qt_5_5_0_patch.diff +++ b/Telegram/_qt_5_5_0_patch.diff @@ -11566,6 +11566,22 @@ index da0ba27..1d42b79 100644 void QWindowsXpFileDialogHelper::selectNameFilter(const QString &f) { m_data.setSelectedNameFilter(f); // Dialog cannot be updated at run-time. +diff --git a/qtbase/src/plugins/platforms/windows/qwindowsservices.cpp b/qtbase/src/plugins/platforms/windows/qwindowsservices.cpp +index cc697ba..8e15e86 100644 +--- a/qtbase/src/plugins/platforms/windows/qwindowsservices.cpp ++++ b/qtbase/src/plugins/platforms/windows/qwindowsservices.cpp +@@ -125,8 +125,9 @@ static inline bool launchMail(const QUrl &url) + } + // Pass the url as the parameter. Should use QProcess::startDetached(), + // but that cannot handle a Windows command line [yet]. +- command.replace(QStringLiteral("%1"), url.toString(QUrl::FullyEncoded)); +- if (debug) ++ if (command.indexOf(QStringLiteral("%1")) < 0) return false; ++ command.replace(QStringLiteral("%1"), url.toString(QUrl::FullyEncoded)); ++ if (debug) + qDebug() << __FUNCTION__ << "Launching" << command; + //start the process + PROCESS_INFORMATION pi; diff --git a/qtbase/src/plugins/platforms/windows/qwindowswindow.cpp b/qtbase/src/plugins/platforms/windows/qwindowswindow.cpp index 543c081..d80429b 100644 --- a/qtbase/src/plugins/platforms/windows/qwindowswindow.cpp diff --git a/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/windows/qwindowsservices.cpp b/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/windows/qwindowsservices.cpp new file mode 100644 index 000000000..8e15e86d5 --- /dev/null +++ b/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/windows/qwindowsservices.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#define QT_NO_URL_CAST_FROM_STRING +#include "qwindowsservices.h" +#include "qtwindows_additional.h" + +#include +#include +#include + +#include +#ifndef Q_OS_WINCE +# include +#endif + +QT_BEGIN_NAMESPACE + +enum { debug = 0 }; + +static inline bool shellExecute(const QUrl &url) +{ +#ifndef Q_OS_WINCE + const QString nativeFilePath = + url.isLocalFile() ? QDir::toNativeSeparators(url.toLocalFile()) : url.toString(QUrl::FullyEncoded); + const quintptr result = (quintptr)ShellExecute(0, 0, (wchar_t*)nativeFilePath.utf16(), 0, 0, SW_SHOWNORMAL); + // ShellExecute returns a value greater than 32 if successful + if (result <= 32) { + qWarning("ShellExecute '%s' failed (error %s).", qPrintable(url.toString()), qPrintable(QString::number(result))); + return false; + } + return true; +#else + Q_UNUSED(url); + return false; +#endif +} + +// Retrieve the commandline for the default mail client. It contains a +// placeholder %1 for the URL. The default key used below is the +// command line for the mailto: shell command. +static inline QString mailCommand() +{ + enum { BufferSize = sizeof(wchar_t) * MAX_PATH }; + + const wchar_t mailUserKey[] = L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\mailto\\UserChoice"; + + wchar_t command[MAX_PATH] = {0}; + // Check if user has set preference, otherwise use default. + HKEY handle; + QString keyName; + if (!RegOpenKeyEx(HKEY_CURRENT_USER, mailUserKey, 0, KEY_READ, &handle)) { + DWORD bufferSize = BufferSize; + if (!RegQueryValueEx(handle, L"Progid", 0, 0, reinterpret_cast(command), &bufferSize)) + keyName = QString::fromWCharArray(command); + RegCloseKey(handle); + } + if (keyName.isEmpty()) + keyName = QStringLiteral("mailto"); + keyName += QStringLiteral("\\Shell\\Open\\Command"); + if (debug) + qDebug() << __FUNCTION__ << "keyName=" << keyName; + command[0] = 0; + if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, (const wchar_t*)keyName.utf16(), 0, KEY_READ, &handle)) { + DWORD bufferSize = BufferSize; + RegQueryValueEx(handle, L"", 0, 0, reinterpret_cast(command), &bufferSize); + RegCloseKey(handle); + } + if (!command[0]) + return QString(); +#ifndef Q_OS_WINCE + wchar_t expandedCommand[MAX_PATH] = {0}; + return ExpandEnvironmentStrings(command, expandedCommand, MAX_PATH) ? + QString::fromWCharArray(expandedCommand) : QString::fromWCharArray(command); +#else + return QString(); +#endif +} + +static inline bool launchMail(const QUrl &url) +{ + QString command = mailCommand(); + if (command.isEmpty()) { + qWarning("Cannot launch '%s': There is no mail program installed.", qPrintable(url.toString())); + return false; + } + //Make sure the path for the process is in quotes + const QChar doubleQuote = QLatin1Char('"'); + if (!command.startsWith(doubleQuote)) { + const int exeIndex = command.indexOf(QStringLiteral(".exe "), 0, Qt::CaseInsensitive); + if (exeIndex != -1) { + command.insert(exeIndex + 4, doubleQuote); + command.prepend(doubleQuote); + } + } + // Pass the url as the parameter. Should use QProcess::startDetached(), + // but that cannot handle a Windows command line [yet]. + if (command.indexOf(QStringLiteral("%1")) < 0) return false; + command.replace(QStringLiteral("%1"), url.toString(QUrl::FullyEncoded)); + if (debug) + qDebug() << __FUNCTION__ << "Launching" << command; + //start the process + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(pi)); + STARTUPINFO si; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + if (!CreateProcess(NULL, (wchar_t*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + qErrnoWarning("Unable to launch '%s'", qPrintable(command)); + return false; + } + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return true; +} + +bool QWindowsServices::openUrl(const QUrl &url) +{ + const QString scheme = url.scheme(); + if (scheme == QLatin1String("mailto") && launchMail(url)) + return true; + return shellExecute(url); +} + +bool QWindowsServices::openDocument(const QUrl &url) +{ + return shellExecute(url); +} + +QT_END_NAMESPACE