version 0.8.30 with bots support and forward-by-dragndrop

This commit is contained in:
John Preston 2015-06-24 20:24:48 +03:00
parent 780d00bd8c
commit 793a2ec90c
26 changed files with 396 additions and 111 deletions

View file

@ -1,10 +1,10 @@
@echo OFF
set "AppVersion=8029"
set "AppVersionStrSmall=0.8.29"
set "AppVersionStr=0.8.29"
set "AppVersionStrFull=0.8.29.0"
set "DevChannel=1"
set "AppVersion=8030"
set "AppVersionStrSmall=0.8.30"
set "AppVersionStr=0.8.30"
set "AppVersionStrFull=0.8.30.0"
set "DevChannel=0"
if %DevChannel% neq 0 goto preparedev

View file

@ -993,15 +993,21 @@ btnAttachEmoji: iconedButton(btnAttachDocument) {
width: 33px;
}
btnBotKbShow: iconedButton(btnAttachEmoji) {
icon: sprite(375px, 74px, 21px, 16px);
iconPos: point(6px, 16px);
downIcon: sprite(375px, 74px, 21px, 16px);
downIconPos: point(6px, 16px);
icon: sprite(375px, 74px, 21px, 21px);
iconPos: point(6px, 12px);
downIcon: sprite(375px, 74px, 21px, 21px);
downIconPos: point(6px, 12px);
}
btnBotCmdStart: iconedButton(btnAttachEmoji) {
icon: sprite(354px, 74px, 21px, 21px);
iconPos: point(6px, 12px);
downIcon: sprite(354px, 74px, 21px, 21px);
downIconPos: point(6px, 12px);
}
btnBotKbHide: iconedButton(btnAttachEmoji) {
icon: sprite(352px, 74px, 23px, 14px);
icon: sprite(373px, 95px, 23px, 14px);
iconPos: point(5px, 17px);
downIcon: sprite(352px, 74px, 23px, 14px);
downIcon: sprite(373px, 95px, 23px, 14px);
downIconPos: point(5px, 17px);
}
btnRecordAudio: sprite(363px, 366px, 16px, 24px);

View file

@ -312,7 +312,11 @@ namespace App {
return lng_status_lastseen_date(lt_date, dOnline.date().toString(qsl("dd.MM.yy")));
}
bool onlineColorUse(int32 online, int32 now) {
bool onlineColorUse(UserData *user, int32 now) {
if (isServiceUser(user->id) || user->botInfo) {
return false;
}
int32 online = user->onlineTill;
if (online <= 0) {
switch (online) {
case 0:

View file

@ -105,7 +105,7 @@ namespace App {
int32 onlineForSort(UserData *user, int32 now);
int32 onlineWillChangeIn(UserData *user, int32 nowOnServer);
QString onlineText(UserData *user, int32 nowOnServer, bool precise = false);
bool onlineColorUse(int32 online, int32 now);
bool onlineColorUse(UserData *user, int32 now);
UserData *feedUsers(const MTPVector<MTPUser> &users); // returns last user
ChatData *feedChats(const MTPVector<MTPChat> &chats); // returns last chat

View file

@ -642,7 +642,7 @@ void Application::checkMapVersion() {
QString versionFeatures;
if (DevChannel && Local::oldMapVersion() < 8029) {
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) {
} else if (!DevChannel && Local::oldMapVersion() < 8030) {
versionFeatures = lng_new_version_text(lt_blog_link, qsl("https://telegram.org/blog/bot-revolution"));// lang(lng_new_version_text).trimmed();
}
if (!versionFeatures.isEmpty()) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

After

Width:  |  Height:  |  Size: 220 KiB

View file

@ -249,7 +249,7 @@ void ContactsInner::paintDialog(QPainter &p, PeerData *peer, ContactData *data,
} else {
if (data->inchat || data->check) {
p.setPen(st::white->p);
} else if (user && (uname || App::onlineColorUse(user->onlineTill, _time))) {
} else if (user && (uname || App::onlineColorUse(user, _time))) {
p.setPen(st::profileOnlineColor->p);
} else {
p.setPen(st::profileOfflineColor->p);

View file

@ -235,7 +235,6 @@ void StickerSetBox::onAddStickers() {
void StickerSetBox::onShareStickers() {
QString url = qsl("https://telegram.me/addstickers/") + _inner.shortName();
DEBUG_LOG(("Setting text to clipboard from stickerset box: %1").arg(url));
QApplication::clipboard()->setText(url);
App::wnd()->showLayer(new ConfirmBox(lang(lng_stickers_copied), true), true);
}

View file

@ -17,9 +17,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#pragma once
static const int32 AppVersion = 8029;
static const wchar_t *AppVersionStr = L"0.8.29";
static const bool DevChannel = true;
static const int32 AppVersion = 8030;
static const wchar_t *AppVersionStr = L"0.8.30";
static const bool DevChannel = false;
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
static const wchar_t *AppName = L"Telegram Desktop";

View file

@ -680,6 +680,26 @@ void DialogsListWidget::itemReplaced(HistoryItem *oldItem, HistoryItem *newItem)
}
}
PeerData *DialogsListWidget::updateFromParentDrag(QPoint globalPos) {
lastMousePos = globalPos;
selByMouse = true;
onUpdateSelected(true);
update();
if (_state == DefaultState) {
if (sel) return sel->history->peer;
} else if (_state == FilteredState || _state == SearchedState) {
if (filteredSel >= 0 && filteredSel < filterResults.size()) {
return filterResults[filteredSel]->history->peer;
} else if (peopleSel >= 0 && peopleSel < peopleResults.size()) {
return peopleResults[peopleSel];
} else if (searchedSel >= 0 && searchedSel < searchResults.size()) {
return searchResults[searchedSel]->_item->history()->peer;
}
}
return 0;
}
void DialogsListWidget::itemRemoved(HistoryItem *item) {
int wasCount = searchResults.size();
for (int i = 0; i < searchResults.size();) {
@ -1356,6 +1376,8 @@ MsgId DialogsListWidget::lastSearchId() const {
DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent)
, _drawShadow(true)
, _dragInScroll(false)
, _dragForward(false)
, dlgOffset(0)
, dlgCount(-1)
, dlgPreloading(0)
@ -1388,6 +1410,8 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent)
connect(&_newGroup, SIGNAL(clicked()), this, SLOT(onNewGroup()));
connect(&_cancelSearch, SIGNAL(clicked()), this, SLOT(onCancelSearch()));
setAcceptDrops(true);
_searchTimer.setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages()));
@ -1741,6 +1765,69 @@ bool DialogsWidget::addNewContact(int32 uid, bool show) {
return true;
}
void DialogsWidget::dragEnterEvent(QDragEnterEvent *e) {
if (App::main()->selectingPeer()) return;
_dragInScroll = false;
_dragForward = cWideMode() && e->mimeData()->hasFormat(qsl("application/x-td-forward-selected"));
if (_dragForward) {
e->setDropAction(Qt::CopyAction);
e->accept();
updateDragInScroll(scroll.geometry().contains(e->pos()));
} else if (false && App::main() && App::main()->getDragState(e->mimeData()) != DragStateNone) {
e->setDropAction(Qt::CopyAction);
e->accept();
}
}
void DialogsWidget::dragMoveEvent(QDragMoveEvent *e) {
if (scroll.geometry().contains(e->pos())) {
if (_dragForward) updateDragInScroll(true);
PeerData *p = list.updateFromParentDrag(mapToGlobal(e->pos()));
if (p) {
e->setDropAction(Qt::CopyAction);
} else {
e->setDropAction(Qt::IgnoreAction);
}
} else {
if (_dragForward) updateDragInScroll(false);
list.leaveEvent(0);
e->setDropAction(Qt::IgnoreAction);
}
e->accept();
}
void DialogsWidget::dragLeaveEvent(QDragLeaveEvent *e) {
if (_dragForward) updateDragInScroll(false);
list.leaveEvent(0);
e->accept();
}
void DialogsWidget::updateDragInScroll(bool inScroll) {
if (_dragInScroll != inScroll) {
_dragInScroll = inScroll;
if (_dragInScroll) {
App::main()->forwardLayer(1);
} else {
App::main()->dialogsCancelled();
}
}
}
void DialogsWidget::dropEvent(QDropEvent *e) {
if (scroll.geometry().contains(e->pos())) {
PeerData *p = list.updateFromParentDrag(mapToGlobal(e->pos()));
if (p) {
e->acceptProposedAction();
if (e->mimeData()->hasFormat(qsl("application/x-td-forward-selected"))) {
App::main()->onForward(p->id, true);
} else {
App::main()->showPeer(p->id, 0, false, true);
}
}
}
}
void DialogsWidget::onListScroll() {
// if (!App::self()) return;

View file

@ -98,6 +98,8 @@ public:
void itemRemoved(HistoryItem *item);
void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem);
PeerData *updateFromParentDrag(QPoint globalPos);
~DialogsListWidget();
public slots:
@ -171,6 +173,12 @@ public:
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req);
bool addNewContact(int32 uid, bool show = true);
void dragEnterEvent(QDragEnterEvent *e);
void dragMoveEvent(QDragMoveEvent *e);
void dragLeaveEvent(QDragLeaveEvent *e);
void dropEvent(QDropEvent *e);
void updateDragInScroll(bool inScroll);
void resizeEvent(QResizeEvent *e);
void keyPressEvent(QKeyEvent *e);
void paintEvent(QPaintEvent *e);
@ -232,6 +240,8 @@ private:
bool _drawShadow;
bool _dragInScroll, _dragForward;
void unreadCountsReceived(const QVector<MTPDialog> &dialogs);
bool dialogsFailed(const RPCError &error);
bool contactsFailed(const RPCError &error);

View file

@ -2425,7 +2425,8 @@ void MentionsInner::paintEvent(QPaintEvent *e) {
QPainter p(this);
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 mentionleft = 2 * st::mentionPadding.left() + st::mentionPhotoSize;
int32 mentionwidth = width() - mentionleft - 2 * st::mentionPadding.right();
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;
@ -2445,9 +2446,9 @@ void MentionsInner::paintEvent(QPaintEvent *e) {
UserData *user = _rows->at(i);
QString first = (_parent->filter().size() < 2) ? QString() : ('@' + user->username.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('@' + user->username) : user->username.mid(_parent->filter().size() - 1);
int32 firstwidth = st::mentionFont->m.width(first), secondwidth = st::mentionFont->m.width(second), unamewidth = firstwidth + secondwidth, namewidth = user->nameText.maxWidth();
if (availwidth < unamewidth + namewidth) {
namewidth = (availwidth * namewidth) / (namewidth + unamewidth);
unamewidth = availwidth - namewidth;
if (mentionwidth < unamewidth + namewidth) {
namewidth = (mentionwidth * namewidth) / (namewidth + unamewidth);
unamewidth = mentionwidth - namewidth;
if (firstwidth < unamewidth + st::mentionFont->elidew) {
if (firstwidth < unamewidth) {
first = st::mentionFont->m.elidedText(first, Qt::ElideRight, unamewidth);
@ -2465,10 +2466,10 @@ void MentionsInner::paintEvent(QPaintEvent *e) {
p.setFont(st::mentionFont->f);
p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p);
p.drawText(2 * st::mentionPadding.left() + st::mentionPhotoSize + namewidth + st::mentionPadding.right(), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
p.drawText(mentionleft + namewidth + st::mentionPadding.right(), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
if (!second.isEmpty()) {
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
p.drawText(2 * st::mentionPadding.left() + st::mentionPhotoSize + namewidth + st::mentionPadding.right() + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
p.drawText(mentionleft + namewidth + st::mentionPadding.right() + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
}
} else if (!_hrows->isEmpty()) {
QString hrow = _hrows->at(i);
@ -2501,30 +2502,30 @@ void MentionsInner::paintEvent(QPaintEvent *e) {
if (hasUsername || botStatus == 0 || botStatus == 2) {
toHighlight += '@' + user->username;
}
if (_parent->chat() || botStatus == 0 || botStatus == 2) {
if (true || _parent->chat() || botStatus == 0 || botStatus == 2) {
user->photo->load();
p.drawPixmap(st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), user->photo->pixRounded(st::mentionPhotoSize));
}
int32 addleft = 0, widthleft = htagwidth;
int32 addleft = 0, widthleft = mentionwidth;
QString first = (_parent->filter().size() < 2) ? QString() : ('/' + toHighlight.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('/' + toHighlight) : toHighlight.mid(_parent->filter().size() - 1);
int32 firstwidth = st::mentionFont->m.width(first), secondwidth = st::mentionFont->m.width(second);
if (htagwidth < firstwidth + secondwidth) {
if (htagwidth < firstwidth + st::mentionFont->elidew) {
first = st::mentionFont->m.elidedText(first + second, Qt::ElideRight, htagwidth);
if (widthleft < firstwidth + secondwidth) {
if (widthleft < firstwidth + st::mentionFont->elidew) {
first = st::mentionFont->m.elidedText(first + second, Qt::ElideRight, widthleft);
second = QString();
} else {
second = st::mentionFont->m.elidedText(second, Qt::ElideRight, htagwidth - firstwidth);
second = st::mentionFont->m.elidedText(second, Qt::ElideRight, widthleft - firstwidth);
}
}
p.setFont(st::mentionFont->f);
if (!first.isEmpty()) {
p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p);
p.drawText(htagleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
p.drawText(mentionleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
}
if (!second.isEmpty()) {
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
p.drawText(htagleft + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
p.drawText(mentionleft + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
}
addleft += firstwidth + secondwidth + st::mentionPadding.left();
widthleft -= firstwidth + secondwidth + st::mentionPadding.left();
@ -2538,7 +2539,7 @@ void MentionsInner::paintEvent(QPaintEvent *e) {
descwidth = st::mentionFont->m.width(description);
}
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
p.drawText(htagleft + addleft + (widthleft - descwidth), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, description);
p.drawText(mentionleft + addleft + (widthleft - descwidth), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, description);
}
}
}

View file

@ -289,7 +289,7 @@ public:
QString encoded() const {
QUrl u(_url), good(u.isValid() ? u.toEncoded() : QString());
QString result(good.isValid() ? good.toEncoded() : _url);
QString result(good.isValid() ? QString::fromUtf8(good.toEncoded()) : _url);
if (!QRegularExpression(qsl("^[a-zA-Z]+://")).match(result).hasMatch()) { // no protocol
return qsl("http://") + result;

View file

@ -326,6 +326,12 @@ History::History(const PeerId &peerId) : width(0), height(0)
}
}
void History::clearLastKeyboard() {
lastKeyboardInited = true;
lastKeyboardId = 0;
lastKeyboardFrom = 0;
}
void History::updateNameText() {
nameText.setText(st::msgNameFont, peer->nameOrPhone.isEmpty() ? peer->name : peer->nameOrPhone, _textNameOptions);
}
@ -632,9 +638,7 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPmessage &msg, boo
case mtpc_messageActionChatDeleteUser: {
const MTPDmessageActionChatDeleteUser &d(action.c_messageActionChatDeleteUser());
if (lastKeyboardFrom == App::peerFromUser(d.vuser_id)) {
lastKeyboardInited = true;
lastKeyboardId = 0;
lastKeyboardFrom = 0;
clearLastKeyboard();
}
// App::peer(App::peerFromUser(d.vuser_id)); left
} break;
@ -828,14 +832,10 @@ HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem *
}
if (markupFlags & MTPDreplyKeyboardMarkup_flag_ZERO) { // zero markup means replyKeyboardHide
if (lastKeyboardFrom == adding->from()->id || (!lastKeyboardInited && !peer->chat && !adding->out())) {
lastKeyboardInited = true;
lastKeyboardId = 0;
lastKeyboardFrom = 0;
clearLastKeyboard();
}
} else if (peer->chat && (peer->asChat()->count < 1 || !peer->asChat()->participants.isEmpty()) && !peer->asChat()->participants.contains(adding->from())) {
lastKeyboardInited = true;
lastKeyboardId = 0;
lastKeyboardFrom = 0;
clearLastKeyboard();
} else {
lastKeyboardInited = true;
lastKeyboardId = adding->id;
@ -960,11 +960,10 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
}
if (!(markupFlags & MTPDreplyKeyboardMarkup_flag_ZERO)) {
if (!lastKeyboardInited) {
lastKeyboardInited = true;
if (wasKeyboardHide || ((peer->asChat()->count < 1 || !peer->asChat()->participants.isEmpty()) && !peer->asChat()->participants.contains(item->from()))) {
lastKeyboardId = 0;
lastKeyboardFrom = 0;
clearLastKeyboard();
} else {
lastKeyboardInited = true;
lastKeyboardId = item->id;
lastKeyboardFrom = item->from()->id;
lastKeyboardUsed = false;
@ -976,10 +975,8 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
} else if (!lastKeyboardInited && item->hasReplyMarkup() && !item->out()) { // conversations with bots
int32 markupFlags = App::replyMarkup(item->id).flags;
if (!(markupFlags & MTPDreplyKeyboardMarkup_flag_personal) || item->notifyByFrom()) {
lastKeyboardInited = true;
if (markupFlags & MTPDreplyKeyboardMarkup_flag_ZERO) {
lastKeyboardId = 0;
lastKeyboardFrom = 0;
clearLastKeyboard();
} else {
lastKeyboardInited = true;
lastKeyboardId = item->id;

View file

@ -254,6 +254,7 @@ struct History : public QList<HistoryBlock*> {
bool lastKeyboardInited, lastKeyboardUsed;
MsgId lastKeyboardId;
PeerId lastKeyboardFrom;
void clearLastKeyboard();
mtpRequestId sendRequestId;

View file

@ -51,6 +51,7 @@ HistoryList::HistoryList(HistoryWidget *historyWidget, ScrollArea *scroll, Histo
, _dragSelFrom(0)
, _dragSelTo(0)
, _dragSelecting(false)
, _wasSelectedText(false)
, _touchScroll(false)
, _touchSelect(false)
, _touchInProgress(false)
@ -482,6 +483,7 @@ void HistoryList::dragActionCancel() {
_dragAction = NoDrag;
_dragStartPos = QPoint(0, 0);
_dragSelFrom = _dragSelTo = 0;
_wasSelectedText = false;
historyWidget->noSelectingScroll();
}
@ -542,6 +544,9 @@ void HistoryList::dragActionFinish(const QPoint &screenPos, Qt::MouseButton butt
updateMsg(App::pressedItem());
App::pressedItem(0);
}
_wasSelectedText = false;
if (needClick) {
DEBUG_LOG(("Clicked link: %1 (%2) %3").arg(needClick->text()).arg(needClick->readable()).arg(needClick->encoded()));
needClick->onClick(button);
@ -573,6 +578,7 @@ void HistoryList::dragActionFinish(const QPoint &screenPos, Qt::MouseButton butt
} else if (_dragAction == Selecting) {
if (_dragSelFrom && _dragSelTo) {
applyDragSelection();
_dragSelFrom = _dragSelTo = 0;
} else if (!_selected.isEmpty() && !_dragWasInactive) {
uint32 sel = _selected.cbegin().value();
if (sel != FullItemSel && (sel & 0xFFFF) == ((sel >> 16) & 0xFFFF)) {
@ -595,6 +601,8 @@ void HistoryList::mouseReleaseEvent(QMouseEvent *e) {
}
void HistoryList::mouseDoubleClickEvent(QMouseEvent *e) {
if (!hist) return;
if (((_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) || (_dragAction == NoDrag && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel))) && _dragSelType == TextSelectLetters && _dragItem) {
bool afterDragSymbol, uponSelected;
uint16 symbol;
@ -610,7 +618,7 @@ void HistoryList::mouseDoubleClickEvent(QMouseEvent *e) {
_selected.clear();
}
_selected.insert(_dragItem, selStatus);
}
}
mouseMoveEvent(e);
_trippleClickPoint = e->globalPos();
@ -800,8 +808,9 @@ void HistoryList::onMenuDestroy(QObject *obj) {
void HistoryList::copySelectedText() {
QString sel = getSelectedText();
DEBUG_LOG(("Setting selected text to clipboard: %1").arg(sel));
QApplication::clipboard()->setText(sel);
if (!sel.isEmpty()) {
QApplication::clipboard()->setText(sel);
}
}
void HistoryList::openContextUrl() {
@ -814,7 +823,6 @@ void HistoryList::openContextUrl() {
void HistoryList::copyContextUrl() {
QString enc = _contextMenuLnk->encoded();
if (!enc.isEmpty()) {
DEBUG_LOG(("Setting text to clipboard from context url: %1").arg(enc));
QApplication::clipboard()->setText(enc);
}
}
@ -888,7 +896,6 @@ void HistoryList::copyContextText() {
QString contextMenuText = item->selectedText(FullItemSel);
if (!contextMenuText.isEmpty()) {
DEBUG_LOG(("Setting text to clipboard from context menu: %1").arg(contextMenuText));
QApplication::clipboard()->setText(contextMenuText);
}
}
@ -898,15 +905,21 @@ void HistoryList::resizeEvent(QResizeEvent *e) {
}
QString HistoryList::getSelectedText() const {
if (_selected.isEmpty()) return QString();
if (_selected.cbegin().value() != FullItemSel) {
return _selected.cbegin().key()->selectedText(_selected.cbegin().value());
SelectedItems sel = _selected;
if (_dragAction == Selecting && _dragSelFrom && _dragSelTo) {
applyDragSelection(&sel);
}
if (sel.isEmpty()) return QString();
if (sel.cbegin().value() != FullItemSel) {
return sel.cbegin().key()->selectedText(sel.cbegin().value());
}
int32 fullSize = 0;
QString timeFormat(qsl(", [dd.MM.yy hh:mm]\n"));
QMap<int32, QString> texts;
for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) {
for (SelectedItems::const_iterator i = sel.cbegin(), e = sel.cend(); i != e; ++i) {
HistoryItem *item = i.key();
QString text, sel = item->selectedText(FullItemSel), time = item->date.toString(timeFormat);
int32 size = item->from()->name.size() + time.size() + sel.size();
@ -999,6 +1012,10 @@ void HistoryList::updateBotInfo(bool recount) {
}
}
bool HistoryList::wasSelectedText() const {
return _wasSelectedText;
}
void HistoryList::updateSize() {
int32 ph = scrollArea->height(), minadd = 0;
ySkip = ph - (hist->height + st::historyPadding);
@ -1236,6 +1253,61 @@ void HistoryList::onUpdateSelected() {
if (item != _dragItem || (m - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()) {
if (_dragAction == PrepareDrag) {
_dragAction = Dragging;
bool uponSelected = false;
if (_dragItem) {
bool afterDragSymbol;
uint16 symbol;
if (!_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) {
uponSelected = _selected.contains(_dragItem);
} else {
_dragItem->getSymbol(symbol, afterDragSymbol, uponSelected, _dragStartPos.x(), _dragStartPos.y());
if (uponSelected) {
if (_selected.isEmpty() ||
_selected.cbegin().value() == FullItemSel ||
_selected.cbegin().key() != _dragItem
) {
uponSelected = false;
} else {
uint16 selFrom = (_selected.cbegin().value() >> 16) & 0xFFFF, selTo = _selected.cbegin().value() & 0xFFFF;
if (symbol < selFrom || symbol >= selTo) {
uponSelected = false;
}
}
}
}
}
QString sel;
QList<QUrl> urls;
if (uponSelected) {
sel = getSelectedText();
} else if (textlnkDown()) {
sel = textlnkDown()->encoded();
if (!sel.isEmpty() && sel.at(0) != '/' && sel.at(0) != '@' && sel.at(0) != '#') {
urls.push_back(QUrl::fromEncoded(sel.toUtf8()));
}
}
if (!sel.isEmpty()) {
updateDragSelection(0, 0, false);
historyWidget->noSelectingScroll();
QDrag *drag = new QDrag(App::wnd());
QMimeData *mimeData = new QMimeData;
mimeData->setText(sel);
if (!urls.isEmpty()) mimeData->setUrls(urls);
if (uponSelected && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && cWideMode()) {
QStringList ids;
ids.reserve(_selected.size());
for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) {
ids.push_back(QString::number(i.key()->id, 16));
}
mimeData->setData(qsl("application/x-td-forward-selected"), "1");
}
drag->setMimeData(mimeData);
drag->exec();
return;
}
} else if (_dragAction == PrepareSelect) {
_dragAction = Selecting;
}
@ -1247,7 +1319,12 @@ void HistoryList::onUpdateSelected() {
uint16 second;
_dragItem->getSymbol(second, afterSymbol, uponSymbol, m.x(), m.y());
if (afterSymbol && _dragSelType == TextSelectLetters) ++second;
_selected[_dragItem] = _dragItem->adjustSelection(qMin(second, _dragSymbol), qMax(second, _dragSymbol), _dragSelType);
uint32 selState = _dragItem->adjustSelection(qMin(second, _dragSymbol), qMax(second, _dragSymbol), _dragSelType);
_selected[_dragItem] = selState;
if (!_wasSelectedText && (selState == FullItemSel || (selState & 0xFFFF) != ((selState >> 16) & 0xFFFF))) {
_wasSelectedText = true;
setFocus();
}
updateDragSelection(0, 0, false);
} else {
bool selectingDown = (_dragItem->block()->y < item->block()->y) || ((_dragItem->block() == item->block()) && (_dragItem->y < item->y || (_dragItem == item && _dragStartPos.y() < m.y())));
@ -1316,6 +1393,10 @@ void HistoryList::updateDragSelection(HistoryItem *dragSelFrom, HistoryItem *dra
qSwap(_dragSelFrom, _dragSelTo);
}
_dragSelecting = dragSelecting;
if (!_wasSelectedText && _dragSelFrom && _dragSelTo && _dragSelecting) {
_wasSelectedText = true;
setFocus();
}
force = true;
}
if (!force) return;
@ -1324,9 +1405,14 @@ void HistoryList::updateDragSelection(HistoryItem *dragSelFrom, HistoryItem *dra
}
void HistoryList::applyDragSelection() {
if (!_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) {
_selected.clear();
applyDragSelection(&_selected);
}
void HistoryList::applyDragSelection(SelectedItems *toItems) const {
if (!toItems->isEmpty() && toItems->cbegin().value() != FullItemSel) {
toItems->clear();
}
int32 fromy = _dragSelFrom->y + _dragSelFrom->block()->y, toy = _dragSelTo->y + _dragSelTo->block()->y + _dragSelTo->height();
if (_dragSelecting) {
int32 fromblock = hist->indexOf(_dragSelFrom->block()), fromitem = _dragSelFrom->block()->indexOf(_dragSelFrom);
@ -1336,35 +1422,34 @@ void HistoryList::applyDragSelection() {
HistoryBlock *block = (*hist)[fromblock];
for (int32 cnt = (fromblock < toblock) ? block->size() : (toitem + 1); fromitem < cnt; ++fromitem) {
HistoryItem *item = (*block)[fromitem];
SelectedItems::iterator i = _selected.find(item);
SelectedItems::iterator i = toItems->find(item);
if (item->id > 0 && !item->serviceMsg()) {
if (i == _selected.cend()) {
if (_selected.size() >= MaxSelectedItems) break;
_selected.insert(item, FullItemSel);
if (i == toItems->cend()) {
if (toItems->size() >= MaxSelectedItems) break;
toItems->insert(item, FullItemSel);
} else if (i.value() != FullItemSel) {
*i = FullItemSel;
}
} else {
if (i != _selected.cend()) {
_selected.erase(i);
if (i != toItems->cend()) {
toItems->erase(i);
}
}
}
if (_selected.size() >= MaxSelectedItems) break;
if (toItems->size() >= MaxSelectedItems) break;
fromitem = 0;
}
}
} else {
for (SelectedItems::iterator i = _selected.begin(); i != _selected.cend(); ) {
for (SelectedItems::iterator i = toItems->begin(); i != toItems->cend();) {
int32 iy = i.key()->y + i.key()->block()->y;
if (iy >= fromy && iy < toy) {
i = _selected.erase(i);
i = toItems->erase(i);
} else {
++i;
}
}
}
_dragSelFrom = _dragSelTo = 0;
}
void HistoryList::showLinkTip() {
@ -1579,9 +1664,9 @@ bool BotKeyboard::updateMarkup(HistoryItem *to) {
clearSelection();
_btns.clear();
const ReplyMarkup &markup(App::replyMarkup(to->id));
_forceReply = markup.flags | MTPDreplyKeyboardMarkup_flag_FORCE_REPLY;
_forceReply = markup.flags & MTPDreplyKeyboardMarkup_flag_FORCE_REPLY;
_maximizeSize = !(markup.flags & MTPDreplyKeyboardMarkup_flag_resize);
_singleUse = markup.flags & MTPDreplyKeyboardMarkup_flag_single_use;
_singleUse = _forceReply || (markup.flags & MTPDreplyKeyboardMarkup_flag_single_use);
const ReplyMarkup::Commands &commands(markup.commands);
if (!commands.isEmpty()) {
@ -2034,6 +2119,8 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
, _attachEmoji(this, st::btnAttachEmoji)
, _kbShow(this, st::btnBotKbShow)
, _kbHide(this, st::btnBotKbHide)
, _cmdStart(this, st::btnBotCmdStart)
, _cmdStartShown(false)
, _field(this, st::taMsgField, lang(lng_message_ph))
, _recordAnim(animFunc(this, &HistoryWidget::recordStep))
, _recordingAnim(animFunc(this, &HistoryWidget::recordingStep))
@ -2126,7 +2213,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
_toHistoryEnd.installEventFilter(this);
_attachMention.hide();
connect(&_attachMention, SIGNAL(chosen(QString)), &_field, SLOT(onMentionHashtagOrBotCommandInsert(QString)));
connect(&_attachMention, SIGNAL(chosen(QString)), this, SLOT(onMentionHashtagOrBotCommandInsert(QString)));
_field.installEventFilter(&_attachMention);
_field.hide();
@ -2139,6 +2226,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
_attachEmoji.hide();
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachDocument.installEventFilter(&_attachType);
_attachPhoto.installEventFilter(&_attachType);
@ -2146,6 +2234,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(&_kbShow, SIGNAL(clicked()), this, SLOT(onKbToggle()));
connect(&_kbHide, SIGNAL(clicked()), this, SLOT(onKbToggle()));
connect(&_cmdStart, SIGNAL(clicked()), this, SLOT(onCmdStart()));
connect(_attachType.addButton(new IconedButton(this, st::dropdownAttachDocument, lang(lng_attach_file))), SIGNAL(clicked()), this, SLOT(onDocumentSelect()));
connect(_attachType.addButton(new IconedButton(this, st::dropdownAttachPhoto, lang(lng_attach_photo))), SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
@ -2164,6 +2253,15 @@ void HistoryWidget::start() {
connect(App::api(), SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*)));
}
void HistoryWidget::onMentionHashtagOrBotCommandInsert(QString str) {
if (str.at(0) == '/') { // bot command
App::sendBotCommand(str);
setFieldText(_field.getLastText().mid(_field.textCursor().position()));
} else {
_field.onMentionHashtagOrBotCommandInsert(str);
}
}
void HistoryWidget::onTextChange() {
updateTyping();
@ -2182,6 +2280,11 @@ void HistoryWidget::onTextChange() {
a_recordCancel = anim::cvalue(st::recordCancel->c, st::recordCancel->c);
}
}
if (updateCmdStartShown()) {
updateControlsVisibility();
resizeEvent(0);
update();
}
if (!hist || _synthedTextUpdate) return;
_saveDraftText = true;
@ -2269,7 +2372,7 @@ void HistoryWidget::activate() {
}
}
if (_list) {
if (_selCount || _recording || isBotStart()) {
if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) {
_list->setFocus();
} else {
_field.setFocus();
@ -2574,6 +2677,7 @@ void HistoryWidget::setKbWasHidden() {
_kbScroll.hide();
_attachEmoji.show();
_kbHide.hide();
_cmdStart.hide();
_kbShow.show();
}
_field.setMaxHeight(st::maxFieldHeight);
@ -2710,6 +2814,8 @@ void HistoryWidget::showPeer(const PeerId &peer, MsgId msgId, bool force, bool l
App::contextItem(0);
App::mousedItem(0);
_kbWasHidden = false;
if (peer) {
App::forgetMedia();
serviceImageCacheSize = imageCacheSize();
@ -2737,6 +2843,7 @@ void HistoryWidget::showPeer(const PeerId &peer, MsgId msgId, bool force, bool l
_scroll.setWidget(_list);
_list->show();
updateBotKeyboard();
checkUnreadLoaded();
App::main()->peerUpdated(histPeer);
@ -2774,12 +2881,10 @@ void HistoryWidget::showPeer(const PeerId &peer, MsgId msgId, bool force, bool l
connect(&_scroll, SIGNAL(geometryChanged()), _list, SLOT(onParentGeometryChanged()));
connect(&_scroll, SIGNAL(scrolled()), _list, SLOT(onUpdateSelected()));
} else {
updateBotKeyboard();
updateControlsVisibility();
}
_kbWasHidden = false;
updateBotKeyboard();
emit peerShown(histPeer);
App::main()->topBar()->update();
update();
@ -2825,6 +2930,7 @@ void HistoryWidget::updateControlsVisibility() {
_toHistoryEnd.hide();
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachType.hide();
_emojiPan.hide();
return;
@ -2845,6 +2951,7 @@ void HistoryWidget::updateControlsVisibility() {
_attachEmoji.hide();
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachDocument.hide();
_attachPhoto.hide();
_kbScroll.hide();
@ -2867,6 +2974,7 @@ void HistoryWidget::updateControlsVisibility() {
_attachEmoji.hide();
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachDocument.hide();
_attachPhoto.hide();
if (_kbShown) {
@ -2881,19 +2989,27 @@ void HistoryWidget::updateControlsVisibility() {
_attachEmoji.hide();
_kbHide.show();
_kbShow.hide();
_cmdStart.hide();
} else if (_kbReplyTo) {
_kbScroll.hide();
_attachEmoji.show();
_kbHide.hide();
_kbShow.hide();
_cmdStart.hide();
} else {
_kbScroll.hide();
_attachEmoji.show();
_kbHide.hide();
if (_keyboard.hasMarkup() || _keyboard.forceReply()) {
if (_keyboard.hasMarkup()) {
_kbShow.show();
_cmdStart.hide();
} else {
_kbShow.hide();
if (_cmdStartShown) {
_cmdStart.show();
} else {
_cmdStart.hide();
}
}
}
if (cDefaultAttach() == dbidaPhoto) {
@ -2923,6 +3039,7 @@ void HistoryWidget::updateControlsVisibility() {
_attachEmoji.hide();
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachType.hide();
_emojiPan.hide();
if (!_field.isHidden()) {
@ -2948,6 +3065,7 @@ void HistoryWidget::updateControlsVisibility() {
_attachEmoji.hide();
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachType.hide();
_emojiPan.hide();
_replyForwardPreviewCancel.hide();
@ -3302,6 +3420,7 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
if (!_attachMention.isHidden()) _attachMention.hideStart();
if (!_attachType.isHidden()) _attachType.hideStart();
if (!_emojiPan.isHidden()) _emojiPan.hideStart();
} else if (App::main()->hasForwardingItems()) {
App::main()->readServerHistory(hist, false);
hist->loadAround(0);
@ -3311,6 +3430,8 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
if (replyTo < 0) cancelReply(lastKeyboardUsed);
if (_previewData && _previewData->pendingTill) previewCancel();
_field.setFocus();
if (!_keyboard.hasMarkup() && _keyboard.forceReply() && !_kbReplyTo) onKbToggle();
}
void HistoryWidget::onBotStart() {
@ -3326,7 +3447,7 @@ void HistoryWidget::onBotStart() {
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();
if (_keyboard.hasMarkup() || _keyboard.forceReply()) {
if (_keyboard.hasMarkup()) {
if (_keyboard.singleUse() && _keyboard.forMsgId() == hist->lastKeyboardId && hist->lastKeyboardUsed) _kbWasHidden = true;
if (!_kbWasHidden) _kbShown = _keyboard.hasMarkup();
}
@ -3415,6 +3536,7 @@ void HistoryWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTo
_attachMention.hide();
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_field.hide();
_replyForwardPreviewCancel.hide();
_send.hide();
@ -3783,10 +3905,26 @@ void HistoryWidget::updateDragAreas() {
}
bool HistoryWidget::isBotStart() const {
if (histPeer->chat || !histPeer->asUser()->botInfo) return false;
if (!hist || !histPeer || histPeer->chat || !histPeer->asUser()->botInfo) return false;
return !histPeer->asUser()->botInfo->startToken.isEmpty() || (hist->isEmpty() && !hist->lastMsg);
}
bool HistoryWidget::updateCmdStartShown() {
bool cmdStartShown = false;
if (hist && histPeer && ((histPeer->chat && histPeer->asChat()->botStatus > 0) || (!histPeer->chat && histPeer->asUser()->botInfo))) {
if (!isBotStart() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) {
if (_field.getLastText().isEmpty()) {
cmdStartShown = true;
}
}
}
if (_cmdStartShown != cmdStartShown) {
_cmdStartShown = cmdStartShown;
return true;
}
return false;
}
void HistoryWidget::dropEvent(QDropEvent *e) {
_attachDrag = DragStateNone;
updateDragAreas();
@ -3805,20 +3943,29 @@ void HistoryWidget::onDocumentDrop(QDropEvent *e) {
void HistoryWidget::onKbToggle(bool manual) {
if (_kbShown || _kbReplyTo) {
_kbHide.hide();
_kbShow.show();
_kbScroll.hide();
_kbShown = false;
if (_kbShown) {
_kbShow.show();
if (manual) _kbWasHidden = true;
_field.setMaxHeight(st::maxFieldHeight);
_kbScroll.hide();
_kbShown = false;
_kbReplyTo = 0;
if (!App::main()->hasForwardingItems() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
_replyForwardPreviewCancel.hide();
_field.setMaxHeight(st::maxFieldHeight);
_kbReplyTo = 0;
if (!App::main()->hasForwardingItems() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
_replyForwardPreviewCancel.hide();
}
} else {
if (hist) {
hist->clearLastKeyboard();
}
updateBotKeyboard();
}
if (manual) _kbWasHidden = true;
} else if (!_keyboard.hasMarkup() && _keyboard.forceReply()) {
_kbHide.hide();
_kbShow.hide();
_cmdStart.show();
_kbScroll.hide();
_kbShown = false;
@ -3857,6 +4004,11 @@ void HistoryWidget::onKbToggle(bool manual) {
updateField();
}
void HistoryWidget::onCmdStart() {
setFieldText(qsl("/"));
_field.moveCursor(QTextCursor::End);
}
void HistoryWidget::onPhotoDrop(QDropEvent *e) {
if (!hist) return;
@ -4029,6 +4181,7 @@ void HistoryWidget::onFieldResize() {
_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());
_cmdStart.move(_attachEmoji.x() - _cmdStart.width(), height() - kbh - _cmdStart.height());
_attachType.move(0, _attachDocument.y() - _attachType.height());
_emojiPan.move(width() - _emojiPan.width(), _attachEmoji.y() - _emojiPan.height());
@ -4391,7 +4544,8 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
_replyForwardPreviewCancel.move(width() - _replyForwardPreviewCancel.width(), _field.y() - st::sendPadding - _replyForwardPreviewCancel.height());
updateListSize();
_field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width() - ((_kbShown || (!_keyboard.hasMarkup() && !_keyboard.forceReply())) ? 0 : _kbShow.width()), _field.height());
bool kbShowShown = hist && !_kbShown && _keyboard.hasMarkup();
_field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width() - (kbShowShown ? _kbShow.width() : 0) - (_cmdStartShown ? _cmdStart.width() : 0), _field.height());
_toHistoryEnd.move((width() - _toHistoryEnd.width()) / 2, _scroll.y() + _scroll.height() - _toHistoryEnd.height() - st::historyToEndSkip);
@ -4400,6 +4554,7 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
_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());
_cmdStart.move(_attachEmoji.x() - _cmdStart.width(), height() - kbh - _cmdStart.height());
_attachType.move(0, _attachDocument.y() - _attachType.height());
_emojiPan.move(width() - _emojiPan.width(), _attachEmoji.y() - _emojiPan.height());
@ -4575,11 +4730,12 @@ void HistoryWidget::updateBotKeyboard() {
} else {
changed = _keyboard.updateMarkup(hist->lastKeyboardId ? App::histItemById(hist->lastKeyboardId) : 0);
}
updateCmdStartShown();
if (!changed) return;
bool hasMarkup = _keyboard.hasMarkup(), forceReply = _keyboard.forceReply() && !_replyTo;
if (hasMarkup || forceReply) {
if (_keyboard.singleUse() && _keyboard.forMsgId() == hist->lastKeyboardId && hist->lastKeyboardUsed) _kbWasHidden = true;
if (_keyboard.singleUse() && _keyboard.hasMarkup() && _keyboard.forMsgId() == hist->lastKeyboardId && hist->lastKeyboardUsed) _kbWasHidden = true;
if (!isBotStart() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) {
if (!_showAnim.animating()) {
if (hasMarkup) {
@ -4592,6 +4748,7 @@ void HistoryWidget::updateBotKeyboard() {
_kbHide.hide();
}
_kbShow.hide();
_cmdStart.hide();
}
int32 maxh = hasMarkup ? qMin(_keyboard.height(), int(st::maxFieldHeight) - (int(st::maxFieldHeight) / 2)) : 0;
_field.setMaxHeight(st::maxFieldHeight - maxh);
@ -4608,6 +4765,7 @@ void HistoryWidget::updateBotKeyboard() {
_attachEmoji.show();
_kbHide.hide();
_kbShow.show();
_cmdStart.hide();
}
_field.setMaxHeight(st::maxFieldHeight);
_kbShown = false;
@ -4622,6 +4780,7 @@ void HistoryWidget::updateBotKeyboard() {
_attachEmoji.show();
_kbHide.hide();
_kbShow.hide();
_cmdStart.show();
}
_field.setMaxHeight(st::maxFieldHeight);
_kbShown = false;
@ -4822,8 +4981,9 @@ void HistoryWidget::cancelReply(bool lastKeyboardUsed) {
onDraftSave();
}
if (_keyboard.singleUse() && _keyboard.forceReply() && lastKeyboardUsed) {
if (_kbReplyTo) onKbToggle(false);
hist->lastKeyboardUsed = true;
if (_kbReplyTo) {
onKbToggle(false);
}
}
}
@ -4979,6 +5139,11 @@ void HistoryWidget::onFullPeerUpdated(PeerData *data) {
checkMentionDropdown();
_list->updateBotInfo();
}
if (updateCmdStartShown()) {
updateControlsVisibility();
resizeEvent(0);
update();
}
}
void HistoryWidget::peerUpdated(PeerData *data) {
@ -5096,7 +5261,7 @@ void HistoryWidget::updateTopBarSelection() {
updateControlsVisibility();
updateListSize();
if (!App::wnd()->layerShown() && !App::passcoded()) {
if (_selCount || _recording || isBotStart()) {
if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) {
_list->setFocus();
} else {
_field.setFocus();

View file

@ -81,6 +81,8 @@ public:
void updateBotInfo(bool recount = true);
bool wasSelectedText() const;
~HistoryList();
public slots:
@ -115,7 +117,6 @@ private:
HistoryItem *prevItem(HistoryItem *item);
HistoryItem *nextItem(HistoryItem *item);
void updateDragSelection(HistoryItem *dragSelFrom, HistoryItem *dragSelTo, bool dragSelecting, bool force = false);
void applyDragSelection();
History *hist;
@ -133,6 +134,9 @@ private:
Qt::CursorShape _cursor;
typedef QMap<HistoryItem*, uint32> SelectedItems;
SelectedItems _selected;
void applyDragSelection();
void applyDragSelection(SelectedItems *toItems) const;
enum DragAction {
NoDrag = 0x00,
PrepareDrag = 0x01,
@ -154,6 +158,7 @@ private:
HistoryItem *_dragSelFrom, *_dragSelTo;
bool _dragSelecting;
bool _wasSelectedText; // was some text selected in current drag action
bool _touchScroll, _touchSelect, _touchInProgress;
QPoint _touchStart, _touchPrevPos, _touchPos;
@ -460,6 +465,8 @@ public:
bool eventFilter(QObject *obj, QEvent *e);
void updateBotKeyboard();
DragState getDragState(const QMimeData *d);
~HistoryWidget();
signals:
@ -506,6 +513,7 @@ public slots:
void onDocumentDrop(QDropEvent *e);
void onKbToggle(bool manual = true);
void onCmdStart();
void onPhotoReady();
void onSendConfirmed();
@ -514,6 +522,7 @@ public slots:
void showPeer(const PeerId &peer, MsgId msgId = 0, bool force = false, bool leaveActive = false);
void clearLoadingAround();
void activate();
void onMentionHashtagOrBotCommandInsert(QString str);
void onTextChange();
void onStickerSend(DocumentData *sticker);
@ -591,7 +600,6 @@ private:
void setFieldText(const QString &text);
QStringList getMediasFromMime(const QMimeData *d);
DragState getDragState(const QMimeData *d);
void updateDragAreas();
@ -616,9 +624,11 @@ private:
MentionsDropdown _attachMention;
bool isBotStart() const;
bool updateCmdStartShown();
FlatButton _send, _botStart;
IconedButton _attachDocument, _attachPhoto, _attachEmoji, _kbShow, _kbHide;
IconedButton _attachDocument, _attachPhoto, _attachEmoji, _kbShow, _kbHide, _cmdStart;
bool _cmdStartShown;
MessageField _field;
Animation _recordAnim, _recordingAnim;
bool _recording, _inRecord, _inField, _inReply;

View file

@ -694,6 +694,10 @@ void MainWidget::dialogsActivate() {
dialogs.activate();
}
DragState MainWidget::getDragState(const QMimeData *mime) {
return history.getDragState(mime);
}
bool MainWidget::leaveChatFailed(PeerData *peer, const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;

View file

@ -262,6 +262,8 @@ public:
void focusPeerSelect();
void dialogsActivate();
DragState getDragState(const QMimeData *mime);
bool leaveChatFailed(PeerData *peer, const RPCError &e);
void deleteHistory(PeerData *peer, const MTPUpdates &updates);
void deleteHistoryPart(PeerData *peer, const MTPmessages_AffectedHistory &result);

View file

@ -300,7 +300,6 @@ void ProfileInner::onMediaAudios() {
}
void ProfileInner::onInvitationLink() {
DEBUG_LOG(("Setting text to clipboard from invite url: %1").arg(_peerChat->invitationUrl));
QApplication::clipboard()->setText(_peerChat->invitationUrl);
App::wnd()->showLayer(new ConfirmBox(lang(lng_group_invite_copied), true));
}
@ -512,7 +511,7 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
p.setPen(st::black->p);
p.drawText(_left + st::profilePhotoSize + st::profileStatusLeft, top + st::profileStatusTop + st::linkFont->ascent, '@' + _peerUser->username);
}
p.setPen((_peerUser && App::onlineColorUse(_peerUser->onlineTill, l_time) ? st::profileOnlineColor : st::profileOfflineColor)->p);
p.setPen((_peerUser && App::onlineColorUse(_peerUser, l_time) ? st::profileOnlineColor : st::profileOfflineColor)->p);
p.drawText(_left + st::profilePhotoSize + st::profileStatusLeft, top + addbyname + st::profileStatusTop + st::linkFont->ascent, _onlineText);
if (_chatAdmin && !_peerChat->invitationUrl.isEmpty()) {
p.setPen(st::black->p);
@ -643,7 +642,7 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
p.setFont(st::linkFont->f);
data->name.drawElided(p, _left + st::profileListPhotoSize + st::profileListPadding.width(), top + st::profileListNameTop, _width - _kickWidth - st::profileListPadding.width() - st::profileListPhotoSize - st::profileListPadding.width());
p.setFont(st::profileSubFont->f);
p.setPen((App::onlineColorUse(user->onlineTill, l_time) ? st::profileOnlineColor : st::profileOfflineColor)->p);
p.setPen((App::onlineColorUse(user, l_time) ? st::profileOnlineColor : st::profileOfflineColor)->p);
p.drawText(_left + st::profileListPhotoSize + st::profileListPadding.width(), top + st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, data->online);
if (data->cankick) {
@ -906,12 +905,10 @@ void ProfileInner::onMenuDestroy(QObject *obj) {
}
void ProfileInner::onCopyPhone() {
DEBUG_LOG(("Setting text to clipboard from user phone: %1").arg(_phoneText));
QApplication::clipboard()->setText(_phoneText);
}
void ProfileInner::onCopyUsername() {
DEBUG_LOG(("Setting text to clipboard from username: @%1").arg(_peerUser->username));
QApplication::clipboard()->setText('@' + _peerUser->username);
}

View file

@ -258,6 +258,8 @@ void UserData::nameUpdated() {
}
void UserData::madeAction() {
if (botInfo || isServiceUser(id)) return;
int32 t = unixtime();
if (onlineTill <= 0 && -onlineTill < t) {
onlineTill = -t - SetOnlineAfterActivity;

View file

@ -11,7 +11,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.8.29</string>
<string>0.8.30</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.29;
CURRENT_PROJECT_VERSION = 0.8.30;
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.29;
CURRENT_PROJECT_VERSION = 0.8.30;
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.29;
CURRENT_PROJECT_VERSION = 0.8.30;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 0.8;
DYLIB_CURRENT_VERSION = 0.8.29;
DYLIB_CURRENT_VERSION = 0.8.30;
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.29;
CURRENT_PROJECT_VERSION = 0.8.30;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 0.8;
DYLIB_CURRENT_VERSION = 0.8.29;
DYLIB_CURRENT_VERSION = 0.8.30;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;

View file

@ -1,2 +1,2 @@
echo 8029 0.8.29 1
echo 8030 0.8.30 0
# AppVersion AppVersionStr DevChannel