version 0.8.27.dev ready

This commit is contained in:
John Preston 2015-06-17 22:43:03 +03:00
parent 52ea153c31
commit c291bf0861
26 changed files with 480 additions and 155 deletions

View File

@ -1,9 +1,9 @@
@echo OFF
set "AppVersion=8026"
set "AppVersionStrSmall=0.8.26"
set "AppVersionStr=0.8.26"
set "AppVersionStrFull=0.8.26.0"
set "AppVersion=8027"
set "AppVersionStrSmall=0.8.27"
set "AppVersionStr=0.8.27"
set "AppVersionStrFull=0.8.27.0"
set "DevChannel=1"
if %DevChannel% neq 0 goto preparedev

View File

@ -1011,8 +1011,8 @@ recordSignalMin: 5px;
recordSignalMax: 10px;
recordCancel: #aaa;
recordCancelActive: #ec6466;
recordFont: font(16px);
recordTextTop: 12px;
recordFont: font(13px);
recordTextTop: 14px;
replySkip: 51px;
replyColor: #377aae;
@ -1679,7 +1679,7 @@ botKbColor: #8a8a8f;
botKbFont: font(16px);
botKbButton: botKeyboardButton {
margin: 10px;
padding: 14px;
padding: 10px;
height: 46px;
textTop: 13px;
downTextTop: 14px;

View File

@ -1977,12 +1977,15 @@ namespace App {
void feedReplyMarkup(MsgId msgId, const MTPReplyMarkup &markup) {
ReplyMarkup data;
ReplyMarkup::Commands &commands(data.commands);
switch (markup.type()) {
case mtpc_replyKeyboardMarkup: {
const MTPDreplyKeyboardMarkup &d(markup.c_replyKeyboardMarkup());
data.flags = d.vflags.v;
const QVector<MTPKeyboardButtonRow> &v(d.vrows.c_vector().v);
if (!v.isEmpty()) {
data.reserve(v.size());
commands.reserve(v.size());
for (int32 i = 0, l = v.size(); i < l; ++i) {
switch (v.at(i).type()) {
case mtpc_keyboardButtonRow: {
@ -1998,12 +2001,12 @@ namespace App {
} break;
}
}
if (!btns.isEmpty()) data.push_back(btns);
if (!btns.isEmpty()) commands.push_back(btns);
}
} break;
}
}
if (!data.isEmpty()) {
if (!commands.isEmpty()) {
replyMarkups.insert(msgId, data);
}
}
@ -2016,7 +2019,7 @@ namespace App {
}
const ReplyMarkup &replyMarkup(MsgId msgId) {
static ReplyMarkup zeroMarkup;
static ReplyMarkup zeroMarkup(MTPDreplyKeyboardMarkup_flag_ZERO);
ReplyMarkups::const_iterator i = replyMarkups.constFind(msgId);
if (i == replyMarkups.cend()) return zeroMarkup;
return i.value();
@ -2046,15 +2049,21 @@ namespace App {
}
}
void insertBotCommand(const QString &cmd) {
if (App::main()) {
App::main()->insertBotCommand(cmd);
}
}
void searchByHashtag(const QString &tag) {
if (App::main()) {
App::main()->searchMessages(tag + ' ');
}
}
void openUserByName(const QString &username, bool toProfile, const QString &start, const QString &startToken) {
void openUserByName(const QString &username, bool toProfile, const QString &startToken) {
if (App::main()) {
App::main()->openUserByName(username, toProfile, start, startToken);
App::main()->openUserByName(username, toProfile, startToken);
}
}

View File

@ -35,7 +35,13 @@ typedef QHash<VideoData*, HistoryItemsMap> VideoItems;
typedef QHash<AudioData*, HistoryItemsMap> AudioItems;
typedef QHash<DocumentData*, HistoryItemsMap> DocumentItems;
typedef QHash<WebPageData*, HistoryItemsMap> WebPageItems;
typedef QList<QList<QString> > ReplyMarkup;
struct ReplyMarkup {
ReplyMarkup(int32 flags = 0) : flags(flags) {
}
typedef QList<QList<QString> > Commands;
Commands commands;
int32 flags;
};
enum RoundCorners {
MaskCorners = 0x00, // for images
@ -234,8 +240,9 @@ namespace App {
void setProxySettings(QTcpSocket &socket);
void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
void insertBotCommand(const QString &cmd);
void searchByHashtag(const QString &tag);
void openUserByName(const QString &username, bool toProfile = false, const QString &start = QString(), const QString &startToken = QString());
void openUserByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
void joinGroupByHash(const QString &hash);
void stickersBox(const QString &name);
void openLocalUrl(const QString &url);

View File

@ -640,7 +640,7 @@ void Application::checkMapVersion() {
psRegisterCustomScheme();
if (Local::oldMapVersion()) {
QString versionFeatures;
if (DevChannel && Local::oldMapVersion() < 8026) {
if (DevChannel && Local::oldMapVersion() < 8027) {
versionFeatures = lang(lng_new_version_minor);// QString::fromUtf8("\xe2\x80\x94 IPv6 connections support\n\xe2\x80\x94 Bug fixes and minor stuff");// .replace('@', qsl("@") + QChar(0x200D));
} else if (!DevChannel && Local::oldMapVersion() < 8024) {
versionFeatures = lng_new_version_text(lt_blog_link, qsl("https://telegram.org/blog/bot-revolution"));// lang(lng_new_version_text).trimmed();

View File

@ -91,7 +91,15 @@ void ContactsInner::onPeerNameChanged(PeerData *peer, const PeerData::Names &old
}
void ContactsInner::onAddBot() {
App::main()->addParticipants(_addToChat, QVector<UserData*>(1, _bot));
if (_bot->botInfo && !_bot->botInfo->startGroupToken.isEmpty()) {
uint64 randomId = MTP::nonce<uint64>();
MTP::send(MTPmessages_StartBot(_bot->inputUser, MTP_int(App::chatFromPeer(_addToChat->id)), MTP_long(randomId), MTP_string(_bot->botInfo->startGroupToken)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, _bot));
App::wnd()->hideLayer();
App::main()->showPeer(_addToChat->id, 0, false);
} else {
App::main()->addParticipants(_addToChat, QVector<UserData*>(1, _bot));
}
}
void ContactsInner::peerUpdated(PeerData *peer) {
@ -738,7 +746,10 @@ ContactsInner::~ContactsInner() {
for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) {
delete *i;
}
if (_bot) delete _contacts;
if (_bot) {
delete _contacts;
if (_bot->botInfo) _bot->botInfo->startGroupToken = QString();
}
}
void ContactsInner::resizeEvent(QResizeEvent *e) {

View File

@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#pragma once
static const int32 AppVersion = 8026;
static const wchar_t *AppVersionStr = L"0.8.26";
static const int32 AppVersion = 8027;
static const wchar_t *AppVersionStr = L"0.8.27";
static const bool DevChannel = true;
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";

View File

@ -2411,7 +2411,7 @@ void MentionsInner::paintEvent(QPaintEvent *e) {
int32 atwidth = st::mentionFont->m.width('@'), hashwidth = st::mentionFont->m.width('#');
int32 availwidth = width() - 2 * st::mentionPadding.left() - st::mentionPhotoSize - 2 * st::mentionPadding.right();
int32 htagleft = st::btnAttachPhoto.width + st::taMsgField.textMrg.left() - st::dlgShadow, htagwidth = width() - st::mentionPadding.right() - htagleft;
int32 htagleft = st::btnAttachPhoto.width + st::taMsgField.textMrg.left() - st::dlgShadow, htagwidth = width() - st::mentionPadding.right() - htagleft - st::mentionScroll.width;
int32 from = qFloor(e->rect().top() / st::mentionHeight), to = qFloor(e->rect().bottom() / st::mentionHeight) + 1;
int32 last = _rows->isEmpty() ? (_hrows->isEmpty() ? _crows->size() : _hrows->size()) : _rows->size();

View File

@ -30,7 +30,7 @@ namespace {
const QRegularExpression _reMailStart(qsl("^[a-zA-Z\\-_\\.0-9]{1,256}\\@"));
const QRegularExpression _reHashtag(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])#[\\w]{2,64}([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption);
const QRegularExpression _reMention(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])@[A-Za-z_0-9]{5,32}([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption);
const QRegularExpression _reBotCommand(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])/[\\w]{1,64}(@[A-Za-z_0-9]{5,32})?([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption);
const QRegularExpression _reBotCommand(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])/[A-Za-z_0-9]{1,64}(@[A-Za-z_0-9]{5,32})?([\\W]|$)"));
QSet<int32> _validProtocols, _validTopDomains;
const style::textStyle *_textStyle = 0;
@ -757,7 +757,7 @@ void TextLink::onClick(Qt::MouseButton button) const {
start = (start == qsl("sg") ? qsl("startgroup") : (start == qsl("s") ? qsl("start") : QString()));
}
}
App::openUserByName(telegramMeUser.captured(1), start == qsl("startgroup"), start, startToken);
App::openUserByName(telegramMeUser.captured(1), start == qsl("startgroup"), startToken);
} else if (telegramMeGroup.hasMatch()) {
App::joinGroupByHash(telegramMeGroup.captured(1));
} else if (telegramMeStickers.hasMatch()) {
@ -784,7 +784,8 @@ void HashtagLink::onClick(Qt::MouseButton button) const {
void BotCommandLink::onClick(Qt::MouseButton button) const {
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
App::sendBotCommand(_cmd);
App::insertBotCommand(_cmd);
// App::sendBotCommand(_cmd);
}
}

View File

@ -310,6 +310,8 @@ History::History(const PeerId &peerId) : width(0), height(0)
, lastWidth(0)
, lastScrollTop(History::ScrollMax)
, mute(isNotifyMuted(peer->notify))
, lastKeyboardInited(false)
, lastKeyboardUsed(false)
, lastKeyboardId(0)
, lastKeyboardFrom(0)
, sendRequestId(0)
@ -814,11 +816,21 @@ HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem *
}
}
if (adding->hasReplyMarkup()) {
lastKeyboardId = adding->id;
lastKeyboardFrom = adding->from()->id;
} else if (lastKeyboardFrom == adding->from()->id) {
lastKeyboardId = 0;
lastKeyboardFrom = 0;
if (peer->chat) {
peer->asChat()->markupSenders.insert(adding->from(), true);
}
if (App::replyMarkup(adding->id).flags & MTPDreplyKeyboardMarkup_flag_ZERO) { // zero markup means replyKeyboardHide
if (lastKeyboardFrom == adding->from()->id || (!lastKeyboardInited && !peer->chat && !adding->out())) {
lastKeyboardInited = true;
lastKeyboardId = 0;
lastKeyboardFrom = 0;
}
} else {
lastKeyboardInited = true;
lastKeyboardId = adding->id;
lastKeyboardFrom = adding->from()->id;
lastKeyboardUsed = false;
}
}
}
return adding;
@ -923,12 +935,40 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
}
}
if (item->from()->id) {
if (lastAuthors && !lastAuthors->contains(item->from())) {
if (item->hasReplyMarkup() && !lastKeyboardId) {
if (lastAuthors) { // chats
if (!lastAuthors->contains(item->from())) {
lastAuthors->push_back(item->from());
}
if (!lastKeyboardInited && item->hasReplyMarkup() && !item->out()) { // chats with bots
bool wasKeyboardHide = peer->asChat()->markupSenders.contains(item->from());
if (!wasKeyboardHide) {
peer->asChat()->markupSenders.insert(item->from(), true);
}
if (!(App::replyMarkup(item->id).flags & MTPDreplyKeyboardMarkup_flag_ZERO)) {
if (!lastKeyboardInited) {
lastKeyboardInited = true;
if (wasKeyboardHide) {
lastKeyboardId = 0;
lastKeyboardFrom = 0;
} else {
lastKeyboardId = item->id;
lastKeyboardFrom = item->from()->id;
lastKeyboardUsed = false;
}
}
}
}
} else if (!lastKeyboardInited && item->hasReplyMarkup() && !item->out()) { // conversations with bots
lastKeyboardInited = true;
if (App::replyMarkup(item->id).flags & MTPDreplyKeyboardMarkup_flag_ZERO) {
lastKeyboardId = 0;
lastKeyboardFrom = 0;
} else {
lastKeyboardInited = true;
lastKeyboardId = item->id;
lastKeyboardFrom = item->from()->id;
lastKeyboardUsed = false;
}
lastAuthors->push_back(item->from());
}
}
}
@ -1286,13 +1326,19 @@ void History::clear(bool leaveItems) {
}
Parent::clear();
setMsgCount(0);
if (!leaveItems) {
if (leaveItems) {
lastKeyboardInited = false;
} else {
setUnreadCount(0);
lastMsg = 0;
}
height = 0;
oldLoaded = false;
if (peer->chat) peer->asChat()->lastAuthors.clear();
if (peer->chat) {
peer->asChat()->lastAuthors.clear();
peer->asChat()->markupSenders.clear();
}
if (leaveItems && App::main()) App::main()->historyCleared(this);
}
History::Parent::iterator History::erase(History::Parent::iterator i) {

View File

@ -251,6 +251,7 @@ struct History : public QList<HistoryBlock*> {
int32 lastWidth, lastScrollTop;
bool mute;
bool lastKeyboardInited, lastKeyboardUsed;
MsgId lastKeyboardId;
PeerId lastKeyboardFrom;

View File

@ -928,7 +928,7 @@ QString HistoryList::getSelectedText() const {
void HistoryList::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Escape) {
historyWidget->onClearSelected();
historyWidget->onListEscapePressed();
} else if (e == QKeySequence::Copy && !_selected.isEmpty()) {
copySelectedText();
} else if (e == QKeySequence::Delete) {
@ -1188,6 +1188,9 @@ void HistoryList::onUpdateSelected() {
App::hoveredItem(0);
}
}
if (_dragItem && _dragItem->detached()) {
dragActionCancel();
}
linkTipTimer.start(1000);
Qt::CursorShape cur = style::cur_default;
@ -1446,9 +1449,10 @@ void MessageField::focusInEvent(QFocusEvent *e) {
emit focused();
}
BotKeyboard::BotKeyboard() : _wasForMsgId(0),
BotKeyboard::BotKeyboard() : _wasForMsgId(0), _height(0), _maxOuterHeight(0), _maximizeSize(false), _singleUse(false),
_sel(-1), _down(-1), _hoverAnim(animFunc(this, &BotKeyboard::hoverStep)), _st(&st::botKbButton) {
setGeometry(0, 0, _st->margin, _st->margin);
_height = _st->margin;
setMouseTracking(true);
_cmdTipTimer.setSingleShot(true);
@ -1474,9 +1478,17 @@ void BotKeyboard::paintEvent(QPaintEvent *e) {
if (rtl()) rect.moveLeft(width() - rect.left() - rect.width());
int32 tx = rect.x(), tw = rect.width();
if (tw > st::botKbFont->elidew + _st->padding * 2) {
tx += _st->padding;
tw -= _st->padding * 2;
} else if (tw > st::botKbFont->elidew) {
tx += (tw - st::botKbFont->elidew) / 2;
tw = st::botKbFont->elidew;
}
if (_down == i * MatrixRowShift + j) {
App::roundRect(p, rect, st::botKbDownBg, BotKeyboardDownCorners);
btn.text.drawElided(p, rect.x(), rect.y() + _st->downTextTop, rect.width(), 1, style::al_top);
btn.text.drawElided(p, tx, rect.y() + _st->downTextTop + ((rect.height() - _st->height) / 2), tw, 1, style::al_top);
} else {
App::roundRect(p, rect, st::botKbBg, BotKeyboardCorners);
float64 hover = btn.hover;
@ -1485,7 +1497,7 @@ void BotKeyboard::paintEvent(QPaintEvent *e) {
App::roundRect(p, rect, st::botKbOverBg, BotKeyboardOverCorners);
p.setOpacity(1);
}
btn.text.drawElided(p, rect.x(), rect.y() + _st->textTop, rect.width(), 1, style::al_top);
btn.text.drawElided(p, tx, rect.y() + _st->textTop + ((rect.height() - _st->height) / 2), tw, 1, style::al_top);
}
}
if (j < s) break;
@ -1494,13 +1506,15 @@ void BotKeyboard::paintEvent(QPaintEvent *e) {
void BotKeyboard::resizeEvent(QResizeEvent *e) {
updateStyle();
int32 h = (_btns.size() + 1) * _st->margin + _btns.size() * _st->height;
if (height() != h) {
resize(width(), h);
_height = (_btns.size() + 1) * _st->margin + _btns.size() * _st->height;
if (_maximizeSize) _height = qMax(_height, _maxOuterHeight);
if (height() != _height) {
resize(width(), _height);
return;
}
int32 y = _st->margin;
float64 y = _st->margin, btnh = _btns.isEmpty() ? _st->height : (float64(_height - _st->margin) / _btns.size());
for (int32 i = 0, l = _btns.size(); i != l; ++i) {
int32 j = 0, s = _btns.at(i).size();
@ -1516,15 +1530,15 @@ void BotKeyboard::resizeEvent(QResizeEvent *e) {
float64 x = _st->margin, coef = widthForText / widthOfText;
for (j = 0; j != s; ++j) {
Button &btn(_btns[i][j]);
float64 tw = widthForText / float64(s)/*qMax(btn.text.maxWidth(), 1) * coef*/, w = 2 * _st->padding + tw;
float64 tw = widthForText / float64(s), w = 2 * _st->padding + tw;
if (w < _st->padding) w = _st->padding;
btn.rect = QRect(qRound(x), y, qRound(w), _st->height);
btn.rect = QRect(qRound(x), qRound(y), qRound(w), qRound(btnh - _st->margin));
x += w + _st->margin;
btn.full = tw >= btn.text.maxWidth();
}
y += _st->height + _st->margin;
y += btnh;
}
}
@ -1565,11 +1579,15 @@ bool BotKeyboard::updateMarkup(HistoryItem *to) {
clearSelection();
_btns.clear();
const ReplyMarkup &markup(App::replyMarkup(to->id));
if (!markup.isEmpty()) {
int32 i = 0, l = qMin(markup.size(), 32);
_maximizeSize = !(markup.flags & MTPDreplyKeyboardMarkup_flag_resize);
_singleUse = markup.flags & MTPDreplyKeyboardMarkup_flag_single_use;
const ReplyMarkup::Commands &commands(markup.commands);
if (!commands.isEmpty()) {
int32 i = 0, l = qMin(commands.size(), 32);
_btns.reserve(l);
for (; i != l; ++i) {
const QList<QString> &row(markup.at(i));
const QList<QString> &row(commands.at(i));
QList<Button> btns;
int32 j = 0, s = qMin(row.size(), 16);
btns.reserve(s);
@ -1580,9 +1598,10 @@ bool BotKeyboard::updateMarkup(HistoryItem *to) {
}
updateStyle();
int32 h = (_btns.size() + 1) * _st->margin + _btns.size() * _st->height;
if (height() != h) {
resize(width(), h);
_height = (_btns.size() + 1) * _st->margin + _btns.size() * _st->height;
if (_maximizeSize) _height = qMax(_height, _maxOuterHeight);
if (height() != _height) {
resize(width(), _height);
} else {
resizeEvent(0);
}
@ -1590,6 +1609,7 @@ bool BotKeyboard::updateMarkup(HistoryItem *to) {
return true;
}
if (_wasForMsgId) {
_maximizeSize = _singleUse = false;
_wasForMsgId = 0;
clearSelection();
_btns.clear();
@ -1619,15 +1639,26 @@ bool BotKeyboard::hoverStep(float64 ms) {
return !_animations.isEmpty();
}
void BotKeyboard::resizeToWidth(int32 width) {
void BotKeyboard::resizeToWidth(int32 width, int32 maxOuterHeight) {
updateStyle(width);
resize(width, (_btns.size() + 1) * _st->margin + _btns.size() * _st->height);
_height = (_btns.size() + 1) * _st->margin + _btns.size() * _st->height;
_maxOuterHeight = maxOuterHeight;
if (_maximizeSize) _height = qMax(_height, _maxOuterHeight);
resize(width, _height);
}
bool BotKeyboard::maximizeSize() const {
return _maximizeSize;
}
bool BotKeyboard::singleUse() const {
return _singleUse;
}
void BotKeyboard::updateStyle(int32 w) {
if (w < 0) w = width();
_st = &st::botKbButton;
bool tiny = false;
for (int32 i = 0, l = _btns.size(); i != l; ++i) {
int32 j = 0, s = _btns.at(i).size();
int32 widthLeft = w - (s * _st->margin + st::botKbScroll.width + s * 2 * _st->padding);
@ -1637,7 +1668,7 @@ void BotKeyboard::updateStyle(int32 w) {
widthLeft -= qMax(btn.text.maxWidth(), 1);
if (widthLeft < 0) break;
}
if (j != s) {
if (j != s && s > 3) {
_st = &st::botKbTinyButton;
break;
}
@ -1992,6 +2023,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
, _toHistoryEnd(this, st::historyToEnd)
, _attachMention(this)
, _send(this, lang(lng_send_button), st::btnSend)
, _botStart(this, lang(lng_bot_start), st::btnSend)
, _attachDocument(this, st::btnAttachDocument)
, _attachPhoto(this, st::btnAttachPhoto)
, _attachEmoji(this, st::btnAttachEmoji)
@ -2034,6 +2066,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(&_toHistoryEnd, SIGNAL(clicked()), this, SLOT(onHistoryToEnd()));
connect(&_replyForwardPreviewCancel, SIGNAL(clicked()), this, SLOT(onReplyForwardPreviewCancel()));
connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
connect(&_botStart, SIGNAL(clicked()), this, SLOT(onBotStart()));
connect(&_attachDocument, SIGNAL(clicked()), this, SLOT(onDocumentSelect()));
connect(&_attachPhoto, SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
connect(&_field, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
@ -2093,6 +2126,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
_field.hide();
_field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width(), _send.height() - 2 * st::sendPadding);
_send.hide();
_botStart.hide();
_attachDocument.hide();
_attachPhoto.hide();
@ -2229,7 +2263,7 @@ void HistoryWidget::activate() {
}
}
if (_list) {
if (_selCount || _recording) {
if (_selCount || _recording || !_botStart.isHidden()) {
_list->setFocus();
} else {
_field.setFocus();
@ -2606,6 +2640,11 @@ void HistoryWidget::showPeer(const PeerId &peer, MsgId msgId, bool force, bool l
_list = 0;
updateTopBarSelection();
if (_activeHist && _activeHist->peer->id != peer && (!leaveActive || _activeHist != hist)) {
if (!_activeHist->peer->chat && _activeHist->peer->asUser()->botInfo) {
_activeHist->peer->asUser()->botInfo->startToken = QString();
}
}
if (leaveActive && hist) {
_activeHist = hist;
} else {
@ -2614,6 +2653,9 @@ void HistoryWidget::showPeer(const PeerId &peer, MsgId msgId, bool force, bool l
}
if (hist) {
App::main()->dlgUpdated(hist);
if (!hist->peer->chat && hist->peer->asUser()->botInfo) {
hist->peer->asUser()->botInfo->startToken = QString();
}
}
}
histPeer = peer ? App::peer(peer) : 0;
@ -2743,6 +2785,7 @@ void HistoryWidget::updateControlsVisibility() {
_scroll.hide();
_kbScroll.hide();
_send.hide();
_botStart.hide();
_toHistoryEnd.hide();
_attachMention.hide();
_field.hide();
@ -2765,66 +2808,85 @@ void HistoryWidget::updateControlsVisibility() {
}
if (!histPeer->chat || !histPeer->asChat()->forbidden) {
checkMentionDropdown();
if (cHasAudioCapture() && _field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) {
bool botStart = !histPeer->chat && histPeer->asUser()->botInfo && (!histPeer->asUser()->botInfo->startToken.isEmpty() || hist->isEmpty() && !hist->lastMsg);
if (botStart) {
if (_botStart.isHidden()) {
_botStart.clearState();
_botStart.show();
}
_send.hide();
setMouseTracking(true);
mouseMoveEvent(0);
} else {
_send.show();
setMouseTracking(false);
_recordAnim.stop();
_inRecord = _inField = false;
a_recordOver = anim::fvalue(0, 0);
}
if (_recording) {
_field.hide();
_attachEmoji.hide();
_kbShow.hide();
_kbHide.hide();
_attachDocument.hide();
_attachPhoto.hide();
if (_kbShown) {
_kbScroll.show();
} else {
_kbScroll.hide();
}
_kbScroll.hide();
_replyForwardPreviewCancel.hide();
} else {
_field.show();
if (_kbShown) {
_kbScroll.show();
_attachEmoji.hide();
_kbHide.show();
_kbShow.hide();
_botStart.hide();
if (cHasAudioCapture() && _field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) {
_send.hide();
setMouseTracking(true);
mouseMoveEvent(0);
} else {
_kbScroll.hide();
_attachEmoji.show();
_send.show();
setMouseTracking(false);
_recordAnim.stop();
_inRecord = _inField = false;
a_recordOver = anim::fvalue(0, 0);
}
if (_recording) {
_field.hide();
_attachEmoji.hide();
_kbShow.hide();
_kbHide.hide();
if (_keyboard.hasMarkup()) {
_kbShow.show();
_attachDocument.hide();
_attachPhoto.hide();
if (_kbShown) {
_kbScroll.show();
} else {
_kbScroll.hide();
}
} else {
_field.show();
if (_kbShown) {
_kbScroll.show();
_attachEmoji.hide();
_kbHide.show();
_kbShow.hide();
} else {
_kbScroll.hide();
_attachEmoji.show();
_kbHide.hide();
if (_keyboard.hasMarkup()) {
_kbShow.show();
} else {
_kbShow.hide();
}
}
if (cDefaultAttach() == dbidaPhoto) {
_attachDocument.hide();
_attachPhoto.show();
} else {
_attachDocument.show();
_attachPhoto.hide();
}
}
if (cDefaultAttach() == dbidaPhoto) {
_attachDocument.hide();
_attachPhoto.show();
if ((_replyToId || App::main()->hasForwardingItems() || (_previewData && _previewData->pendingTill >= 0))) {
if (_replyForwardPreviewCancel.isHidden()) {
_replyForwardPreviewCancel.show();
resizeEvent(0);
update();
}
} else {
_attachDocument.show();
_attachPhoto.hide();
_replyForwardPreviewCancel.hide();
}
}
if ((_replyToId || App::main()->hasForwardingItems() || (_previewData && _previewData->pendingTill >= 0))) {
if (_replyForwardPreviewCancel.isHidden()) {
_replyForwardPreviewCancel.show();
resizeEvent(0);
update();
}
} else {
_replyForwardPreviewCancel.hide();
}
} else {
_attachMention.hide();
_send.hide();
_botStart.hide();
_attachDocument.hide();
_attachPhoto.hide();
_attachEmoji.hide();
@ -2849,6 +2911,7 @@ void HistoryWidget::updateControlsVisibility() {
_kbScroll.hide();
_attachMention.hide();
_send.hide();
_botStart.hide();
_attachDocument.hide();
_attachPhoto.hide();
_attachEmoji.hide();
@ -2902,6 +2965,12 @@ void HistoryWidget::historyWasRead(bool force) {
App::main()->readServerHistory(hist, force);
}
void HistoryWidget::historyCleared(History *history) {
if (history == hist) {
_list->dragActionCancel();
}
}
bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
@ -3214,6 +3283,22 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
_field.setFocus();
}
void HistoryWidget::onBotStart() {
if (histPeer->chat || !histPeer->asUser()->botInfo) {
updateControlsVisibility();
return;
}
QString token = histPeer->asUser()->botInfo->startToken;
if (token.isEmpty()) {
sendBotCommand(qsl("/start"), 0);
} else {
uint64 randomId = MTP::nonce<uint64>();
MTP::send(MTPmessages_StartBot(histPeer->asUser()->inputUser, MTP_int(0), MTP_long(randomId), MTP_string(token)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, histPeer->asUser()));
histPeer->asUser()->botInfo->startToken = QString();
}
}
void HistoryWidget::onShareContact(const PeerId &peer, UserData *contact) {
if (!contact || contact->phone.isEmpty()) return;
@ -3295,6 +3380,7 @@ void HistoryWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTo
_field.hide();
_replyForwardPreviewCancel.hide();
_send.hide();
_botStart.hide();
a_coord = back ? anim::ivalue(-st::introSlideShift, 0) : anim::ivalue(st::introSlideShift, 0);
a_alpha = anim::fvalue(0, 1);
a_bgCoord = back ? anim::ivalue(0, st::introSlideShift) : anim::ivalue(0, -st::introSlideShift);
@ -3350,7 +3436,7 @@ void HistoryWidget::animStop() {
bool HistoryWidget::recordStep(float64 ms) {
float64 dt = ms / st::btnSend.duration;
bool res = true;
if (dt >= 1 || !_send.isHidden()) {
if (dt >= 1 || !_send.isHidden() || !_botStart.isHidden()) {
res = false;
a_recordOver.finish();
a_recordDown.finish();
@ -3532,7 +3618,38 @@ void HistoryWidget::sendBotCommand(const QString &cmd, MsgId replyTo) { // reply
int32 botStatus = histPeer->chat ? histPeer->asChat()->botStatus : -1;
App::main()->sendPreparedText(hist, cmd, replyTo ? ((histPeer->chat && (botStatus == 0 || botStatus == 2)) ? replyTo : -1) : 0);
if (replyTo) cancelReply();
if (replyTo) {
cancelReply();
if (_keyboard.hasMarkup() && _keyboard.singleUse() && _keyboard.forMsgId() == replyTo) {
if (_kbShown) onKbToggle(false);
hist->lastKeyboardUsed = true;
}
}
}
void HistoryWidget::insertBotCommand(const QString &cmd) {
if (!hist) return;
QString toInsert = cmd;
UserData *bot = histPeer->chat ? (App::hoveredLinkItem() ? (App::hoveredLinkItem()->toHistoryForwarded() ? App::hoveredLinkItem()->toHistoryForwarded()->fromForwarded() : App::hoveredLinkItem()->from()) : 0) : histPeer->asUser();
QString username = (bot && bot->botInfo) ? bot->username : QString();
if (cmd.indexOf('@') < 2 && !username.isEmpty()) {
toInsert += '@' + username;
}
toInsert += ' ';
QString text = _field.getLastText();
QRegularExpressionMatch m = QRegularExpression(qsl("^/[A-Za-z_0-9]{0,64}(@[A-Za-z_0-9]{0,32})?(\\s|$)")).match(text);
if (m.hasMatch()) {
text = toInsert + text.mid(m.capturedLength());
} else {
text = toInsert + text;
}
_field.setText(text);
QTextCursor cur(_field.textCursor());
cur.movePosition(QTextCursor::End);
_field.setTextCursor(cur);
}
DragState HistoryWidget::getDragState(const QMimeData *d) {
@ -3621,22 +3738,25 @@ void HistoryWidget::onDocumentDrop(QDropEvent *e) {
uploadMedias(files, ToPrepareDocument);
}
void HistoryWidget::onKbToggle() {
void HistoryWidget::onKbToggle(bool manual) {
if (_kbShown) {
_kbHide.hide();
_kbShow.show();
_kbScroll.hide();
_kbShown = false;
_kbReplyTo = 0;
_kbWasHidden = true;
if (manual) _kbWasHidden = true;
} else {
_kbHide.show();
_kbShow.hide();
_kbScroll.show();
_kbShown = true;
_kbReplyTo = hist->peer->chat ? App::histItemById(_keyboard.forMsgId()) : 0;
if (_kbReplyTo && !_replyToId) _replyToText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
_kbWasHidden = false;
if (_kbReplyTo && !_replyToId) {
updateReplyToName();
_replyToText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
}
if (manual) _kbWasHidden = false;
}
resizeEvent(0);
if (_kbHide.isHidden()) {
@ -3801,9 +3921,12 @@ void HistoryWidget::updateOnlineDisplayTimer() {
}
void HistoryWidget::onFieldResize() {
int32 maxKeyboardHeight = int(st::maxFieldHeight) - _field.height();
_keyboard.resizeToWidth(width(), maxKeyboardHeight);
int32 kbh = 0;
if (_kbShown) {
kbh = qMin(_keyboard.height(), int(st::maxFieldHeight) - _field.height());
kbh = qMin(_keyboard.height(), maxKeyboardHeight);
_kbScroll.setGeometry(0, height() - kbh, width(), kbh);
}
_field.move(_attachDocument.x() + _attachDocument.width(), height() - kbh - _field.height() - st::sendPadding);
@ -3811,6 +3934,7 @@ void HistoryWidget::onFieldResize() {
_attachDocument.move(0, height() - kbh - _attachDocument.height());
_attachPhoto.move(_attachDocument.x(), _attachDocument.y());
_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
_send.move(width() - _send.width(), _attachDocument.y());
_attachEmoji.move(_send.x() - _attachEmoji.width(), height() - kbh - _attachEmoji.height());
_kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height());
@ -4160,11 +4284,12 @@ void HistoryWidget::msgUpdated(PeerId peer, const HistoryItem *msg) {
}
void HistoryWidget::resizeEvent(QResizeEvent *e) {
_keyboard.resizeToWidth(width());
int32 maxKeyboardHeight = int(st::maxFieldHeight) - _field.height();
_keyboard.resizeToWidth(width(), maxKeyboardHeight);
int32 kbh = 0;
if (_kbShown) {
kbh = qMin(_keyboard.height(), int(st::maxFieldHeight) - _field.height());
kbh = qMin(_keyboard.height(), maxKeyboardHeight);
_kbScroll.setGeometry(0, height() - kbh, width(), kbh);
}
_field.move(_attachDocument.x() + _attachDocument.width(), height() - kbh - _field.height() - st::sendPadding);
@ -4180,6 +4305,7 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
_toHistoryEnd.move((width() - _toHistoryEnd.width()) / 2, _scroll.y() + _scroll.height() - _toHistoryEnd.height() - st::historyToEndSkip);
_send.move(width() - _send.width(), _attachDocument.y());
_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
_attachEmoji.move(_send.x() - _attachEmoji.width(), height() - kbh - _attachEmoji.height());
_kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height());
_kbHide.move(_attachEmoji.x(), _attachEmoji.y());
@ -4248,12 +4374,19 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown,
return; // scrollTopMax etc are not working after recountHeight()
}
int32 newScrollHeight = height() - (hist->readyForWork() && (!histPeer->chat || !histPeer->asChat()->forbidden) ? (_field.height() + 2 * st::sendPadding) : 0);
if (_replyToId || _kbReplyTo || App::main()->hasForwardingItems() || (_previewData && _previewData->pendingTill >= 0)) {
newScrollHeight -= st::replyHeight;
}
if (_kbShown) {
newScrollHeight -= _kbScroll.height();
int32 newScrollHeight = height();
if (_botStart.isHidden()) {
if (hist->readyForWork() && (!histPeer->chat || !histPeer->asChat()->forbidden)) {
newScrollHeight -= (_field.height() + 2 * st::sendPadding);
}
if (_replyToId || _kbReplyTo || App::main()->hasForwardingItems() || (_previewData && _previewData->pendingTill >= 0)) {
newScrollHeight -= st::replyHeight;
}
if (_kbShown) {
newScrollHeight -= _kbScroll.height();
}
} else {
newScrollHeight -= _botStart.height();
}
bool wasAtBottom = _scroll.scrollTop() + 1 > _scroll.scrollTopMax(), needResize = _scroll.width() != width() || _scroll.height() != newScrollHeight;
if (needResize) {
@ -4354,7 +4487,8 @@ void HistoryWidget::updateBotKeyboard() {
if (!changed) return;
if (_keyboard.hasMarkup()) {
if (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden)) {
if (_keyboard.singleUse() && _keyboard.forMsgId() == hist->lastKeyboardId && hist->lastKeyboardUsed) _kbWasHidden = true;
if (_botStart.isHidden() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) {
if (!_showAnim.animating()) {
_kbScroll.show();
_attachEmoji.hide();
@ -4365,7 +4499,10 @@ void HistoryWidget::updateBotKeyboard() {
_field.setMaxHeight(st::maxFieldHeight - maxh);
_kbShown = true;
_kbReplyTo = hist->peer->chat ? App::histItemById(_keyboard.forMsgId()) : 0;
if (_kbReplyTo && !_replyToId) _replyToText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
if (_kbReplyTo && !_replyToId) {
updateReplyToName();
_replyToText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
}
} else {
if (!_showAnim.animating()) {
_kbScroll.hide();
@ -4781,6 +4918,14 @@ void HistoryWidget::onDeleteContextSure() {
App::wnd()->hideLayer();
}
void HistoryWidget::onListEscapePressed() {
if (_selCount && _list) {
onClearSelected();
} else {
onCancel();
}
}
void HistoryWidget::onClearSelected() {
if (_list) _list->clearSelectedItems();
}
@ -4818,7 +4963,7 @@ void HistoryWidget::updateTopBarSelection() {
updateControlsVisibility();
updateListSize();
if (!App::wnd()->layerShown() && !App::passcoded()) {
if (_selCount || _recording) {
if (_selCount || _recording || !_botStart.isHidden()) {
_list->setFocus();
} else {
_field.setFocus();

View File

@ -216,7 +216,10 @@ public:
bool hasMarkup() const;
bool hoverStep(float64 ms);
void resizeToWidth(int32 width);
void resizeToWidth(int32 width, int32 maxOuterHeight);
bool maximizeSize() const;
bool singleUse() const;
MsgId forMsgId() const {
return _wasForMsgId;
@ -233,6 +236,8 @@ private:
void clearSelection();
MsgId _wasForMsgId;
int32 _height, _maxOuterHeight;
bool _maximizeSize, _singleUse;
QTimer _cmdTipTimer;
QPoint _lastMousePos;
@ -364,6 +369,7 @@ public:
void newUnreadMsg(History *history, HistoryItem *item);
void historyToDown(History *history);
void historyWasRead(bool force = true);
void historyCleared(History *history);
QRect historyRect() const;
@ -441,7 +447,10 @@ public:
bool recordingStep(float64 ms);
void stopRecording(bool send);
void onListEscapePressed();
void sendBotCommand(const QString &cmd, MsgId replyTo);
void insertBotCommand(const QString &cmd);
~HistoryWidget();
@ -481,13 +490,14 @@ public slots:
void onListScroll();
void onHistoryToEnd();
void onSend(bool ctrlShiftEnter = false, MsgId replyTo = -1);
void onBotStart();
void onPhotoSelect();
void onDocumentSelect();
void onPhotoDrop(QDropEvent *e);
void onDocumentDrop(QDropEvent *e);
void onKbToggle();
void onKbToggle(bool manual = true);
void onPhotoReady();
void onSendConfirmed();
@ -597,7 +607,7 @@ private:
MentionsDropdown _attachMention;
FlatButton _send;
FlatButton _send, _botStart;
IconedButton _attachDocument, _attachPhoto, _attachEmoji, _kbShow, _kbHide;
MessageField _field;
Animation _recordAnim, _recordingAnim;

View File

@ -26,6 +26,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include "mainwidget.h"
#include "boxes/confirmbox.h"
#include "boxes/stickersetbox.h"
#include "boxes/contactsbox.h"
#include "localstorage.h"
@ -973,6 +974,7 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl
void MainWidget::sendMessage(History *hist, const QString &text, MsgId replyTo) {
readServerHistory(hist, false);
hist->loadAround(0);
if (history.peer())
sendPreparedText(hist, history.prepareMessage(text), replyTo);
}
@ -1026,6 +1028,10 @@ void MainWidget::sendBotCommand(const QString &cmd, MsgId replyTo) {
history.sendBotCommand(cmd, replyTo);
}
void MainWidget::insertBotCommand(const QString &cmd) {
history.insertBotCommand(cmd);
}
void MainWidget::searchMessages(const QString &query) {
App::wnd()->hideMediaview();
dialogs.searchMessages(query);
@ -1779,6 +1785,7 @@ void MainWidget::showPeer(quint64 peerId, qint32 msgId, bool back, bool force) {
if (profile || overview) {
if (profile) {
profile->hide();
profile->clear();
profile->deleteLater();
profile->rpcInvalidate();
profile = 0;
@ -1902,6 +1909,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
}
if (profile) {
profile->hide();
profile->clear();
profile->deleteLater();
profile->rpcInvalidate();
profile = 0;
@ -1949,6 +1957,7 @@ void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop,
}
if (profile) {
profile->hide();
profile->clear();
profile->deleteLater();
profile->rpcInvalidate();
}
@ -2073,6 +2082,10 @@ void MainWidget::historyWasRead() {
history.historyWasRead(false);
}
void MainWidget::historyCleared(History *hist) {
history.historyCleared(hist);
}
void MainWidget::animShow(const QPixmap &bgAnimCache, bool back) {
_bgAnimCache = bgAnimCache;
@ -2536,7 +2549,7 @@ void MainWidget::openLocalUrl(const QString &url) {
QRegularExpressionMatch m = QRegularExpression(qsl("^tg://resolve/?\\?domain=([a-zA-Z0-9\\.\\_]+)(&(start|startgroup)=([a-zA-Z0-9\\.\\_\\-]+))?(&|$)"), QRegularExpression::CaseInsensitiveOption).match(u);
if (m.hasMatch()) {
QString start = m.captured(3), startToken = m.captured(4);
openUserByName(m.captured(1), (start == qsl("startgroup")), start, startToken);
openUserByName(m.captured(1), (start == qsl("startgroup")), startToken);
}
} else if (u.startsWith(QLatin1String("tg://join"), Qt::CaseInsensitive)) {
QRegularExpressionMatch m = QRegularExpression(qsl("^tg://join/?\\?invite=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"), QRegularExpression::CaseInsensitiveOption).match(u);
@ -2551,18 +2564,24 @@ void MainWidget::openLocalUrl(const QString &url) {
}
}
void MainWidget::openUserByName(const QString &username, bool toProfile, const QString &start, const QString &startToken) {
void MainWidget::openUserByName(const QString &username, bool toProfile, const QString &startToken) {
App::wnd()->hideMediaview();
UserData *user = App::userByName(username);
if (user) {
if (toProfile) {
showPeerProfile(user);
if (user->botInfo && !user->botInfo->cantJoinGroups && !startToken.isEmpty()) {
user->botInfo->startGroupToken = startToken;
App::wnd()->showLayer(new ContactsBox(user));
} else {
showPeerProfile(user);
}
} else {
if (user->botInfo) user->botInfo->startToken = startToken;
emit showPeerAsync(user->id, 0, false, true);
}
} else {
MTP::send(MTPcontacts_ResolveUsername(MTP_string(username)), rpcDone(&MainWidget::usernameResolveDone, toProfile), rpcFail(&MainWidget::usernameResolveFail, username));
MTP::send(MTPcontacts_ResolveUsername(MTP_string(username)), rpcDone(&MainWidget::usernameResolveDone, qMakePair(toProfile, startToken)), rpcFail(&MainWidget::usernameResolveFail, username));
}
}
@ -2583,13 +2602,19 @@ void MainWidget::onStickersInstalled(uint64 setId) {
history.stickersInstalled(setId);
}
void MainWidget::usernameResolveDone(bool toProfile, const MTPUser &user) {
void MainWidget::usernameResolveDone(QPair<bool, QString> toProfileStartToken, const MTPUser &result) {
App::wnd()->hideLayer();
UserData *u = App::feedUsers(MTP_vector<MTPUser>(1, user));
if (toProfile) {
showPeerProfile(u);
UserData *user = App::feedUsers(MTP_vector<MTPUser>(1, result));
if (toProfileStartToken.first) {
if (user->botInfo && !user->botInfo->cantJoinGroups && !toProfileStartToken.second.isEmpty()) {
user->botInfo->startGroupToken = toProfileStartToken.second;
App::wnd()->showLayer(new ContactsBox(user));
} else {
showPeerProfile(user);
}
} else {
showPeer(u->id, 0, false, true);
if (user->botInfo) user->botInfo->startToken = toProfileStartToken.second;
showPeer(user->id, 0, false, true);
}
}

View File

@ -187,7 +187,7 @@ public:
void start(const MTPUser &user);
void openLocalUrl(const QString &str);
void openUserByName(const QString &name, bool toProfile = false, const QString &start = QString(), const QString &startToken = QString());
void openUserByName(const QString &name, bool toProfile = false, const QString &startToken = QString());
void joinGroupByHash(const QString &hash);
void stickersBox(const MTPInputStickerSet &set);
@ -216,6 +216,7 @@ public:
void dialogsToUp();
void newUnreadMsg(History *history, HistoryItem *item);
void historyWasRead();
void historyCleared(History *history);
void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg);
void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg);
@ -297,6 +298,7 @@ public:
void stopAnimActive();
void sendBotCommand(const QString &cmd, MsgId msgId);
void insertBotCommand(const QString &cmd);
void searchMessages(const QString &query);
void preloadOverviews(PeerData *peer);
@ -450,7 +452,7 @@ private:
void handleUpdates(const MTPUpdates &updates);
bool updateFail(const RPCError &e);
void usernameResolveDone(bool toProfile, const MTPUser &user);
void usernameResolveDone(QPair<bool, QString> toProfileStartToken, const MTPUser &result);
bool usernameResolveFail(QString name, const RPCError &error);
void inviteCheckDone(QString hash, const MTPChatInvite &invite);

View File

@ -38,6 +38,10 @@ enum {
MTPDuser_flag_bot = (1 << 14),
MTPDuser_flag_bot_reads_all = (1 << 15),
MTPDuser_flag_bot_cant_join = (1 << 16),
MTPDreplyKeyboardMarkup_flag_resize = (1 << 0),
MTPDreplyKeyboardMarkup_flag_single_use = (1 << 1),
MTPDreplyKeyboardMarkup_flag_ZERO = (1 << 31) // client side flag for zeroMarkup
};
static const MTPReplyMarkup MTPnullMarkup = MTP_replyKeyboardMarkup(MTP_int(0), MTP_vector<MTPKeyboardButtonRow>(0));

View File

@ -2332,6 +2332,10 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
to.add("{ inputMessagesFilterAudio }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_inputMessagesFilterAudioDocuments:
to.add("{ inputMessagesFilterAudioDocuments }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_updateNewMessage:
if (stage) {
to.add(",\n").addSpaces(lev);
@ -4343,6 +4347,10 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_replyKeyboardHide:
to.add("{ replyKeyboardHide }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_replyKeyboardMarkup:
if (stage) {
to.add(",\n").addSpaces(lev);

View File

@ -199,6 +199,7 @@ enum {
mtpc_inputMessagesFilterPhotoVideoDocuments = 0xd95e73bb,
mtpc_inputMessagesFilterDocument = 0x9eddf188,
mtpc_inputMessagesFilterAudio = 0xcfc87522,
mtpc_inputMessagesFilterAudioDocuments = 0x5afbf764,
mtpc_updateNewMessage = 0x1f2b0afd,
mtpc_updateMessageID = 0x4e90bfd6,
mtpc_updateDeleteMessages = 0xa20db0e5,
@ -384,6 +385,7 @@ enum {
mtpc_botInfo = 0x9cf585d,
mtpc_keyboardButton = 0xa2fa4880,
mtpc_keyboardButtonRow = 0x77608b83,
mtpc_replyKeyboardHide = 0xced6ebbc,
mtpc_replyKeyboardMarkup = 0x3502758c,
mtpc_invokeAfterMsg = 0xcb9f372d,
mtpc_invokeAfterMsgs = 0x3dc4b4f0,
@ -4923,6 +4925,7 @@ private:
friend MTPmessagesFilter MTP_inputMessagesFilterPhotoVideoDocuments();
friend MTPmessagesFilter MTP_inputMessagesFilterDocument();
friend MTPmessagesFilter MTP_inputMessagesFilterAudio();
friend MTPmessagesFilter MTP_inputMessagesFilterAudioDocuments();
mtpTypeId _type;
};
@ -7981,32 +7984,39 @@ typedef MTPBoxed<MTPkeyboardButtonRow> MTPKeyboardButtonRow;
class MTPreplyMarkup : private mtpDataOwner {
public:
MTPreplyMarkup();
MTPreplyMarkup(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_replyKeyboardMarkup) : mtpDataOwner(0) {
MTPreplyMarkup() : mtpDataOwner(0), _type(0) {
}
MTPreplyMarkup(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) {
read(from, end, cons);
}
MTPDreplyKeyboardMarkup &_replyKeyboardMarkup() {
if (!data) throw mtpErrorUninitialized();
if (_type != mtpc_replyKeyboardMarkup) throw mtpErrorWrongTypeId(_type, mtpc_replyKeyboardMarkup);
split();
return *(MTPDreplyKeyboardMarkup*)data;
}
const MTPDreplyKeyboardMarkup &c_replyKeyboardMarkup() const {
if (!data) throw mtpErrorUninitialized();
if (_type != mtpc_replyKeyboardMarkup) throw mtpErrorWrongTypeId(_type, mtpc_replyKeyboardMarkup);
return *(const MTPDreplyKeyboardMarkup*)data;
}
uint32 innerLength() const;
mtpTypeId type() const;
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_replyKeyboardMarkup);
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons);
void write(mtpBuffer &to) const;
typedef void ResponseType;
private:
explicit MTPreplyMarkup(mtpTypeId type);
explicit MTPreplyMarkup(MTPDreplyKeyboardMarkup *_data);
friend MTPreplyMarkup MTP_replyKeyboardHide();
friend MTPreplyMarkup MTP_replyKeyboardMarkup(MTPint _flags, const MTPVector<MTPKeyboardButtonRow> &_rows);
mtpTypeId _type;
};
typedef MTPBoxed<MTPreplyMarkup> MTPReplyMarkup;
@ -21786,6 +21796,7 @@ inline void MTPmessagesFilter::read(const mtpPrime *&from, const mtpPrime *end,
case mtpc_inputMessagesFilterPhotoVideoDocuments: _type = cons; break;
case mtpc_inputMessagesFilterDocument: _type = cons; break;
case mtpc_inputMessagesFilterAudio: _type = cons; break;
case mtpc_inputMessagesFilterAudioDocuments: _type = cons; break;
default: throw mtpErrorUnexpected(cons, "MTPmessagesFilter");
}
}
@ -21802,6 +21813,7 @@ inline MTPmessagesFilter::MTPmessagesFilter(mtpTypeId type) : _type(type) {
case mtpc_inputMessagesFilterPhotoVideoDocuments: break;
case mtpc_inputMessagesFilterDocument: break;
case mtpc_inputMessagesFilterAudio: break;
case mtpc_inputMessagesFilterAudioDocuments: break;
default: throw mtpErrorBadTypeId(type, "MTPmessagesFilter");
}
}
@ -21826,6 +21838,9 @@ inline MTPmessagesFilter MTP_inputMessagesFilterDocument() {
inline MTPmessagesFilter MTP_inputMessagesFilterAudio() {
return MTPmessagesFilter(mtpc_inputMessagesFilterAudio);
}
inline MTPmessagesFilter MTP_inputMessagesFilterAudioDocuments() {
return MTPmessagesFilter(mtpc_inputMessagesFilterAudioDocuments);
}
inline uint32 MTPupdate::innerLength() const {
switch (_type) {
@ -25914,30 +25929,52 @@ inline MTPkeyboardButtonRow MTP_keyboardButtonRow(const MTPVector<MTPKeyboardBut
return MTPkeyboardButtonRow(new MTPDkeyboardButtonRow(_buttons));
}
inline MTPreplyMarkup::MTPreplyMarkup() : mtpDataOwner(new MTPDreplyKeyboardMarkup()) {
}
inline uint32 MTPreplyMarkup::innerLength() const {
const MTPDreplyKeyboardMarkup &v(c_replyKeyboardMarkup());
return v.vflags.innerLength() + v.vrows.innerLength();
switch (_type) {
case mtpc_replyKeyboardMarkup: {
const MTPDreplyKeyboardMarkup &v(c_replyKeyboardMarkup());
return v.vflags.innerLength() + v.vrows.innerLength();
}
}
return 0;
}
inline mtpTypeId MTPreplyMarkup::type() const {
return mtpc_replyKeyboardMarkup;
if (!_type) throw mtpErrorUninitialized();
return _type;
}
inline void MTPreplyMarkup::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
if (cons != mtpc_replyKeyboardMarkup) throw mtpErrorUnexpected(cons, "MTPreplyMarkup");
if (!data) setData(new MTPDreplyKeyboardMarkup());
MTPDreplyKeyboardMarkup &v(_replyKeyboardMarkup());
v.vflags.read(from, end);
v.vrows.read(from, end);
if (cons != _type) setData(0);
switch (cons) {
case mtpc_replyKeyboardHide: _type = cons; break;
case mtpc_replyKeyboardMarkup: _type = cons; {
if (!data) setData(new MTPDreplyKeyboardMarkup());
MTPDreplyKeyboardMarkup &v(_replyKeyboardMarkup());
v.vflags.read(from, end);
v.vrows.read(from, end);
} break;
default: throw mtpErrorUnexpected(cons, "MTPreplyMarkup");
}
}
inline void MTPreplyMarkup::write(mtpBuffer &to) const {
const MTPDreplyKeyboardMarkup &v(c_replyKeyboardMarkup());
v.vflags.write(to);
v.vrows.write(to);
switch (_type) {
case mtpc_replyKeyboardMarkup: {
const MTPDreplyKeyboardMarkup &v(c_replyKeyboardMarkup());
v.vflags.write(to);
v.vrows.write(to);
} break;
}
}
inline MTPreplyMarkup::MTPreplyMarkup(MTPDreplyKeyboardMarkup *_data) : mtpDataOwner(_data) {
inline MTPreplyMarkup::MTPreplyMarkup(mtpTypeId type) : mtpDataOwner(0), _type(type) {
switch (type) {
case mtpc_replyKeyboardHide: break;
case mtpc_replyKeyboardMarkup: setData(new MTPDreplyKeyboardMarkup()); break;
default: throw mtpErrorBadTypeId(type, "MTPreplyMarkup");
}
}
inline MTPreplyMarkup::MTPreplyMarkup(MTPDreplyKeyboardMarkup *_data) : mtpDataOwner(_data), _type(mtpc_replyKeyboardMarkup) {
}
inline MTPreplyMarkup MTP_replyKeyboardHide() {
return MTPreplyMarkup(mtpc_replyKeyboardHide);
}
inline MTPreplyMarkup MTP_replyKeyboardMarkup(MTPint _flags, const MTPVector<MTPKeyboardButtonRow> &_rows) {
return MTPreplyMarkup(new MTPDreplyKeyboardMarkup(_flags, _rows));

View File

@ -324,6 +324,7 @@ inputMessagesFilterPhotoVideo#56e9f0e4 = MessagesFilter;
inputMessagesFilterPhotoVideoDocuments#d95e73bb = MessagesFilter;
inputMessagesFilterDocument#9eddf188 = MessagesFilter;
inputMessagesFilterAudio#cfc87522 = MessagesFilter;
inputMessagesFilterAudioDocuments#5afbf764 = MessagesFilter;
updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
updateMessageID#4e90bfd6 id:int random_id:long = Update;
@ -602,6 +603,7 @@ keyboardButton#a2fa4880 text:string = KeyboardButton;
keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
replyKeyboardHide#ced6ebbc = ReplyMarkup;
replyKeyboardMarkup#3502758c flags:# rows:Vector<KeyboardButtonRow> = ReplyMarkup;
---functions---

View File

@ -469,6 +469,9 @@ void ProfileInner::reorderParticipants() {
}
}
void ProfileInner::start() {
}
bool ProfileInner::event(QEvent *e) {
if (e->type() == QEvent::MouseMove) {
_lastPos = static_cast<QMouseEvent*>(e)->globalPos();
@ -1220,6 +1223,7 @@ bool ProfileWidget::animStep(float64 ms) {
_bgAnimCache = _animCache = _animTopBarCache = _bgAnimTopBarCache = QPixmap();
App::main()->topBar()->stopAnim();
_scroll.show();
_inner.start();
activate();
} else {
a_bgCoord.update(dt1, st::introHideFunc);
@ -1249,6 +1253,12 @@ void ProfileWidget::mediaOverviewUpdated(PeerData *peer) {
_inner.mediaOverviewUpdated(peer);
}
void ProfileWidget::clear() {
if (_inner.peer() && !_inner.peer()->chat && _inner.peer()->asUser()->botInfo) {
_inner.peer()->asUser()->botInfo->startGroupToken = QString();
}
}
ProfileWidget::~ProfileWidget() {
}

View File

@ -25,6 +25,8 @@ public:
ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const PeerData *peer);
void start();
bool event(QEvent *e);
void paintEvent(QPaintEvent *e);
void mouseMoveEvent(QMouseEvent *e);
@ -200,6 +202,7 @@ public:
void updateNotifySettings();
void mediaOverviewUpdated(PeerData *peer);
void clear();
~ProfileWidget();
public slots:

View File

@ -132,6 +132,8 @@ struct BotInfo {
QString shareText, description;
QList<BotCommand> commands;
Text text; // description
QString startToken, startGroupToken;
};
struct PhotoData;
@ -180,6 +182,8 @@ struct ChatData : public PeerData {
CanKick cankick;
typedef QList<UserData*> LastAuthors;
LastAuthors lastAuthors;
typedef QMap<UserData*, bool> MarkupSenders;
MarkupSenders markupSenders;
int32 botStatus; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
ImagePtr photoFull;
PhotoId photoId;

View File

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

Binary file not shown.

View File

@ -1701,7 +1701,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.26;
CURRENT_PROJECT_VERSION = 0.8.27;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
@ -1719,7 +1719,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 0.8.26;
CURRENT_PROJECT_VERSION = 0.8.27;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_OPTIMIZATION_LEVEL = fast;
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
@ -1745,10 +1745,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.26;
CURRENT_PROJECT_VERSION = 0.8.27;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 0.8;
DYLIB_CURRENT_VERSION = 0.8.26;
DYLIB_CURRENT_VERSION = 0.8.27;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@ -1888,10 +1888,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.26;
CURRENT_PROJECT_VERSION = 0.8.27;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 0.8;
DYLIB_CURRENT_VERSION = 0.8.26;
DYLIB_CURRENT_VERSION = 0.8.27;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;

View File

@ -1,2 +1,2 @@
echo 8026 0.8.26 1
echo 8027 0.8.27 1
# AppVersion AppVersionStr DevChannel