1
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-04-01 14:50:24 +00:00

merged to master

This commit is contained in:
John Preston 2015-09-03 14:31:22 +03:00
commit f24b5fc35b
71 changed files with 2698 additions and 2731 deletions

View File

@ -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!";

View File

@ -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

View File

@ -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";

View File

@ -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);

View File

@ -70,6 +70,9 @@ namespace {
typedef QMap<HistoryItem*, QMap<HistoryReply*, bool> > RepliesTo;
RepliesTo repliesTo;
typedef QMap<int32, QString> SharedContactPhones;
SharedContactPhones sharedContactPhones;
Histories histories;
typedef QHash<MsgId, HistoryItem*> MsgsData;
@ -79,6 +82,9 @@ namespace {
typedef QMap<uint64, MsgId> RandomData;
RandomData randomData;
typedef QMap<uint64, QString> 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<MTPMessage> &msgs, int msgsState) {
const QVector<MTPMessage> &v(msgs.c_vector().v);
QMap<int32, int32> 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);

View File

@ -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<MTPMessage> &msgs, int msgsState = 0); // 2 - new read message, 1 - new unread message, 0 - not new message, -1 - searched message
void feedWereRead(const QVector<MTPint> &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<MTPDocumentAttribute> &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();

View File

@ -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;

View File

@ -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;

Binary file not shown.

Before

(image error) Size: 167 KiB

After

(image error) Size: 168 KiB

Binary file not shown.

Before

(image error) Size: 220 KiB

After

(image error) Size: 222 KiB

View File

@ -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

View File

@ -17,6 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#pragma once
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
#include <QtNetwork/QLocalSocket>
#include <QtNetwork/QLocalServer>
#include <QtNetwork/QNetworkReply>
@ -60,3 +62,5 @@ private:
};
bool checkReadyUpdate();
#endif

View File

@ -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();

View File

@ -1271,6 +1271,8 @@ void CreateGroupBox::created(const MTPUpdates &updates) {
} break;
case mtpc_updateShortChatMessage: {
} break;
case mtpc_updateShortSentMessage: {
} break;
case mtpc_updatesTooLong: {
} break;
}

View File

@ -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,

View File

@ -829,22 +829,17 @@ void DialogsListWidget::contactsReceived(const QVector<MTPContact> &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;
}

View File

@ -35,7 +35,7 @@ public:
void activate();
void contactsReceived(const QVector<MTPContact> &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;

View File

@ -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());

View File

@ -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();
}

View File

@ -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;

View File

@ -20,6 +20,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include "lang.h"
#include "pspecific.h"
#include <private/qharfbuzz_p.h>
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<NewlineBlock*>(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<SkipBlock*>(_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<const QChar*> 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) {

View File

@ -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<LinkRange> 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<LinkInText> LinksInText;
inline LinksInText linksFromMTP(const QVector<MTPMessageEntity> &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<MTPMessageEntity> linksToMTP(const LinksInText &links) {
MTPVector<MTPMessageEntity> result(MTP_vector<MTPMessageEntity>(0));
QVector<MTPMessageEntity> &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));

View File

@ -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<HistoryDocument*>(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<UserData*> *lastAuthors = &(peer->asChat()->lastAuthors);
@ -1026,7 +1040,7 @@ void History::addToFront(const QVector<MTPMessage> &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<MTPMessage> &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<MTPMessage> &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<MTPMessage> &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<MTPMessage> &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<HistoryDocument*>(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<MTPMessage> &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<MTPMessage> &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 &currentText) {
switch (media.type()) {
void HistoryMessage::initMedia(const MTPMessageMedia *media, QString &currentText) {
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)

View File

@ -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<HistoryBlock*> {
void addToBack(const QVector<MTPMessage> &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 &currentText);
void initMedia(const MTPMessageMedia *media, QString &currentText);
void initMediaFromText(QString &currentText);
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);

View File

@ -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<DocumentOpenLink*>(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()) {

View File

@ -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);

View File

@ -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;

View File

@ -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();
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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");
}

View File

@ -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";

View File

@ -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";

View File

@ -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";

View File

@ -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" = "유니코드 문자를 입력하세요.";

View File

@ -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";

View File

@ -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";

View File

@ -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());

View File

@ -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();
}

View File

@ -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<uint64>();
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<MTPMessageEntity> 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<MTPMessageEntity> 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<MTPUser>(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;

View File

@ -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<bool, QString> toProfileStartToken, const MTPUser &result);
@ -543,7 +546,7 @@ private:
enum PtsSkippedQueue {
SkippedUpdate,
SkippedUpdates,
SkippedSentMessage,
// SkippedSentMessage,
SkippedStatedMessage,
SkippedStatedMessages
};
@ -554,7 +557,7 @@ private:
QMap<uint64, PtsSkippedQueue> _byPtsQueue;
QMap<uint64, MTPUpdate> _byPtsUpdate;
QMap<uint64, MTPUpdates> _byPtsUpdates;
QMap<uint64, MTPmessages_SentMessage> _byPtsSentMessage;
// QMap<uint64, MTPmessages_SentMessage> _byPtsSentMessage;
SingleTimer _byPtsTimer;
QMap<int32, MTPUpdates> _bySeqUpdates;

View File

@ -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?..
}

View File

@ -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),

View File

@ -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 <typename bareT>
class MTPBoxed : public bareT {

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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<MessageEntity> = 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<MessageEntity> = 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<Dialog> messages:Vector<
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messagesSlice#b446ae3 count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.sentMessage#8a99d8e0 id:int date:int media:MessageMedia entities:Vector<MessageEntity> pts:int pts_count:int = messages.SentMessage;
messages.chats#64ff9fd5 chats:Vector<Chat> = messages.Chats;
messages.chatFull#e5d7d19c full_chat:ChatFull chats:Vector<Chat> users:Vector<User> = 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<contacts.Link> 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<Chat> users:Vector<User> seq:int = geochats.StatedMessage;
geochats.located#48feb267 results:Vector<ChatLocated> messages:Vector<GeoChatMessage> chats:Vector<Chat> users:Vector<User> = geochats.Located;
geochats.messages#d1526db1 messages:Vector<GeoChatMessage> chats:Vector<Chat> users:Vector<User> = geochats.Messages;
geochats.messagesSlice#bc5863e8 count:int messages:Vector<GeoChatMessage> chats:Vector<Chat> users:Vector<User> = 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<MessageEntity> = 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<int> = messages.AffectedMessages;
messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
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<MessageEntity> = 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<MessageEntity> = 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<int> random_id:Vector<long> = Updates;
messages.getChats#3c6aa187 id:Vector<int> = 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<InputUser> random_id:Vector<long> 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;

File diff suppressed because it is too large Load Diff

View File

@ -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 &current, 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<PhotoData*, CachedSize> 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<Link> urls;
};
typedef QMap<MsgId, CachedLink*> CachedLinks;
CachedLinks _links;
FlatInput _search;
IconedButton _cancelSearch;
QVector<MsgId> _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<QString, MTPmessages_Messages> SearchCache;
SearchCache _searchCache;
typedef QMap<mtpRequestId, QString> 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<CachedItem> CachedItems;
CachedItems _items;
int32 _width, _height, _minHeight, _addToY;
QTimer _linkTipTimer;
// selection support, like in HistoryWidget
Qt::CursorShape _cursor;
HistoryCursorState _cursorState;
typedef QMap<MsgId, uint32> 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);

View File

@ -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();
}

View File

@ -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

View File

@ -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));

View File

@ -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);

View File

@ -119,7 +119,7 @@ namespace {
};
typedef QMap<StorageKey, ToastImage> 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());

View File

@ -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;

View File

@ -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);

View File

@ -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();

View File

@ -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
};

View File

@ -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 {

View File

@ -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;
};

View File

@ -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 {

View File

@ -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;

View File

@ -275,6 +275,7 @@ enum DataBlockId {
dbiTryIPv6 = 0x28,
dbiSongVolume = 0x29,
dbiWindowsNotifications = 0x30,
dbiIncludeMuted = 0x31,
dbiEncryptedWithSalt = 333,
dbiEncrypted = 444,

View File

@ -11,7 +11,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.8.51</string>
<string>0.8.55</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>CFBundleSignature</key>

Binary file not shown.

View File

@ -1477,6 +1477,20 @@
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
</CustomBuild>
<CustomBuild Include="SourceFiles\gui\countrycodeinput.h">
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing countrycodeinput.h...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(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"</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Moc%27ing countrycodeinput.h...</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">Moc%27ing countrycodeinput.h...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(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"</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">"$(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"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
</CustomBuild>
<CustomBuild Include="SourceFiles\gui\phoneinput.h">
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing phoneinput.h...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
@ -2151,4 +2165,4 @@
<UserProperties UicDir=".\GeneratedFiles" MocDir=".\GeneratedFiles\$(ConfigurationName)" MocOptions="" RccDir=".\GeneratedFiles" lupdateOnBuild="1" lupdateOptions="" lreleaseOptions="" Qt5Version_x0020_Win32="$(DefaultQtVersion)" />
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>

View File

@ -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;

View File

@ -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

View File

@ -1,2 +1,2 @@
echo 0.8 8051 0.8.51 0
echo 0.8 8055 0.8.55 0
# AppVersionStrMajor AppVersion AppVersionStr DevChannel

View File

@ -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

View File

@ -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 <QtCore/QUrl>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <shlobj.h>
#ifndef Q_OS_WINCE
# include <intshcut.h>
#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<unsigned char*>(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<unsigned char*>(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