Inline bot cancel button added.

It replaces Send button when the user is editing an inline bot
query. First cancel clears the inline bot request, second one
clears the field entirely. Escape key acts the same as cancel.
This commit is contained in:
John Preston 2016-04-09 15:02:50 +04:00
parent c3c82eac2d
commit 0110a62776
9 changed files with 246 additions and 153 deletions

View File

@ -1489,6 +1489,11 @@ replyCancel: iconedButton(btnDefIconed) {
width: 49px; width: 49px;
height: 49px; height: 49px;
} }
inlineBotCancel: iconedButton(replyCancel) {
height: 46px;
iconPos: point(-1px, 16px); // < 0 means draw in the center of the button
downIconPos: point(-1px, 17px);
}
forwardIcon: sprite(368px, 197px, 24px, 24px); forwardIcon: sprite(368px, 197px, 24px, 24px);
historyScroll: flatScroll(scrollDef) { historyScroll: flatScroll(scrollDef) {

View File

@ -3655,7 +3655,7 @@ void EmojiPan::inlineBotChanged() {
if (_inlineRequestId) MTP::cancel(_inlineRequestId); if (_inlineRequestId) MTP::cancel(_inlineRequestId);
_inlineRequestId = 0; _inlineRequestId = 0;
_inlineQuery = _inlineNextQuery = _inlineNextOffset = QString(); _inlineQuery = _inlineNextQuery = _inlineNextOffset = QString();
_inlineBot = 0; _inlineBot = nullptr;
for (InlineCache::const_iterator i = _inlineCache.cbegin(), e = _inlineCache.cend(); i != e; ++i) { for (InlineCache::const_iterator i = _inlineCache.cbegin(), e = _inlineCache.cend(); i != e; ++i) {
delete i.value(); delete i.value();
} }

View File

@ -2816,7 +2816,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(&_attachMention, SIGNAL(chosen(QString)), this, SLOT(onMentionHashtagOrBotCommandInsert(QString))); connect(&_attachMention, SIGNAL(chosen(QString)), this, SLOT(onMentionHashtagOrBotCommandInsert(QString)));
connect(&_attachMention, SIGNAL(stickerSelected(DocumentData*)), this, SLOT(onStickerSend(DocumentData*))); connect(&_attachMention, SIGNAL(stickerSelected(DocumentData*)), this, SLOT(onStickerSend(DocumentData*)));
_field.installEventFilter(&_attachMention); _field.installEventFilter(&_attachMention);
_field.setCtrlEnterSubmit(cCtrlEnter()); updateFieldSubmitSettings();
_field.hide(); _field.hide();
_send.hide(); _send.hide();
@ -2884,28 +2884,31 @@ void HistoryWidget::onMentionHashtagOrBotCommandInsert(QString str) {
} }
void HistoryWidget::updateInlineBotQuery() { void HistoryWidget::updateInlineBotQuery() {
UserData *bot = _inlineBot; UserData *bot = nullptr;
bool start = false; QString inlineBotUsername;
QString inlineBotUsername(_inlineBotUsername); QString query = _field.getInlineBotQuery(&bot, &inlineBotUsername);
QString query = _field.getInlineBotQuery(_inlineBot, _inlineBotUsername);
if (inlineBotUsername != _inlineBotUsername) { if (inlineBotUsername != _inlineBotUsername) {
_inlineBotUsername = inlineBotUsername;
if (_inlineBotResolveRequestId) { if (_inlineBotResolveRequestId) {
// Notify::inlineBotRequesting(false); // Notify::inlineBotRequesting(false);
MTP::cancel(_inlineBotResolveRequestId); MTP::cancel(_inlineBotResolveRequestId);
_inlineBotResolveRequestId = 0; _inlineBotResolveRequestId = 0;
} }
if (_inlineBot == LookingUpInlineBot) { if (bot == LookingUpInlineBot) {
_inlineBot = LookingUpInlineBot;
// Notify::inlineBotRequesting(true); // Notify::inlineBotRequesting(true);
_inlineBotResolveRequestId = MTP::send(MTPcontacts_ResolveUsername(MTP_string(_inlineBotUsername)), rpcDone(&HistoryWidget::inlineBotResolveDone), rpcFail(&HistoryWidget::inlineBotResolveFail, _inlineBotUsername)); _inlineBotResolveRequestId = MTP::send(MTPcontacts_ResolveUsername(MTP_string(_inlineBotUsername)), rpcDone(&HistoryWidget::inlineBotResolveDone), rpcFail(&HistoryWidget::inlineBotResolveFail, _inlineBotUsername));
return; return;
} }
} else if (_inlineBot == LookingUpInlineBot) { } else if (bot == LookingUpInlineBot) {
_inlineBot = LookingUpInlineBot;
return; return;
} }
if (_inlineBot) { if (bot) {
if (_inlineBot != bot) { if (_inlineBot != bot) {
updateFieldPlaceholder(); _inlineBot = bot;
inlineBotChanged();
} }
if (_inlineBot->username == cInlineGifBotUsername() && query.isEmpty()) { if (_inlineBot->username == cInlineGifBotUsername() && query.isEmpty()) {
_emojiPan.clearInlineBot(); _emojiPan.clearInlineBot();
@ -2916,12 +2919,7 @@ void HistoryWidget::updateInlineBotQuery() {
_attachMention.hideStart(); _attachMention.hideStart();
} }
} else { } else {
if (_inlineBot != bot) { clearInlineBot();
updateFieldPlaceholder();
_field.finishPlaceholder();
}
_emojiPan.clearInlineBot();
onCheckMentionDropdown();
} }
} }
@ -3531,7 +3529,7 @@ void HistoryWidget::fastShowAtEnd(History *h) {
void HistoryWidget::applyDraft(bool parseLinks) { void HistoryWidget::applyDraft(bool parseLinks) {
HistoryDraft *draft = _history ? _history->draft() : nullptr; HistoryDraft *draft = _history ? _history->draft() : nullptr;
if (!draft) { if (!draft) {
setFieldText(QString()); clearFieldText();
_field.setFocus(); _field.setFocus();
_editMsgId = _replyToId = 0; _editMsgId = _replyToId = 0;
return; return;
@ -3672,11 +3670,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
_scroll.takeWidget(); _scroll.takeWidget();
updateTopBarSelection(); updateTopBarSelection();
if (_inlineBot) { clearInlineBot();
_inlineBot = nullptr;
_emojiPan.clearInlineBot();
updateFieldPlaceholder();
}
_showAtMsgId = showAtMsgId; _showAtMsgId = showAtMsgId;
_histInited = false; _histInited = false;
@ -3776,7 +3770,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
onBotStart(); onBotStart();
} }
} else { } else {
setFieldText(QString()); clearFieldText();
doneShow(); doneShow();
} }
@ -3815,8 +3809,14 @@ void HistoryWidget::updateAfterDrag() {
if (_list) _list->dragActionUpdate(QCursor::pos()); if (_list) _list->dragActionUpdate(QCursor::pos());
} }
void HistoryWidget::ctrlEnterSubmitUpdated() { void HistoryWidget::updateFieldSubmitSettings() {
_field.setCtrlEnterSubmit(cCtrlEnter()); FlatTextarea::SubmitSettings settings = FlatTextarea::SubmitSettings::Enter;
if (_inlineBotCancel) {
settings = FlatTextarea::SubmitSettings::None;
} else if (cCtrlEnter()) {
settings = FlatTextarea::SubmitSettings::CtrlEnter;
}
_field.setSubmitSettings(settings);
} }
void HistoryWidget::updateNotifySettings() { void HistoryWidget::updateNotifySettings() {
@ -3943,6 +3943,7 @@ void HistoryWidget::updateControlsVisibility() {
_scroll.hide(); _scroll.hide();
_kbScroll.hide(); _kbScroll.hide();
_send.hide(); _send.hide();
if (_inlineBotCancel) _inlineBotCancel->hide();
_unblock.hide(); _unblock.hide();
_botStart.hide(); _botStart.hide();
_joinChannel.hide(); _joinChannel.hide();
@ -4010,6 +4011,7 @@ void HistoryWidget::updateControlsVisibility() {
_kbShown = false; _kbShown = false;
_attachMention.hide(); _attachMention.hide();
_send.hide(); _send.hide();
if (_inlineBotCancel) _inlineBotCancel->hide();
_botStart.hide(); _botStart.hide();
_attachDocument.hide(); _attachDocument.hide();
_attachPhoto.hide(); _attachPhoto.hide();
@ -4044,6 +4046,7 @@ void HistoryWidget::updateControlsVisibility() {
} }
_kbShown = false; _kbShown = false;
_send.hide(); _send.hide();
if (_inlineBotCancel) _inlineBotCancel->hide();
_field.hide(); _field.hide();
_attachEmoji.hide(); _attachEmoji.hide();
_kbShow.hide(); _kbShow.hide();
@ -4064,7 +4067,12 @@ void HistoryWidget::updateControlsVisibility() {
_send.hide(); _send.hide();
mouseMoveEvent(0); mouseMoveEvent(0);
} else { } else {
_send.show(); if (_inlineBotCancel) {
_inlineBotCancel->show();
_send.hide();
} else {
_send.show();
}
_a_record.stop(); _a_record.stop();
_inRecord = _inField = false; _inRecord = _inField = false;
a_recordOver = anim::fvalue(0, 0); a_recordOver = anim::fvalue(0, 0);
@ -4146,6 +4154,7 @@ void HistoryWidget::updateControlsVisibility() {
} else { } else {
_attachMention.hide(); _attachMention.hide();
_send.hide(); _send.hide();
if (_inlineBotCancel) _inlineBotCancel->hide();
_unblock.hide(); _unblock.hide();
_botStart.hide(); _botStart.hide();
_joinChannel.hide(); _joinChannel.hide();
@ -4630,6 +4639,15 @@ void HistoryWidget::preloadHistoryIfNeeded() {
} }
} }
void HistoryWidget::onInlineBotCancel() {
QString text = _field.getLastText();
if (text.size() > _inlineBotUsername.size() + 2) {
setFieldText('@' + _inlineBotUsername + ' ', TextUpdateEventsSaveDraft, false);
} else {
clearFieldText(TextUpdateEventsSaveDraft, false);
}
}
void HistoryWidget::onWindowVisibleChanged() { void HistoryWidget::onWindowVisibleChanged() {
QTimer::singleShot(0, this, SLOT(preloadHistoryIfNeeded())); QTimer::singleShot(0, this, SLOT(preloadHistoryIfNeeded()));
} }
@ -4746,7 +4764,7 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
App::main()->sendMessage(_history, _field.getLastText(), replyTo, _broadcast.checked(), _silent.checked(), webPageId); App::main()->sendMessage(_history, _field.getLastText(), replyTo, _broadcast.checked(), _silent.checked(), webPageId);
setFieldText(QString()); clearFieldText();
_saveDraftText = true; _saveDraftText = true;
_saveDraftStart = getms(); _saveDraftStart = getms();
onDraftSave(); onDraftSave();
@ -4971,6 +4989,7 @@ void HistoryWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTo
_field.hide(); _field.hide();
_fieldBarCancel.hide(); _fieldBarCancel.hide();
_send.hide(); _send.hide();
if (_inlineBotCancel) _inlineBotCancel->hide();
_unblock.hide(); _unblock.hide();
_botStart.hide(); _botStart.hide();
_joinChannel.hide(); _joinChannel.hide();
@ -5341,7 +5360,7 @@ bool HistoryWidget::insertBotCommand(const QString &cmd, bool specialGif) {
QString text = _field.getLastText(); QString text = _field.getLastText();
if (specialGif) { if (specialGif) {
if (text.trimmed() == '@' + cInlineGifBotUsername() && text.at(0) == '@') { if (text.trimmed() == '@' + cInlineGifBotUsername() && text.at(0) == '@') {
setFieldText(QString(), TextUpdateEventsSaveDraft, false); clearFieldText(TextUpdateEventsSaveDraft, false);
} }
} else { } else {
QRegularExpressionMatch m = QRegularExpression(qsl("^/[A-Za-z_0-9]{0,64}(@[A-Za-z_0-9]{0,32})?(\\s|$)")).match(text); QRegularExpressionMatch m = QRegularExpression(qsl("^/[A-Za-z_0-9]{0,64}(@[A-Za-z_0-9]{0,32})?(\\s|$)")).match(text);
@ -5481,8 +5500,7 @@ bool HistoryWidget::inlineBotResolveFail(QString name, const RPCError &error) {
_inlineBotResolveRequestId = 0; _inlineBotResolveRequestId = 0;
// Notify::inlineBotRequesting(false); // Notify::inlineBotRequesting(false);
if (name == _inlineBotUsername) { if (name == _inlineBotUsername) {
_inlineBot = nullptr; clearInlineBot();
onCheckMentionDropdown();
} }
return true; return true;
} }
@ -5654,7 +5672,6 @@ void HistoryWidget::onKbToggle(bool manual) {
void HistoryWidget::onCmdStart() { void HistoryWidget::onCmdStart() {
setFieldText(qsl("/")); setFieldText(qsl("/"));
_field.moveCursor(QTextCursor::End);
} }
void HistoryWidget::contextMenuEvent(QContextMenuEvent *e) { void HistoryWidget::contextMenuEvent(QContextMenuEvent *e) {
@ -5816,35 +5833,92 @@ void HistoryWidget::updateOnlineDisplayTimer() {
App::main()->updateOnlineDisplayIn(minIn * 1000); App::main()->updateOnlineDisplayIn(minIn * 1000);
} }
void HistoryWidget::onFieldResize() { void HistoryWidget::moveFieldControls() {
int32 maxKeyboardHeight = int(st::maxFieldHeight) - _field.height(); int w = width(), h = height(), right = w, bottom = h, keyboardHeight = 0;
int maxKeyboardHeight = int(st::maxFieldHeight) - _field.height();
_keyboard.resizeToWidth(width(), maxKeyboardHeight); _keyboard.resizeToWidth(width(), maxKeyboardHeight);
int32 kbh = 0;
if (_kbShown) { if (_kbShown) {
kbh = qMin(_keyboard.height(), maxKeyboardHeight); keyboardHeight = qMin(_keyboard.height(), maxKeyboardHeight);
_kbScroll.setGeometry(0, height() - kbh, width(), kbh); bottom -= keyboardHeight;
_kbScroll.setGeometry(0, bottom, w, keyboardHeight);
} }
_field.move(_attachDocument.x() + _attachDocument.width(), height() - kbh - _field.height() - st::sendPadding);
_fieldBarCancel.move(width() - _fieldBarCancel.width(), _field.y() - st::sendPadding - _fieldBarCancel.height());
_attachDocument.move(0, height() - kbh - _attachDocument.height()); // _attachType ----------------------------------------------------------- _emojiPan --------- _fieldBarCancel
_attachPhoto.move(_attachDocument.x(), _attachDocument.y()); // (_attachDocument|_attachPhoto) _field (_silent|_cmdStart|_kbShow) (_kbHide|_attachEmoji) [_broadcast] _send
_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height()); // (_botStart|_unblock|_joinChannel|_muteUnmute)
_unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height());
_joinChannel.setGeometry(0, _attachDocument.y(), width(), _joinChannel.height());
_muteUnmute.setGeometry(0, _attachDocument.y(), width(), _muteUnmute.height());
_send.move(width() - _send.width(), _attachDocument.y());
_broadcast.move(_send.x() - _broadcast.width(), height() - kbh - _broadcast.height());
_attachEmoji.move((hasBroadcastToggle() ? _broadcast.x() : _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());
_silent.move(_attachEmoji.x() - _silent.width(), height() - kbh - _silent.height());
int buttonsBottom = bottom - _attachDocument.height();
_attachDocument.move(0, buttonsBottom);
_attachPhoto.move(0, buttonsBottom);
_field.move(_attachDocument.width(), bottom - _field.height() - st::sendPadding);
_send.move(right - _send.width(), buttonsBottom);
if (_inlineBotCancel) _inlineBotCancel->move(_send.pos());
right -= _send.width();
_broadcast.move(right - _broadcast.width(), buttonsBottom);
if (hasBroadcastToggle()) right -= _broadcast.width();
_attachEmoji.move(right - _attachEmoji.width(), buttonsBottom);
_kbHide.move(right - _kbHide.width(), buttonsBottom);
right -= _attachEmoji.width();
_kbShow.move(right - _kbShow.width(), buttonsBottom);
_cmdStart.move(right - _cmdStart.width(), buttonsBottom);
_silent.move(right - _silent.width(), buttonsBottom);
right = w;
_fieldBarCancel.move(right - _fieldBarCancel.width(), _field.y() - st::sendPadding - _fieldBarCancel.height());
_attachType.move(0, _attachDocument.y() - _attachType.height()); _attachType.move(0, _attachDocument.y() - _attachType.height());
_emojiPan.moveBottom(_attachEmoji.y()); _emojiPan.moveBottom(_attachEmoji.y());
_botStart.setGeometry(0, bottom - _botStart.height(), w, _botStart.height());
_unblock.setGeometry(0, bottom - _unblock.height(), w, _unblock.height());
_joinChannel.setGeometry(0, bottom - _joinChannel.height(), w, _joinChannel.height());
_muteUnmute.setGeometry(0, bottom - _muteUnmute.height(), w, _muteUnmute.height());
}
void HistoryWidget::updateFieldSize() {
bool kbShowShown = _history && !_kbShown && _keyboard.hasMarkup();
int fieldWidth = width() - _attachDocument.width();
fieldWidth -= _send.width();
fieldWidth -= _attachEmoji.width();
if (kbShowShown) fieldWidth -= _kbShow.width();
if (_cmdStartShown) fieldWidth -= _cmdStart.width();
if (hasBroadcastToggle()) fieldWidth -= _broadcast.width();
if (hasSilentToggle()) fieldWidth -= _silent.width();
if (_field.width() != fieldWidth) {
_field.resize(fieldWidth, _field.height());
} else {
moveFieldControls();
}
}
void HistoryWidget::clearInlineBot() {
if (_inlineBot) {
_inlineBot = nullptr;
inlineBotChanged();
_field.finishPlaceholder();
}
_emojiPan.clearInlineBot();
onCheckMentionDropdown();
}
void HistoryWidget::inlineBotChanged() {
bool isInlineBot = _inlineBot && (_inlineBot != LookingUpInlineBot);
if (isInlineBot && !_inlineBotCancel) {
_inlineBotCancel = MakeUnique<IconedButton>(this, st::inlineBotCancel);
connect(_inlineBotCancel.data(), SIGNAL(clicked()), this, SLOT(onInlineBotCancel()));
_inlineBotCancel->setGeometry(_send.geometry());
updateFieldSubmitSettings();
updateControlsVisibility();
} else if (!isInlineBot && _inlineBotCancel) {
_inlineBotCancel.clear();
updateFieldSubmitSettings();
updateControlsVisibility();
}
updateFieldPlaceholder();
}
void HistoryWidget::onFieldResize() {
moveFieldControls();
updateListSize(); updateListSize();
updateField(); updateField();
} }
@ -5996,7 +6070,7 @@ void HistoryWidget::confirmSendFile(const FileLoadResultPtr &file, bool ctrlShif
void HistoryWidget::cancelSendFile(const FileLoadResultPtr &file) { void HistoryWidget::cancelSendFile(const FileLoadResultPtr &file) {
if (_confirmWithTextId && file->id == _confirmWithTextId) { if (_confirmWithTextId && file->id == _confirmWithTextId) {
setFieldText(QString()); clearFieldText();
_confirmWithTextId = 0; _confirmWithTextId = 0;
} }
if (!file->originalText.isEmpty()) { if (!file->originalText.isEmpty()) {
@ -6017,7 +6091,7 @@ void HistoryWidget::confirmShareContact(const QString &phone, const QString &fna
void HistoryWidget::cancelShareContact() { void HistoryWidget::cancelShareContact() {
if (_confirmWithTextId == 0xFFFFFFFFFFFFFFFFL) { if (_confirmWithTextId == 0xFFFFFFFFFFFFFFFFL) {
setFieldText(QString()); clearFieldText();
_confirmWithTextId = 0; _confirmWithTextId = 0;
} }
} }
@ -6331,15 +6405,7 @@ void HistoryWidget::notify_handlePendingHistoryUpdate() {
void HistoryWidget::resizeEvent(QResizeEvent *e) { void HistoryWidget::resizeEvent(QResizeEvent *e) {
_reportSpamPanel.resize(width(), _reportSpamPanel.height()); _reportSpamPanel.resize(width(), _reportSpamPanel.height());
int32 maxKeyboardHeight = int(st::maxFieldHeight) - _field.height(); moveFieldControls();
_keyboard.resizeToWidth(width(), maxKeyboardHeight);
int32 kbh = 0;
if (_kbShown) {
kbh = qMin(_keyboard.height(), maxKeyboardHeight);
_kbScroll.setGeometry(0, height() - kbh, width(), kbh);
}
_field.move(_attachDocument.x() + _attachDocument.width(), height() - kbh - _field.height() - st::sendPadding);
if (_pinnedBar) { if (_pinnedBar) {
if (_scroll.y() != st::replyHeight) { if (_scroll.y() != st::replyHeight) {
@ -6355,32 +6421,13 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
_attachMention.setBoundings(_scroll.geometry()); _attachMention.setBoundings(_scroll.geometry());
} }
_attachDocument.move(0, height() - kbh - _attachDocument.height());
_attachPhoto.move(_attachDocument.x(), _attachDocument.y());
_fieldBarCancel.move(width() - _fieldBarCancel.width(), _field.y() - st::sendPadding - _fieldBarCancel.height());
updateListSize(false, false, { ScrollChangeAdd, App::main() ? App::main()->contentScrollAddToY() : 0 }); updateListSize(false, false, { ScrollChangeAdd, App::main() ? App::main()->contentScrollAddToY() : 0 });
bool kbShowShown = _history && !_kbShown && _keyboard.hasMarkup(); updateFieldSize();
_field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width() - (kbShowShown ? _kbShow.width() : 0) - (_cmdStartShown ? _cmdStart.width() : 0) - (hasBroadcastToggle() ? _broadcast.width() : 0) - (hasSilentToggle() ? _silent.width() : 0), _field.height());
_toHistoryEnd.move((width() - _toHistoryEnd.width()) / 2, _scroll.y() + _scroll.height() - _toHistoryEnd.height() - st::historyToEndSkip); _toHistoryEnd.move((width() - _toHistoryEnd.width()) / 2, _scroll.y() + _scroll.height() - _toHistoryEnd.height() - st::historyToEndSkip);
updateCollapseCommentsVisibility(); updateCollapseCommentsVisibility();
_send.move(width() - _send.width(), _attachDocument.y());
_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
_unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height());
_joinChannel.setGeometry(0, _attachDocument.y(), width(), _joinChannel.height());
_muteUnmute.setGeometry(0, _attachDocument.y(), width(), _muteUnmute.height());
_broadcast.move(_send.x() - _broadcast.width(), height() - kbh - _broadcast.height());
_attachEmoji.move((hasBroadcastToggle() ? _broadcast.x() : _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());
_silent.move(_attachEmoji.x() - _silent.width(), height() - kbh - _silent.height());
_attachType.move(0, _attachDocument.y() - _attachType.height());
_emojiPan.moveBottom(_attachEmoji.y());
_emojiPan.setMaxHeight(height() - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom() - _attachEmoji.height()); _emojiPan.setMaxHeight(height() - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom() - _attachEmoji.height());
switch (_attachDrag) { switch (_attachDrag) {
@ -6904,7 +6951,7 @@ void HistoryWidget::onInlineResultSend(InlineBots::Result *result, UserData *bot
App::historyRegRandom(randomId, newId); App::historyRegRandom(randomId, newId);
setFieldText(QString()); clearFieldText();
_saveDraftText = true; _saveDraftText = true;
_saveDraftStart = getms(); _saveDraftStart = getms();
onDraftSave(); onDraftSave();
@ -7079,7 +7126,7 @@ void HistoryWidget::sendExistingDocument(DocumentData *doc, const QString &capti
App::historyRegRandom(randomId, newId); App::historyRegRandom(randomId, newId);
if (_attachMention.stickersShown()) { if (_attachMention.stickersShown()) {
setFieldText(QString()); clearFieldText();
_saveDraftText = true; _saveDraftText = true;
_saveDraftStart = getms(); _saveDraftStart = getms();
onDraftSave(); onDraftSave();
@ -7142,10 +7189,11 @@ void HistoryWidget::sendExistingPhoto(PhotoData *photo, const QString &caption)
void HistoryWidget::setFieldText(const QString &text, int32 textUpdateEventsFlags, bool clearUndoHistory) { void HistoryWidget::setFieldText(const QString &text, int32 textUpdateEventsFlags, bool clearUndoHistory) {
_textUpdateEventsFlags = textUpdateEventsFlags; _textUpdateEventsFlags = textUpdateEventsFlags;
_field.setTextFast(text, clearUndoHistory); _field.setTextFast(text, clearUndoHistory);
_field.moveCursor(QTextCursor::End);
_textUpdateEventsFlags = TextUpdateEventsSaveDraft | TextUpdateEventsSendTyping; _textUpdateEventsFlags = TextUpdateEventsSaveDraft | TextUpdateEventsSendTyping;
_previewCancelled = false; _previewCancelled = false;
_previewData = 0; _previewData = nullptr;
if (_previewRequest) { if (_previewRequest) {
MTP::cancel(_previewRequest); MTP::cancel(_previewRequest);
_previewRequest = 0; _previewRequest = 0;
@ -7554,8 +7602,8 @@ void HistoryWidget::updatePreview() {
} }
void HistoryWidget::onCancel() { void HistoryWidget::onCancel() {
if (_inlineBot && _field.getLastText().startsWith('@' + _inlineBot->username + ' ')) { if (_inlineBotCancel) {
setFieldText(QString(), TextUpdateEventsSaveDraft, false); onInlineBotCancel();
} else if (!_attachMention.isHidden()) { } else if (!_attachMention.isHidden()) {
_attachMention.hideStart(); _attachMention.hideStart();
} else { } else {

View File

@ -270,11 +270,9 @@ public:
bool hasSendText() const; bool hasSendText() const;
public slots: public slots:
void onEmojiInsert(EmojiPtr emoji); void onEmojiInsert(EmojiPtr emoji);
signals: signals:
void focused(); void focused();
private: private:
@ -490,13 +488,9 @@ enum TextUpdateEventsFlags {
namespace InlineBots { namespace InlineBots {
namespace Layout { namespace Layout {
class ItemBase; class ItemBase;
} // namespace Layout } // namespace Layout
class Result; class Result;
} // namespace InlineBots } // namespace InlineBots
class HistoryWidget : public TWidget, public RPCSender { class HistoryWidget : public TWidget, public RPCSender {
@ -653,7 +647,7 @@ public:
void updateCollapseCommentsVisibility(); void updateCollapseCommentsVisibility();
void updateAfterDrag(); void updateAfterDrag();
void ctrlEnterSubmitUpdated(); void updateFieldSubmitSettings();
void setInnerFocus(); void setInnerFocus();
bool canSendMessages(PeerData *peer) const; bool canSendMessages(PeerData *peer) const;
@ -813,8 +807,20 @@ public slots:
// in the scroll area and preloads history if needed // in the scroll area and preloads history if needed
void preloadHistoryIfNeeded(); void preloadHistoryIfNeeded();
private slots:
void onInlineBotCancel();
private: private:
// Updates position of controls around the message field,
// like send button, emoji button and others.
void moveFieldControls();
void updateFieldSize();
void clearInlineBot();
void inlineBotChanged();
MsgId _replyToId = 0; MsgId _replyToId = 0;
Text _replyToName; Text _replyToName;
int _replyToNameVersion = 0; int _replyToNameVersion = 0;
@ -950,6 +956,9 @@ private:
void writeDrafts(HistoryDraft **msgDraft, HistoryEditDraft **editDraft); void writeDrafts(HistoryDraft **msgDraft, HistoryEditDraft **editDraft);
void writeDrafts(History *history); void writeDrafts(History *history);
void setFieldText(const QString &text, int32 textUpdateEventsFlags = 0, bool clearUndoHistory = true); void setFieldText(const QString &text, int32 textUpdateEventsFlags = 0, bool clearUndoHistory = true);
void clearFieldText(int32 textUpdateEventsFlags = 0, bool clearUndoHistory = true) {
setFieldText(QString());
}
QStringList getMediasFromMime(const QMimeData *d); QStringList getMediasFromMime(const QMimeData *d);
@ -998,9 +1007,11 @@ private:
CollapseButton _collapseComments; CollapseButton _collapseComments;
MentionsDropdown _attachMention; MentionsDropdown _attachMention;
UserData *_inlineBot = nullptr; UserData *_inlineBot = nullptr;
QString _inlineBotUsername; QString _inlineBotUsername;
mtpRequestId _inlineBotResolveRequestId = 0; mtpRequestId _inlineBotResolveRequestId = 0;
UniquePointer<IconedButton> _inlineBotCancel;
void inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result); void inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result);
bool inlineBotResolveFail(QString name, const RPCError &error); bool inlineBotResolveFail(QString name, const RPCError &error);

View File

@ -723,6 +723,15 @@ void MainWidget::onFilesOrForwardDrop(const PeerId &peer, const QMimeData *data)
} }
} }
void MainWidget::rpcClear() {
history.rpcClear();
dialogs.rpcClear();
if (profile) profile->rpcClear();
if (overview) overview->rpcClear();
if (_api) _api->rpcClear();
RPCSender::rpcClear();
}
QPixmap MainWidget::grabInner() { QPixmap MainWidget::grabInner() {
if (overview && !overview->isHidden()) { if (overview && !overview->isHidden()) {
return myGrab(overview); return myGrab(overview);
@ -2306,7 +2315,7 @@ void MainWidget::updateAfterDrag() {
} }
void MainWidget::ctrlEnterSubmitUpdated() { void MainWidget::ctrlEnterSubmitUpdated() {
history.ctrlEnterSubmitUpdated(); history.updateFieldSubmitSettings();
} }
void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool back) { void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool back) {

View File

@ -20,17 +20,24 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include "apiwrap.h"
#include "dialogswidget.h" #include "dialogswidget.h"
#include "historywidget.h" #include "historywidget.h"
#include "profilewidget.h" #include "profilewidget.h"
#include "overviewwidget.h" #include "overviewwidget.h"
#include "playerwidget.h" #include "playerwidget.h"
#include "apiwrap.h"
class Window; class Window;
struct DialogRow; struct DialogRow;
class ApiWrap;
class MainWidget; class MainWidget;
class ConfirmBox; class ConfirmBox;
class DialogsWidget;
class HistoryWidget;
class ProfileWidget;
class OverviewWidget;
class PlayerWidget;
class TopBarWidget : public TWidget { class TopBarWidget : public TWidget {
Q_OBJECT Q_OBJECT
@ -433,14 +440,7 @@ public:
QPixmap grabTopBar(); QPixmap grabTopBar();
QPixmap grabInner(); QPixmap grabInner();
void rpcClear() override { void rpcClear() override;
history.rpcClear();
dialogs.rpcClear();
if (profile) profile->rpcClear();
if (overview) overview->rpcClear();
if (_api) _api->rpcClear();
RPCSender::rpcClear();
}
bool isItemVisible(HistoryItem *item); bool isItemVisible(HistoryItem *item);
@ -620,8 +620,8 @@ private:
DialogsWidget dialogs; DialogsWidget dialogs;
HistoryWidget history; HistoryWidget history;
ProfileWidget *profile = nullptr; ProfileWidget* profile = nullptr;
OverviewWidget *overview = nullptr; OverviewWidget* overview = nullptr;
PlayerWidget _player; PlayerWidget _player;
TopBarWidget _topBar; TopBarWidget _topBar;
ConfirmBox *_forwardConfirm = nullptr; // for single column layout ConfirmBox *_forwardConfirm = nullptr; // for single column layout

View File

@ -241,7 +241,7 @@ void IconedButton::onStateChange(int oldState, ButtonStateChangeSource source) {
} }
void IconedButton::paintEvent(QPaintEvent *e) { void IconedButton::paintEvent(QPaintEvent *e) {
QPainter p(this); Painter p(this);
p.setOpacity(_opacity); p.setOpacity(_opacity);
@ -256,10 +256,16 @@ void IconedButton::paintEvent(QPaintEvent *e) {
const QPoint &t((_state & StateDown) ? _st.downTextPos : _st.textPos); const QPoint &t((_state & StateDown) ? _st.downTextPos : _st.textPos);
p.drawText(t.x(), t.y() + _st.font->ascent, _text); p.drawText(t.x(), t.y() + _st.font->ascent, _text);
} }
const QRect &i((_state & StateDown) ? _st.downIcon : _st.icon); const style::sprite &i((_state & StateDown) ? _st.downIcon : _st.icon);
if (i.width()) { if (i.pxWidth()) {
const QPoint &t((_state & StateDown) ? _st.downIconPos : _st.iconPos); QPoint t((_state & StateDown) ? _st.downIconPos : _st.iconPos);
p.drawPixmap(t, App::sprite(), i); if (t.x() < 0) {
t.setX((width() - i.pxWidth()) / 2);
}
if (t.y() < 0) {
t.setY((height() - i.pxHeight()) / 2);
}
p.drawSprite(t, i);
} }
} }

View File

@ -25,27 +25,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "window.h" #include "window.h"
FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &pholder, const QString &v) : QTextEdit(parent) FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &pholder, const QString &v) : QTextEdit(parent)
, _minHeight(-1)
, _maxHeight(-1)
, _maxLength(-1)
, _ctrlEnterSubmit(true)
, _oldtext(v) , _oldtext(v)
, _phAfter(0)
, _phVisible(!v.length()) , _phVisible(!v.length())
, a_phLeft(_phVisible ? 0 : st.phShift) , a_phLeft(_phVisible ? 0 : st.phShift)
, a_phAlpha(_phVisible ? 1 : 0) , a_phAlpha(_phVisible ? 1 : 0)
, a_phColor(st.phColor->c) , a_phColor(st.phColor->c)
, _a_appearance(animation(this, &FlatTextarea::step_appearance)) , _a_appearance(animation(this, &FlatTextarea::step_appearance))
, _st(st) , _st(st) {
, _undoAvailable(false)
, _redoAvailable(false)
, _inDrop(false)
, _inHeightCheck(false)
, _fakeMargin(0)
, _touchPress(false)
, _touchRightButton(false)
, _touchMove(false)
, _correcting(false) {
setAcceptRichText(false); setAcceptRichText(false);
resize(_st.width, _st.font->height); resize(_st.width, _st.font->height);
@ -270,7 +256,10 @@ EmojiPtr FlatTextarea::getSingleEmoji() const {
return 0; return 0;
} }
QString FlatTextarea::getInlineBotQuery(UserData *&inlineBot, QString &inlineBotUsername) const { QString FlatTextarea::getInlineBotQuery(UserData **outInlineBot, QString *outInlineBotUsername) const {
t_assert(outInlineBot != nullptr);
t_assert(outInlineBotUsername != nullptr);
const QString &text(getLastText()); const QString &text(getLastText());
int32 inlineUsernameStart = 1, inlineUsernameLength = 0, size = text.size(); int32 inlineUsernameStart = 1, inlineUsernameLength = 0, size = text.size();
@ -288,23 +277,23 @@ QString FlatTextarea::getInlineBotQuery(UserData *&inlineBot, QString &inlineBot
} }
if (inlineUsernameLength && inlineUsernameStart + inlineUsernameLength < text.size() && text.at(inlineUsernameStart + inlineUsernameLength).isSpace()) { if (inlineUsernameLength && inlineUsernameStart + inlineUsernameLength < text.size() && text.at(inlineUsernameStart + inlineUsernameLength).isSpace()) {
QStringRef username = text.midRef(inlineUsernameStart, inlineUsernameLength); QStringRef username = text.midRef(inlineUsernameStart, inlineUsernameLength);
if (username != inlineBotUsername) { if (username != *outInlineBotUsername) {
inlineBotUsername = username.toString(); *outInlineBotUsername = username.toString();
PeerData *peer = App::peerByName(inlineBotUsername); PeerData *peer = App::peerByName(*outInlineBotUsername);
if (peer) { if (peer) {
if (peer->isUser()) { if (peer->isUser()) {
inlineBot = peer->asUser(); *outInlineBot = peer->asUser();
} else { } else {
inlineBot = 0; *outInlineBot = nullptr;
} }
} else { } else {
inlineBot = LookingUpInlineBot; *outInlineBot = LookingUpInlineBot;
} }
} }
if (inlineBot == LookingUpInlineBot) return QString(); if (*outInlineBot == LookingUpInlineBot) return QString();
if (inlineBot && (!inlineBot->botInfo || inlineBot->botInfo->inlinePlaceholder.isEmpty())) { if (*outInlineBot && (!(*outInlineBot)->botInfo || (*outInlineBot)->botInfo->inlinePlaceholder.isEmpty())) {
inlineBot = 0; *outInlineBot = nullptr;
} else { } else {
return text.mid(inlineUsernameStart + inlineUsernameLength + 1); return text.mid(inlineUsernameStart + inlineUsernameLength + 1);
} }
@ -313,8 +302,8 @@ QString FlatTextarea::getInlineBotQuery(UserData *&inlineBot, QString &inlineBot
} }
} }
if (inlineUsernameLength < 3) { if (inlineUsernameLength < 3) {
inlineBot = 0; *outInlineBot = nullptr;
inlineBotUsername = QString(); *outInlineBotUsername = QString();
} }
return QString(); return QString();
} }
@ -945,14 +934,21 @@ QMimeData *FlatTextarea::createMimeDataFromSelection() const {
return result; return result;
} }
void FlatTextarea::setCtrlEnterSubmit(bool ctrlEnterSubmit) { void FlatTextarea::setSubmitSettings(SubmitSettings settings) {
_ctrlEnterSubmit = ctrlEnterSubmit; _submitSettings = settings;
} }
void FlatTextarea::keyPressEvent(QKeyEvent *e) { void FlatTextarea::keyPressEvent(QKeyEvent *e) {
bool shift = e->modifiers().testFlag(Qt::ShiftModifier); bool shift = e->modifiers().testFlag(Qt::ShiftModifier);
bool macmeta = (cPlatform() == dbipMac || cPlatform() == dbipMacOld) && e->modifiers().testFlag(Qt::ControlModifier) && !e->modifiers().testFlag(Qt::MetaModifier) && !e->modifiers().testFlag(Qt::AltModifier); bool macmeta = (cPlatform() == dbipMac || cPlatform() == dbipMacOld) && e->modifiers().testFlag(Qt::ControlModifier) && !e->modifiers().testFlag(Qt::MetaModifier) && !e->modifiers().testFlag(Qt::AltModifier);
bool ctrl = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::MetaModifier), ctrlGood = (ctrl && _ctrlEnterSubmit) || (!ctrl && !shift && !_ctrlEnterSubmit) || (ctrl && shift); bool ctrl = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::MetaModifier);
bool enterSubmit = (ctrl && shift);
if (ctrl && _submitSettings != SubmitSettings::None && _submitSettings != SubmitSettings::Enter) {
enterSubmit = true;
}
if (!ctrl && _submitSettings != SubmitSettings::None && _submitSettings != SubmitSettings::CtrlEnter) {
enterSubmit = true;
}
bool enter = (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return); bool enter = (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return);
if (macmeta && e->key() == Qt::Key_Backspace) { if (macmeta && e->key() == Qt::Key_Backspace) {
@ -960,7 +956,7 @@ void FlatTextarea::keyPressEvent(QKeyEvent *e) {
start.movePosition(QTextCursor::StartOfLine); start.movePosition(QTextCursor::StartOfLine);
tc.setPosition(start.position(), QTextCursor::KeepAnchor); tc.setPosition(start.position(), QTextCursor::KeepAnchor);
tc.removeSelectedText(); tc.removeSelectedText();
} else if (enter && ctrlGood) { } else if (enter && enterSubmit) {
emit submitted(ctrl && shift); emit submitted(ctrl && shift);
} else if (e->key() == Qt::Key_Escape) { } else if (e->key() == Qt::Key_Escape) {
emit cancelled(); emit cancelled();

View File

@ -67,7 +67,12 @@ public:
EmojiPtr getSingleEmoji() const; EmojiPtr getSingleEmoji() const;
QString getMentionHashtagBotCommandPart(bool &start) const; QString getMentionHashtagBotCommandPart(bool &start) const;
QString getInlineBotQuery(UserData *&contextBot, QString &contextBotUsername) const;
// Get the current inline bot and request string for it.
// The *outInlineBot can be filled by LookingUpInlineBot shared ptr.
// In that case the caller should lookup the bot by *outInlineBotUsername.
QString getInlineBotQuery(UserData **outInlineBot, QString *outInlineBotUsername) const;
void removeSingleEmoji(); void removeSingleEmoji();
bool hasText() const; bool hasText() const;
@ -80,7 +85,14 @@ public:
void insertFromMimeData(const QMimeData *source); void insertFromMimeData(const QMimeData *source);
QMimeData *createMimeDataFromSelection() const; QMimeData *createMimeDataFromSelection() const;
void setCtrlEnterSubmit(bool ctrlEnterSubmit);
enum class SubmitSettings {
None,
Enter,
CtrlEnter,
Both,
};
void setSubmitSettings(SubmitSettings settings);
void setTextFast(const QString &text, bool clearUndoHistory = true); void setTextFast(const QString &text, bool clearUndoHistory = true);
@ -123,12 +135,13 @@ private:
void processDocumentContentsChange(int position, int charsAdded); void processDocumentContentsChange(int position, int charsAdded);
bool heightAutoupdated(); bool heightAutoupdated();
int32 _minHeight, _maxHeight; // < 0 - no autosize int _minHeight = -1; // < 0 - no autosize
int32 _maxLength; int _maxHeight = -1;
bool _ctrlEnterSubmit; int _maxLength = -1;
SubmitSettings _submitSettings = SubmitSettings::Enter;
QString _ph, _phelided, _oldtext; QString _ph, _phelided, _oldtext;
int32 _phAfter; int _phAfter = 0;
bool _phVisible; bool _phVisible;
anim::ivalue a_phLeft; anim::ivalue a_phLeft;
anim::fvalue a_phAlpha; anim::fvalue a_phAlpha;
@ -137,15 +150,20 @@ private:
style::flatTextarea _st; style::flatTextarea _st;
bool _undoAvailable, _redoAvailable, _inDrop, _inHeightCheck; bool _undoAvailable = false;
bool _redoAvailable = false;
bool _inDrop = false;
bool _inHeightCheck = false;
int32 _fakeMargin; int _fakeMargin = 0;
QTimer _touchTimer; QTimer _touchTimer;
bool _touchPress, _touchRightButton, _touchMove; bool _touchPress = false;
bool _touchRightButton = false;
bool _touchMove = false;
QPoint _touchStart; QPoint _touchStart;
bool _correcting; bool _correcting = false;
typedef QPair<int, int> LinkRange; typedef QPair<int, int> LinkRange;
typedef QList<LinkRange> LinkRanges; typedef QList<LinkRange> LinkRanges;