Closed beta 10020005: Added several buttons animations.

This commit is contained in:
John Preston 2016-12-27 02:46:36 +04:00
parent ef927c8465
commit 38e6a0ae7e
19 changed files with 445 additions and 227 deletions

View File

@ -263,7 +263,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_settings_change_lang" = "Change language";
"lng_languages" = "Languages";
"lng_sure_save_language" = "Telegram will restart in order to change language";
"lng_settings_update_automatically" = "Update automatically (ver. {version})";
"lng_settings_update_automatically" = "Update automatically";
"lng_settings_current_version_label" = "Version {version}:";
"lng_settings_current_version" = "Version {version}";
"lng_settings_check_now" = "Check for updates";
"lng_settings_update_checking" = "Checking for updates...";

View File

@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,10,20,4
PRODUCTVERSION 0,10,20,4
FILEVERSION 0,10,20,5
PRODUCTVERSION 0,10,20,5
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -51,10 +51,10 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileVersion", "0.10.20.4"
VALUE "FileVersion", "0.10.20.5"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.10.20.4"
VALUE "ProductVersion", "0.10.20.5"
END
END
BLOCK "VarFileInfo"

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,10,20,4
PRODUCTVERSION 0,10,20,4
FILEVERSION 0,10,20,5
PRODUCTVERSION 0,10,20,5
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -43,10 +43,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Updater"
VALUE "FileVersion", "0.10.20.4"
VALUE "FileVersion", "0.10.20.5"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.10.20.4"
VALUE "ProductVersion", "0.10.20.5"
END
END
BLOCK "VarFileInfo"

View File

@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "core/utils.h"
#define BETA_VERSION_MACRO (10020004ULL)
#define BETA_VERSION_MACRO (10020005ULL)
constexpr int AppVersion = 10020;
constexpr str_const AppVersionStr = "0.10.20";

View File

@ -208,20 +208,18 @@ historyUnblock: FlatButton(historyComposeButton) {
historySendIcon: icon {{ "send_control_send", historySendIconFg }};
historySendIconOver: icon {{ "send_control_send", historySendIconFgOver }};
historySend: IconButton {
width: 46px;
height: 46px;
icon: historySendIcon;
iconOver: historySendIconOver;
iconPosition: point(11px, 11px);
}
historySendIconPosition: point(11px, 11px);
historySendSize: size(46px, 46px);
historyEditSaveIcon: icon {{ "send_control_save", historySendIconFg, point(3px, 7px) }};
historyEditSaveIconOver: icon {{ "send_control_save", historySendIconFgOver, point(3px, 7px) }};
historyAttach: IconButton(historySend) {
historyAttach: IconButton {
width: 46px;
height: 46px;
icon: icon {{ "send_control_attach", historyComposeIconFg }};
iconOver: icon {{ "send_control_attach", historyComposeIconFgOver }};
iconPosition: point(11px, 11px);
rippleAreaPosition: point(3px, 3px);
rippleAreaSize: 40px;
@ -259,7 +257,7 @@ historyBotCommandStart: IconButton(historyAttach) {
historyRecordVoiceFg: historyComposeIconFg;
historyRecordVoiceFgOver: historyComposeIconFgOver;
historyRecordVoiceFgActive: windowBgActive;
historyRecordVoiceDuration: 200;
historyRecordVoiceDuration: 120;
historyRecordVoice: icon {{ "send_control_record", historyRecordVoiceFg }};
historyRecordVoiceOver: icon {{ "send_control_record", historyRecordVoiceFgOver }};
historyRecordVoiceActive: icon {{ "send_control_record", historyRecordVoiceFgActive }};
@ -303,11 +301,6 @@ historyReplyCancel: IconButton {
color: windowBgOver;
}
}
historyInlineBotCancel: IconButton(historyReplyCancel) {
height: 46px;
rippleAreaPosition: point(4px, 3px);
}
reportSpamHide: FlatButton {
color: windowActiveTextFg;

View File

@ -2354,7 +2354,7 @@ void HistoryInner::onParentGeometryChanged() {
}
MessageField::MessageField(HistoryWidget *history, const style::FlatTextarea &st, const QString &ph, const QString &val) : Ui::FlatTextarea(history, st, ph, val), history(history) {
setMinHeight(st::historySend.height - 2 * st::historySendPadding);
setMinHeight(st::historySendSize.height() - 2 * st::historySendPadding);
setMaxHeight(st::historyComposeFieldMaxHeight);
}
@ -3027,7 +3027,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
, _historyDown(_scroll, st::historyToDown)
, _fieldAutocomplete(this)
, _reportSpamPanel(this)
, _send(this, st::historySend)
, _send(this)
, _unblock(this, lang(lng_unblock_button).toUpper(), st::historyUnblock)
, _botStart(this, lang(lng_bot_start).toUpper(), st::historyComposeButton)
, _joinChannel(this, lang(lng_channel_join).toUpper(), st::historyComposeButton)
@ -3056,7 +3056,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(_reportSpamPanel, SIGNAL(clearClicked()), this, SLOT(onReportSpamClear()));
connect(_historyDown, SIGNAL(clicked()), this, SLOT(onHistoryToEnd()));
connect(_fieldBarCancel, SIGNAL(clicked()), this, SLOT(onFieldBarCancel()));
connect(_send, SIGNAL(clicked()), this, SLOT(onSend()));
_send->setClickedCallback([this] { sendButtonClicked(); });
connect(_unblock, SIGNAL(clicked()), this, SLOT(onUnblock()));
connect(_botStart, SIGNAL(clicked()), this, SLOT(onBotStart()));
connect(_joinChannel, SIGNAL(clicked()), this, SLOT(onJoinChannel()));
@ -3141,6 +3141,11 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
_joinChannel->hide();
_muteUnmute->hide();
_send->setRecordStartCallback([this] { recordStartCallback(); });
_send->setRecordStopCallback([this](bool active) { recordStopCallback(active); });
_send->setRecordUpdateCallback([this](QPoint globalPos) { recordUpdateCallback(globalPos); });
_send->setRecordAnimationCallback([this] { updateField(); });
_reportSpamPanel->move(0, 0);
_reportSpamPanel->hide();
@ -3286,23 +3291,9 @@ void HistoryWidget::onTextChange() {
}
}
if (cHasAudioCapture()) {
if (!_field->hasSendText() && !readyToForward() && !_editMsgId) {
_previewCancelled = false;
_send->hide();
updateMouseTracking();
mouseMoveEvent(0);
} else if (!_field->isHidden() && _send->isHidden() && (!_inlineBotCancel || _inlineBotCancel->isHidden())) {
if (_inlineBotCancel) {
_send->hide();
_inlineBotCancel->show();
} else {
_send->show();
}
updateMouseTracking();
_a_recordActive.finish();
_inRecord = _inField = false;
}
updateSendButtonType();
if (showRecordButton()) {
_previewCancelled = false;
}
if (updateCmdStartShown()) {
updateControlsVisibility();
@ -4188,6 +4179,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
onBotStart();
_history->clearLocalDraft();
applyDraft();
_send->finishAnimation();
}
return;
}
@ -4319,6 +4311,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
_history->takeLocalDraft(_migrated);
}
applyDraft(false);
_send->finishAnimation();
resizeEvent(nullptr);
if (!_previewCancelled) {
@ -4374,7 +4367,7 @@ void HistoryWidget::updateAfterDrag() {
void HistoryWidget::updateFieldSubmitSettings() {
auto settings = Ui::FlatTextarea::SubmitSettings::Enter;
if (_inlineBotCancel) {
if (_isInlineBot) {
settings = Ui::FlatTextarea::SubmitSettings::None;
} else if (cCtrlEnter()) {
settings = Ui::FlatTextarea::SubmitSettings::CtrlEnter;
@ -4514,7 +4507,6 @@ void HistoryWidget::updateControlsVisibility() {
_scroll->hide();
_kbScroll->hide();
_send->hide();
if (_inlineBotCancel) _inlineBotCancel->hide();
_unblock->hide();
_botStart->hide();
_joinChannel->hide();
@ -4577,7 +4569,6 @@ void HistoryWidget::updateControlsVisibility() {
_kbShown = false;
_fieldAutocomplete->hide();
_send->hide();
if (_inlineBotCancel) _inlineBotCancel->hide();
_botStart->hide();
_attachToggle->hide();
_silent->hide();
@ -4606,7 +4597,6 @@ void HistoryWidget::updateControlsVisibility() {
}
_kbShown = false;
_send->hide();
if (_inlineBotCancel) _inlineBotCancel->hide();
_field->hide();
_attachEmoji->hide();
_botKeyboardShow->hide();
@ -4621,19 +4611,8 @@ void HistoryWidget::updateControlsVisibility() {
_botStart->hide();
_joinChannel->hide();
_muteUnmute->hide();
if (cHasAudioCapture() && !_field->hasSendText() && !readyToForward()) {
_send->hide();
mouseMoveEvent(0);
} else {
if (_inlineBotCancel) {
_inlineBotCancel->show();
_send->hide();
} else {
_send->show();
}
_a_recordActive.finish();
_inRecord = _inField = false;
}
_send->show();
updateSendButtonType();
if (_recording) {
_field->hide();
_attachEmoji->hide();
@ -4698,7 +4677,6 @@ void HistoryWidget::updateControlsVisibility() {
} else {
_fieldAutocomplete->hide();
_send->hide();
if (_inlineBotCancel) _inlineBotCancel->hide();
_unblock->hide();
_botStart->hide();
_joinChannel->hide();
@ -4724,7 +4702,7 @@ void HistoryWidget::updateControlsVisibility() {
}
void HistoryWidget::updateMouseTracking() {
bool trackMouse = !_fieldBarCancel->isHidden() || _pinnedBar || (cHasAudioCapture() && _send->isHidden() && (!_inlineBotCancel || _inlineBotCancel->isHidden()) && !_field->isHidden());
bool trackMouse = !_fieldBarCancel->isHidden() || _pinnedBar;
setMouseTracking(trackMouse);
}
@ -5460,7 +5438,6 @@ void HistoryWidget::showAnimated(Window::SlideDirection direction, const Window:
_field->hide();
_fieldBarCancel->hide();
_send->hide();
if (_inlineBotCancel) _inlineBotCancel->hide();
_unblock->hide();
_botStart->hide();
_joinChannel->hide();
@ -5521,17 +5498,6 @@ void HistoryWidget::historyDownAnimationFinish() {
updateHistoryDownPosition();
}
void HistoryWidget::recordActiveCallback() {
if (_recording) {
updateField();
} else {
update(_send->geometry());
}
if (!_send->isHidden() || (_inlineBotCancel && !_inlineBotCancel->isHidden()) || isBotStart() || isBlocked()) {
_a_recordActive.finish();
}
}
void HistoryWidget::step_recording(float64 ms, bool timer) {
float64 dt = ms / AudioVoiceMsgUpdateView;
if (dt >= 1) {
@ -5582,6 +5548,15 @@ void HistoryWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update
}
}
void HistoryWidget::sendButtonClicked() {
auto type = _send->type();
if (type == Ui::SendButton::Type::Cancel) {
onInlineBotCancel();
} else if (type != Ui::SendButton::Type::Record) {
onSend();
}
}
void HistoryWidget::dragEnterEvent(QDragEnterEvent *e) {
if (!_history || !_canSendMessages) return;
@ -5611,18 +5586,17 @@ void HistoryWidget::leaveEvent(QEvent *e) {
void HistoryWidget::mouseMoveEvent(QMouseEvent *e) {
auto pos = e ? e->pos() : mapFromGlobal(QCursor::pos());
auto inRecord = _send->geometry().contains(pos);
updateOverStates(pos);
}
void HistoryWidget::updateOverStates(QPoint pos) {
auto inField = pos.y() >= (_scroll->y() + _scroll->height()) && pos.y() < height() && pos.x() >= 0 && pos.x() < width();
auto inReplyEdit = QRect(st::historyReplySkip, _field->y() - st::historySendPadding - st::historyReplyHeight, width() - st::historyReplySkip - _fieldBarCancel->width(), st::historyReplyHeight).contains(pos) && (_editMsgId || replyToId());
auto inPinnedMsg = QRect(0, 0, width(), st::historyReplyHeight).contains(pos) && _pinnedBar;
auto inClickable = inRecord || inReplyEdit || inPinnedMsg;
if (inRecord != _inRecord) {
_inRecord = inRecord;
update(_send->geometry());
}
auto inClickable = inReplyEdit || inPinnedMsg;
if (inField != _inField && _recording) {
_inField = inField;
_a_recordActive.start([this] { recordActiveCallback(); }, _inField ? 0. : 1., _inField ? 1. : 0., st::historyRecordVoiceDuration);
_send->setRecordActive(_inField);
}
_inReplyEdit = inReplyEdit;
_inPinnedMsg = inPinnedMsg;
@ -5633,7 +5607,32 @@ void HistoryWidget::mouseMoveEvent(QMouseEvent *e) {
}
void HistoryWidget::leaveToChildEvent(QEvent *e, QWidget *child) { // e -- from enterEvent() of child TWidget
if (hasMouseTracking()) mouseMoveEvent(0);
if (hasMouseTracking()) {
updateOverStates(mapFromGlobal(QCursor::pos()));
}
}
void HistoryWidget::recordStartCallback() {
if (!cHasAudioCapture()) {
return;
}
emit audioCapture()->start();
_recording = _inField = true;
updateControlsVisibility();
activate();
updateField();
_send->setRecordActive(true);
}
void HistoryWidget::recordStopCallback(bool active) {
stopRecording(_peer && active);
}
void HistoryWidget::recordUpdateCallback(QPoint globalPos) {
updateOverStates(mapFromGlobal(globalPos));
}
void HistoryWidget::mouseReleaseEvent(QMouseEvent *e) {
@ -5666,14 +5665,7 @@ void HistoryWidget::stopRecording(bool send) {
activate();
updateField();
if (_inField) {
_a_recordActive.start([this] { recordActiveCallback(); }, 1., 0., st::historyRecordVoiceDuration);
}
if (_recordRipple) {
_recordRipple->lastStop();
}
_send->setRecordActive(false);
}
void HistoryWidget::sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo) { // replyTo != 0 from ReplyKeyboardMarkup, == 0 from cmd links
@ -6016,6 +6008,29 @@ bool HistoryWidget::isMuteUnmute() const {
return _peer && _peer->isChannel() && _peer->asChannel()->isBroadcast() && !_peer->asChannel()->canPublish();
}
bool HistoryWidget::showRecordButton() const {
return cHasAudioCapture() && !_field->hasSendText() && !readyToForward() && !_editMsgId;
}
bool HistoryWidget::showInlineBotCancel() const {
return _inlineBot && (_inlineBot != Ui::LookingUpInlineBot);
}
void HistoryWidget::updateSendButtonType() {
auto type = [this] {
using Type = Ui::SendButton::Type;
if (_editMsgId) {
return Type::Save;
} else if (_isInlineBot) {
return Type::Cancel;
} else if (showRecordButton()) {
return Type::Record;
}
return Type::Send;
};
_send->setType(type());
}
bool HistoryWidget::updateCmdStartShown() {
bool cmdStartShown = false;
if (_history && _peer && ((_peer->isChat() && _peer->asChat()->botStatus > 0) || (_peer->isMegagroup() && _peer->asChannel()->mgInfo->botStatus > 0) || (_peer->isUser() && _peer->asUser()->botInfo))) {
@ -6351,7 +6366,6 @@ void HistoryWidget::moveFieldControls() {
_field->moveToLeft(left, bottom - _field->height() - st::historySendPadding);
auto right = st::historySendRight;
_send->moveToRight(right, buttonsBottom); right += _send->width();
if (_inlineBotCancel) _inlineBotCancel->move(_send->pos());
_attachEmoji->moveToRight(right, buttonsBottom);
_botKeyboardHide->moveToRight(right, buttonsBottom); right += _botKeyboardHide->width();
_botKeyboardShow->moveToRight(right, buttonsBottom);
@ -6395,20 +6409,13 @@ void HistoryWidget::clearInlineBot() {
}
void HistoryWidget::inlineBotChanged() {
bool isInlineBot = _inlineBot && (_inlineBot != Ui::LookingUpInlineBot);
if (isInlineBot && !_inlineBotCancel) {
_inlineBotCancel.create(this, st::historyInlineBotCancel);
connect(_inlineBotCancel, SIGNAL(clicked()), this, SLOT(onInlineBotCancel()));
_inlineBotCancel->setGeometry(_send->geometry());
_attachEmoji->raise();
updateFieldSubmitSettings();
updateControlsVisibility();
} else if (!isInlineBot && _inlineBotCancel) {
_inlineBotCancel.destroy();
bool isInlineBot = showInlineBotCancel();
if (_isInlineBot != isInlineBot) {
_isInlineBot = isInlineBot;
updateFieldPlaceholder();
updateFieldSubmitSettings();
updateControlsVisibility();
}
updateFieldPlaceholder();
}
void HistoryWidget::onFieldResize() {
@ -6438,15 +6445,14 @@ void HistoryWidget::onCheckFieldAutocomplete() {
void HistoryWidget::updateFieldPlaceholder() {
if (_editMsgId) {
_field->setPlaceholder(lang(lng_edit_message_text));
_send->setIconOverride(&st::historyEditSaveIcon, &st::historyEditSaveIconOver);
} else {
if (_inlineBot && _inlineBot != Ui::LookingUpInlineBot) {
_field->setPlaceholder(_inlineBot->botInfo->inlinePlaceholder.mid(1), _inlineBot->username.size() + 2);
} else {
_field->setPlaceholder(lang((_history && _history->isChannel() && !_history->isMegagroup()) ? (_silent->checked() ? lng_broadcast_silent_ph : lng_broadcast_ph) : lng_message_ph));
}
_send->setIconOverride(nullptr);
}
updateSendButtonType();
}
template <typename SendCallback>
@ -7464,22 +7470,6 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
_replyForwardPressed = QRect(0, _field->y() - st::historySendPadding - st::historyReplyHeight, st::historyReplySkip, st::historyReplyHeight).contains(e->pos());
if (_replyForwardPressed && !_fieldBarCancel->isHidden()) {
updateField();
} else if (_inRecord && cHasAudioCapture()) {
emit audioCapture()->start();
_recording = _inField = true;
updateControlsVisibility();
activate();
updateField();
_a_recordActive.start([this] { recordActiveCallback(); }, 0., 1., st::historyRecordVoiceDuration);
if (!_recordRipple) {
auto mask = Ui::RippleAnimation::ellipseMask(QSize(st::historyAttachEmoji.rippleAreaSize, st::historyAttachEmoji.rippleAreaSize));
_recordRipple = std_::make_unique<Ui::RippleAnimation>(st::historyAttachEmoji.ripple, std_::move(mask), [this] { update(_send->geometry()); });
}
_recordRipple->add(mapFromGlobal(QCursor::pos()) - QPoint(_send->x() + (_send->width() - st::historyAttachEmoji.rippleAreaSize) / 2, _send->y() + st::historyAttachEmoji.rippleAreaPosition.y()));
} else if (_inReplyEdit) {
Ui::showPeerHistory(_peer, _editMsgId ? _editMsgId : replyToId());
} else if (_inPinnedMsg) {
@ -7890,6 +7880,10 @@ void HistoryWidget::onEditMessage() {
if (EditCaptionBox::canEdit(to)) {
Ui::show(Box<EditCaptionBox>(to));
} else {
if (_recording) {
// Just fix some strange inconsistency.
_send->clearState();
}
if (!_editMsgId) {
if (_replyToId || !_field->isEmpty()) {
_history->setLocalDraft(std_::make_unique<Data::Draft>(_field, _replyToId, _previewCancelled));
@ -8251,7 +8245,7 @@ void HistoryWidget::updatePreview() {
}
void HistoryWidget::onCancel() {
if (_inlineBotCancel) {
if (_isInlineBot) {
onInlineBotCancel();
} else if (_editMsgId) {
auto original = _replyEditMsg ? _replyEditMsg->originalText() : TextWithEntities();
@ -8684,30 +8678,6 @@ void HistoryWidget::paintEditHeader(Painter &p, const QRect &rect, int left, int
}
}
void HistoryWidget::drawRecordButton(Painter &p, float64 recordActive, TimeMs ms) {
if (_recordRipple) {
auto rippleColor = anim::color(st::historyAttachEmoji.ripple.color, st::historyRecordVoiceRippleBgActive, recordActive);
_recordRipple->paint(p, _send->x() + (_send->width() - st::historyAttachEmoji.rippleAreaSize) / 2, _send->y() + st::historyAttachEmoji.rippleAreaPosition.y(), width(), ms, &rippleColor);
if (_recordRipple->empty()) {
_recordRipple.reset();
}
}
auto fastIcon = [recordActive, this] {
if (recordActive == 1.) {
return &st::historyRecordVoiceActive;
} else if (_inRecord) {
return &st::historyRecordVoiceOver;
}
return &st::historyRecordVoice;
};
fastIcon()->paintInCenter(p, _send->geometry());
if (recordActive > 0. && recordActive < 1.) {
p.setOpacity(recordActive);
st::historyRecordVoiceActive.paintInCenter(p, _send->geometry());
p.setOpacity(1.);
}
}
void HistoryWidget::drawRecording(Painter &p, float64 recordActive) {
p.setPen(Qt::NoPen);
p.setBrush(st::historyRecordSignalColor);
@ -8832,10 +8802,8 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
if (_list) {
if (!_field->isHidden() || _recording) {
drawField(p, r);
if (_send->isHidden() && (!_inlineBotCancel || _inlineBotCancel->isHidden())) {
auto recordActive = _a_recordActive.current(ms, _inField ? 1. : 0.);
drawRecordButton(p, recordActive, ms);
if (_recording) drawRecording(p, recordActive);
if (!_send->isHidden() && _recording) {
drawRecording(p, _send->recordActiveRatio());
}
}
if (_pinnedBar && !_pinnedBar->cancel->isHidden()) {

View File

@ -45,6 +45,7 @@ class PopupMenu;
class IconButton;
class HistoryDownButton;
class EmojiButton;
class SendButton;
class FlatButton;
class LinkButton;
class RoundButton;
@ -841,10 +842,14 @@ private slots:
private:
void animationCallback();
void recordActiveCallback();
void updateOverStates(QPoint pos);
void recordStartCallback();
void recordStopCallback(bool active);
void recordUpdateCallback(QPoint globalPos);
void chooseAttach();
void historyDownAnimationFinish();
void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update);
void sendButtonClicked();
struct SendingFilesLists {
QList<QUrl> nonLocalUrls;
QStringList directories;
@ -925,7 +930,6 @@ private:
void drawField(Painter &p, const QRect &rect);
void paintEditHeader(Painter &p, const QRect &rect, int left, int top) const;
void drawRecordButton(Painter &p, float64 recordActive, TimeMs ms);
void drawRecording(Painter &p, float64 recordActive);
void drawPinnedBar(Painter &p);
@ -1091,7 +1095,7 @@ private:
UserData *_inlineBot = nullptr;
QString _inlineBotUsername;
mtpRequestId _inlineBotResolveRequestId = 0;
object_ptr<Ui::IconButton> _inlineBotCancel = { nullptr };
bool _isInlineBot = false;
void inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result);
bool inlineBotResolveFail(QString name, const RPCError &error);
@ -1100,10 +1104,13 @@ private:
bool isJoinChannel() const;
bool isMuteUnmute() const;
bool updateCmdStartShown();
void updateSendButtonType();
bool showRecordButton() const;
bool showInlineBotCancel() const;
object_ptr<ReportSpamPanel> _reportSpamPanel;
object_ptr<Ui::IconButton> _send;
object_ptr<Ui::SendButton> _send;
object_ptr<Ui::FlatButton> _unblock;
object_ptr<Ui::FlatButton> _botStart;
object_ptr<Ui::FlatButton> _joinChannel;
@ -1119,14 +1126,11 @@ private:
bool _cmdStartShown = false;
object_ptr<MessageField> _field;
bool _recording = false;
bool _inRecord = false;
bool _inField = false;
bool _inReplyEdit = false;
bool _inPinnedMsg = false;
bool _inClickable = false;
int _recordingSamples = 0;
Animation _a_recordActive;
std_::unique_ptr<Ui::RippleAnimation> _recordRipple;
int _recordCancelWidth;
// This can animate for a very long time (like in music playing),

View File

@ -52,6 +52,8 @@ UpdateStateRow::UpdateStateRow(QWidget *parent) : TWidget(parent)
Sandbox::connect(SIGNAL(updateFailed()), this, SLOT(onFailed()));
Sandbox::connect(SIGNAL(updateReady()), this, SLOT(onReady()));
_versionText = lng_settings_current_version_label(lt_version, currentVersionText());
switch (Sandbox::updatingState()) {
case Application::UpdatingDownload:
setState(State::Download, true);
@ -66,7 +68,7 @@ int UpdateStateRow::resizeGetHeight(int newWidth) {
auto labelWidth = [](const QString &label) {
return st::linkFont->width(label) + st::linkFont->spacew;
};
auto checkLeft = (_state == State::Latest) ? labelWidth(lang(lng_settings_latest_installed)) : 0;
auto checkLeft = (_state == State::Latest) ? labelWidth(lang(lng_settings_latest_installed)) : labelWidth(_versionText);
auto restartLeft = labelWidth(lang(lng_settings_update_ready));
_check->resizeToWidth(qMin(newWidth, _check->naturalWidth()));
@ -88,11 +90,11 @@ void UpdateStateRow::paintEvent(QPaintEvent *e) {
case State::Download: return _downloadText;
case State::Ready: return lang(lng_settings_update_ready);
case State::Fail: return lang(lng_settings_update_fail);
default: return QString();
default: return _versionText;
}
})();
p.setFont(st::linkFont);
p.setPen(st::settingsUpdateFg);
p.setPen((_state == State::None) ? st::windowFg : st::settingsUpdateFg);
p.drawTextLeft(0, 0, width(), text);
}
@ -176,7 +178,7 @@ void GeneralWidget::refreshControls() {
style::margins slidedPadding(0, marginSmall.bottom() / 2, 0, marginSmall.bottom() - (marginSmall.bottom() / 2));
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
addChildRow(_updateAutomatically, marginSub, lng_settings_update_automatically(lt_version, currentVersionText()), SLOT(onUpdateAutomatically()), cAutoUpdate());
addChildRow(_updateAutomatically, marginSub, lang(lng_settings_update_automatically), SLOT(onUpdateAutomatically()), cAutoUpdate());
style::margins marginLink(st::defaultBoxCheckbox.textPosition.x(), 0, 0, st::settingsSkip);
addChildRow(_updateRow, marginLink, slidedPadding);
connect(_updateRow->entity(), SIGNAL(restart()), this, SLOT(onRestart()));

View File

@ -70,6 +70,7 @@ private:
State _state = State::None;
QString _downloadText;
QString _versionText;
};
#endif // !TDESKTOP_DISABLE_AUTOUPDATE

View File

@ -54,6 +54,13 @@ public:
_clickedCallback = std_::move(callback);
}
void setVisible(bool visible) override {
TWidget::setVisible(visible);
if (!visible) {
clearState();
}
}
protected:
void enterEvent(QEvent *e) override;
void leaveEvent(QEvent *e) override;

View File

@ -26,6 +26,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/effects/ripple_animation.h"
namespace Ui {
namespace {
constexpr int kWideScale = 5;
} // namespace
HistoryDownButton::HistoryDownButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
, _st(st) {
@ -141,4 +146,147 @@ QImage EmojiButton::prepareRippleMask() const {
return RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
}
SendButton::SendButton(QWidget *parent) : RippleButton(parent, st::historyReplyCancel.ripple) {
resize(st::historySendSize);
}
void SendButton::setType(Type type) {
if (_type != type) {
_contentFrom = grabContent();
_type = type;
_a_typeChanged.finish();
_contentTo = grabContent();
_a_typeChanged.start([this] { update(); }, 0., 1., st::historyRecordVoiceDuration);
update();
}
if (_type != Type::Record) {
_recordActive = false;
_a_recordActive.finish();
}
}
void SendButton::setRecordActive(bool recordActive) {
if (_recordActive != recordActive) {
_recordActive = recordActive;
_a_recordActive.start([this] { recordAnimationCallback(); }, _recordActive ? 0. : 1., _recordActive ? 1. : 0, st::historyRecordVoiceDuration);
update();
}
}
void SendButton::finishAnimation() {
_a_typeChanged.finish();
_a_recordActive.finish();
update();
}
void SendButton::mouseMoveEvent(QMouseEvent *e) {
AbstractButton::mouseMoveEvent(e);
if (_recording) {
if (_recordUpdateCallback) {
_recordUpdateCallback(e->globalPos());
}
}
}
void SendButton::paintEvent(QPaintEvent *e) {
Painter p(this);
auto ms = getms();
auto over = (isDown() || isOver());
auto changed = _a_typeChanged.current(ms, 1.);
if (changed < 1.) {
PainterHighQualityEnabler hq(p);
p.setOpacity(1. - changed);
auto targetRect = QRect((1 - kWideScale) / 2 * width(), (1 - kWideScale) / 2 * height(), kWideScale * width(), kWideScale * height());
auto hiddenWidth = anim::interpolate(0, (1 - kWideScale) / 2 * width(), changed);
auto hiddenHeight = anim::interpolate(0, (1 - kWideScale) / 2 * height(), changed);
p.drawPixmap(targetRect.marginsAdded(QMargins(hiddenWidth, hiddenHeight, hiddenWidth, hiddenHeight)), _contentFrom);
p.setOpacity(changed);
auto shownWidth = anim::interpolate((1 - kWideScale) / 2 * width(), 0, changed);
auto shownHeight = anim::interpolate((1 - kWideScale) / 2 * height(), 0, changed);
p.drawPixmap(targetRect.marginsAdded(QMargins(shownWidth, shownHeight, shownWidth, shownHeight)), _contentTo);
} else if (_type == Type::Record) {
auto recordActive = recordActiveRatio();
auto rippleColor = anim::color(st::historyAttachEmoji.ripple.color, st::historyRecordVoiceRippleBgActive, recordActive);
paintRipple(p, (width() - st::historyAttachEmoji.rippleAreaSize) / 2, st::historyAttachEmoji.rippleAreaPosition.y(), ms, &rippleColor);
auto fastIcon = [recordActive, over, this] {
if (recordActive == 1.) {
return &st::historyRecordVoiceActive;
} else if (over) {
return &st::historyRecordVoiceOver;
}
return &st::historyRecordVoice;
};
fastIcon()->paintInCenter(p, rect());
if (recordActive > 0. && recordActive < 1.) {
p.setOpacity(recordActive);
st::historyRecordVoiceActive.paintInCenter(p, rect());
p.setOpacity(1.);
}
} else if (_type == Type::Save) {
auto &saveIcon = over ? st::historyEditSaveIconOver : st::historyEditSaveIcon;
saveIcon.paint(p, st::historySendIconPosition, width());
} else if (_type == Type::Cancel) {
paintRipple(p, (width() - st::historyAttachEmoji.rippleAreaSize) / 2, st::historyAttachEmoji.rippleAreaPosition.y(), ms);
auto &cancelIcon = over ? st::historyReplyCancelIconOver : st::historyReplyCancelIcon;
cancelIcon.paintInCenter(p, rect());
} else {
auto &sendIcon = over ? st::historySendIconOver : st::historySendIcon;
sendIcon.paint(p, st::historySendIconPosition, width());
}
}
void SendButton::onStateChanged(State was, StateChangeSource source) {
RippleButton::onStateChanged(was, source);
auto down = (state() & StateFlag::Down);
if ((was & StateFlag::Down) != down) {
if (down) {
if (_type == Type::Record) {
_recording = true;
if (_recordStartCallback) {
_recordStartCallback();
}
}
} else if (_recording) {
_recording = false;
if (_recordStopCallback) {
_recordStopCallback(_recordActive);
}
}
}
}
QPixmap SendButton::grabContent() {
auto result = QImage(kWideScale * size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
result.setDevicePixelRatio(cRetinaFactor());
result.fill(Qt::transparent);
{
Painter p(&result);
p.drawPixmap((kWideScale - 1) / 2 * width(), (kWideScale - 1) / 2 * height(), myGrab(this));
}
return App::pixmapFromImageInPlace(std_::move(result));
}
QImage SendButton::prepareRippleMask() const {
auto size = (_type == Type::Record) ? st::historyAttachEmoji.rippleAreaSize : st::historyReplyCancel.rippleAreaSize;
return Ui::RippleAnimation::ellipseMask(QSize(size, size));
}
QPoint SendButton::prepareRippleStartPosition() const {
auto real = mapFromGlobal(QCursor::pos());
auto size = (_type == Type::Record) ? st::historyAttachEmoji.rippleAreaSize : st::historyReplyCancel.rippleAreaSize;
auto y = (_type == Type::Record) ? st::historyAttachEmoji.rippleAreaPosition.y() : (height() - st::historyReplyCancel.rippleAreaSize) / 2;
return real - QPoint((width() - size) / 2, y);
}
void SendButton::recordAnimationCallback() {
update();
if (_recordAnimationCallback) {
_recordAnimationCallback();
}
}
} // namespace Ui

View File

@ -75,4 +75,65 @@ private:
};
class SendButton : public RippleButton {
public:
SendButton(QWidget *parent);
enum class Type {
Send,
Save,
Record,
Cancel,
};
Type type() const {
return _type;
}
void setType(Type state);
void setRecordActive(bool recordActive);
void finishAnimation();
void setRecordStartCallback(base::lambda<void()> &&callback) {
_recordStartCallback = std_::move(callback);
}
void setRecordUpdateCallback(base::lambda<void(QPoint globalPos)> &&callback) {
_recordUpdateCallback = std_::move(callback);
}
void setRecordStopCallback(base::lambda<void(bool active)> &&callback) {
_recordStopCallback = std_::move(callback);
}
void setRecordAnimationCallback(base::lambda<void()> &&callback) {
_recordAnimationCallback = std_::move(callback);
}
float64 recordActiveRatio() {
return _a_recordActive.current(getms(), _recordActive ? 1. : 0.);
}
protected:
void mouseMoveEvent(QMouseEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void onStateChanged(State was, StateChangeSource source) override;
QImage prepareRippleMask() const override;
QPoint prepareRippleStartPosition() const override;
private:
void recordAnimationCallback();
QPixmap grabContent();
Type _type = Type::Send;
bool _recordActive = false;
QPixmap _contentFrom, _contentTo;
Animation _a_typeChanged;
Animation _a_recordActive;
bool _recording = false;
base::lambda<void()> _recordStartCallback;
base::lambda<void(bool active)> _recordStopCallback;
base::lambda<void(QPoint globalPos)> _recordUpdateCallback;
base::lambda<void()> _recordAnimationCallback;
};
} // namespace Ui

View File

@ -131,6 +131,10 @@ QPoint RippleButton::prepareRippleStartPosition() const {
return mapFromGlobal(QCursor::pos());
}
void RippleButton::resetRipples() {
_ripple.reset();
}
RippleButton::~RippleButton() = default;
FlatButton::FlatButton(QWidget *parent, const QString &text, const style::FlatButton &st) : RippleButton(parent, st.ripple)
@ -189,7 +193,6 @@ void FlatButton::paintEvent(QPaintEvent *e) {
RoundButton::RoundButton(QWidget *parent, const QString &text, const style::RoundButton &st) : RippleButton(parent, st.ripple)
, _fullText(text)
, _st(st) {
setCursor(style::cur_pointer);
updateText();
}
@ -308,7 +311,6 @@ QPoint RoundButton::prepareRippleStartPosition() const {
IconButton::IconButton(QWidget *parent, const style::IconButton &st) : RippleButton(parent, st.ripple)
, _st(st) {
resize(_st.width, _st.height);
setCursor(style::cur_pointer);
}
void IconButton::setIconOverride(const style::icon *iconOverride, const style::icon *iconOverOverride) {

View File

@ -75,6 +75,7 @@ protected:
QPoint disabledRippleStartPosition() const {
return QPoint(-0x3FFFFFFF, -0x3FFFFFFF);
}
void resetRipples();
private:
void ensureRipple();

View File

@ -156,8 +156,13 @@ bool TopBarWidget::eventFilter(QObject *obj, QEvent *e) {
void TopBarWidget::paintEvent(QPaintEvent *e) {
Painter p(this);
auto hasSelected = (_selectedCount > 0);
auto selectedButtonsTop = countSelectedButtonsTop(_selectedShown.current(getms(), hasSelected ? 1. : 0.));
p.fillRect(QRect(0, 0, width(), st::topBarHeight), st::topBarBg);
if (_clearSelection->isHidden()) {
if (selectedButtonsTop < 0) {
p.translate(0, selectedButtonsTop + st::topBarHeight);
p.save();
auto decreaseWidth = 0;
if (!_info->isHidden()) {
@ -195,32 +200,43 @@ void TopBarWidget::paintUnreadCounter(Painter &p, int outerWidth) {
}
void TopBarWidget::mousePressEvent(QMouseEvent *e) {
if (e->button() == Qt::LeftButton && e->pos().y() < st::topBarHeight && !_selCount) {
if (e->button() == Qt::LeftButton && e->pos().y() < st::topBarHeight && !_selectedCount) {
emit clicked();
}
}
void TopBarWidget::resizeEvent(QResizeEvent *e) {
int buttonsLeft = st::topBarActionSkip + (Adaptive::OneColumn() ? 0 : st::lineWidth);
int buttonsWidth = _forward->contentWidth() + _delete->contentWidth() + _clearSelection->width();
updateControlsGeometry();
}
int TopBarWidget::countSelectedButtonsTop(float64 selectedShown) {
return (1. - selectedShown) * (-st::topBarHeight);
}
void TopBarWidget::updateControlsGeometry() {
auto hasSelected = (_selectedCount > 0);
auto selectedButtonsTop = countSelectedButtonsTop(_selectedShown.current(hasSelected ? 1. : 0.));
auto otherButtonsTop = selectedButtonsTop + st::topBarHeight;
auto buttonsLeft = st::topBarActionSkip + (Adaptive::OneColumn() ? 0 : st::lineWidth);
auto buttonsWidth = _forward->contentWidth() + _delete->contentWidth() + _clearSelection->width();
buttonsWidth += buttonsLeft + st::topBarActionSkip * 3;
int widthLeft = qMin(width() - buttonsWidth, -2 * st::defaultActiveButton.width);
auto widthLeft = qMin(width() - buttonsWidth, -2 * st::defaultActiveButton.width);
_forward->setFullWidth(-(widthLeft / 2));
_delete->setFullWidth(-(widthLeft / 2));
int buttonsTop = (height() - _forward->height()) / 2;
selectedButtonsTop += (height() - _forward->height()) / 2;
_forward->moveToLeft(buttonsLeft, buttonsTop);
_forward->moveToLeft(buttonsLeft, selectedButtonsTop);
buttonsLeft += _forward->width() + st::topBarActionSkip;
_delete->moveToLeft(buttonsLeft, buttonsTop);
_clearSelection->moveToRight(st::topBarActionSkip, buttonsTop);
_delete->moveToLeft(buttonsLeft, selectedButtonsTop);
_clearSelection->moveToRight(st::topBarActionSkip, selectedButtonsTop);
_info->moveToRight(0, 0);
_menuToggle->moveToRight(0, 0);
_mediaType->moveToRight(0, 0);
_search->moveToRight(_info->isHidden() ? _menuToggle->width() : _info->width(), 0);
_info->moveToRight(0, otherButtonsTop);
_menuToggle->moveToRight(0, otherButtonsTop);
_mediaType->moveToRight(0, otherButtonsTop);
_search->moveToRight(_info->isHidden() ? _menuToggle->width() : _info->width(), otherButtonsTop);
}
void TopBarWidget::startAnim() {
@ -247,31 +263,18 @@ void TopBarWidget::stopAnim() {
void TopBarWidget::showAll() {
if (_animating) {
resizeEvent(nullptr);
updateControlsGeometry();
return;
}
auto historyPeer = App::main() ? App::main()->historyPeer() : nullptr;
auto overviewPeer = App::main() ? App::main()->overviewPeer() : nullptr;
if (_selCount) {
_clearSelection->show();
if (_canDelete) {
_delete->show();
} else {
_delete->hide();
}
_forward->show();
_mediaType->hide();
} else {
_clearSelection->hide();
_delete->hide();
_forward->hide();
if (App::main() && App::main()->mediaTypeSwitch()) {
_mediaType->show();
} else {
_mediaType->hide();
}
}
if (historyPeer && !overviewPeer && _clearSelection->isHidden()) {
_clearSelection->show();
_delete->setVisible(_canDelete);
_forward->show();
_mediaType->setVisible(App::main() ? App::main()->mediaTypeSwitch() : false);
if (historyPeer && !overviewPeer) {
if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) {
_info->setPeer(historyPeer);
_info->show();
@ -291,18 +294,18 @@ void TopBarWidget::showAll() {
if (_membersShowArea) {
_membersShowArea->show();
}
resizeEvent(nullptr);
updateControlsGeometry();
}
void TopBarWidget::updateMembersShowArea() {
auto membersShowAreaNeeded = [this]() {
if (_selCount || App::main()->overviewPeer() || !_selPeer) {
if ((_selectedCount > 0) || App::main()->overviewPeer() || !_selectedInPeer) {
return false;
}
if (auto chat = _selPeer->asChat()) {
if (auto chat = _selectedInPeer->asChat()) {
return chat->amIn();
}
if (auto megagroup = _selPeer->asMegagroup()) {
if (auto megagroup = _selectedInPeer->asMegagroup()) {
return megagroup->canViewMembers() && (megagroup->membersCount() < Global::ChatSizeMax());
}
return false;
@ -321,18 +324,36 @@ void TopBarWidget::updateMembersShowArea() {
_membersShowArea->setGeometry(App::main()->getMembersShowAreaGeometry());
}
void TopBarWidget::showSelected(uint32 selCount, bool canDelete) {
_selPeer = App::main()->overviewPeer() ? App::main()->overviewPeer() : App::main()->peer();
_selCount = selCount;
if (_selCount > 0) {
_canDelete = canDelete;
_forward->setSecondaryText(QString::number(_selCount));
_delete->setSecondaryText(QString::number(_selCount));
void TopBarWidget::showSelected(int selectedCount, bool canDelete) {
if (_selectedCount == selectedCount) {
return;
}
setCursor(_selCount ? style::cur_default : style::cur_pointer);
updateMembersShowArea();
showAll();
auto wasSelected = (_selectedCount > 0);
_selectedInPeer = App::main()->overviewPeer() ? App::main()->overviewPeer() : App::main()->peer();
_selectedCount = selectedCount;
if (_selectedCount > 0) {
_forward->setSecondaryText(QString::number(_selectedCount));
_delete->setSecondaryText(QString::number(_selectedCount));
}
auto hasSelected = (_selectedCount > 0);
if (_canDelete != canDelete) {
_canDelete = canDelete;
showAll();
}
if (wasSelected != hasSelected) {
setCursor(hasSelected ? style::cur_default : style::cur_pointer);
updateMembersShowArea();
_selectedShown.start([this] { selectedShowCallback(); }, hasSelected ? 0. : 1., hasSelected ? 1. : 0., st::topBarSlideDuration, anim::easeOutCirc);
} else {
updateControlsGeometry();
}
}
void TopBarWidget::selectedShowCallback() {
updateControlsGeometry();
update();
}
void TopBarWidget::updateAdaptiveLayout() {

View File

@ -40,7 +40,7 @@ public:
void startAnim();
void stopAnim();
void showAll();
void showSelected(uint32 selCount, bool canDelete = false);
void showSelected(int selectedCount, bool canDelete = false);
void updateMembersShowArea();
@ -58,6 +58,9 @@ signals:
void clicked();
private:
void updateControlsGeometry();
void selectedShowCallback();
void onForwardSelection();
void onDeleteSelection();
void onClearSelection();
@ -66,16 +69,19 @@ private:
void showMenu();
void updateAdaptiveLayout();
int countSelectedButtonsTop(float64 selectedShown);
MainWidget *main();
PeerData *_searchInPeer = nullptr;
PeerData *_selPeer = nullptr;
int _selCount = 0;
PeerData *_selectedInPeer = nullptr;
int _selectedCount = 0;
bool _canDelete = false;
bool _animating = false;
Animation _selectedShown;
object_ptr<Ui::RoundButton> _clearSelection;
object_ptr<Ui::RoundButton> _forward, _delete;

View File

@ -82,9 +82,12 @@ notifyReplyArea: InputField(defaultInputField) {
border: 0px;
borderActive: 0px;
}
notifySendReply: IconButton(historySend) {
notifySendReply: IconButton {
width: 36px;
height: 36px;
icon: historySendIcon;
iconOver: historySendIconOver;
iconPosition: point(6px, 6px);
}
@ -126,15 +129,14 @@ mainMenuTelegramLabel: FlatLabel(defaultFlatLabel) {
linkFont: semiboldFont;
linkFontOver: font(fsize semibold underline);
}
}
mainMenuTelegramPalette: TextPalette(defaultTextPalette) {
linkFg: windowSubTextFg;
palette: TextPalette(defaultTextPalette) {
linkFg: windowSubTextFg;
}
}
mainMenuTelegramBottom: 43px;
mainMenuVersionLabel: FlatLabel(mainMenuTelegramLabel) {
style: defaultTextStyle;
}
mainMenuVersionPalette: mainMenuTelegramPalette;
mainMenuVersionBottom: 21px;
// Windows specific title
@ -220,6 +222,7 @@ topBarInfoButton: PeerAvatarButton {
size: topBarHeight;
photoSize: 42px;
}
topBarSlideDuration: 150;
// Mac specific

View File

@ -147,7 +147,7 @@ void Generator::prepare() {
_dialogs = QRect(_body.x(), _body.y(), st::themePreviewDialogsWidth, _body.height());
_dialogsList = _dialogs.marginsRemoved(QMargins(0, st::dialogsFilterPadding.y() + st::dialogsMenuToggle.height + st::dialogsFilterPadding.y(), 0, st::dialogsPadding.y()));
_topBar = QRect(_dialogs.x() + _dialogs.width(), _dialogs.y(), _body.width() - _dialogs.width(), st::topBarHeight);
_composeArea = QRect(_topBar.x(), _body.y() + _body.height() - st::historySend.height, _topBar.width(), st::historySend.height);
_composeArea = QRect(_topBar.x(), _body.y() + _body.height() - st::historySendSize.height(), _topBar.width(), st::historySendSize.height());
_history = QRect(_topBar.x(), _topBar.y() + _topBar.height(), _topBar.width(), _body.height() - _topBar.height() - _composeArea.height());
generateData();
@ -402,10 +402,10 @@ void Generator::paintTopBar() {
void Generator::paintComposeArea() {
_p->fillRect(_composeArea, st::historyReplyBg[_palette]);
auto controlsTop = _composeArea.y() + _composeArea.height() - st::historySend.height;
auto controlsTop = _composeArea.y() + _composeArea.height() - st::historySendSize.height();
st::historyAttach.icon[_palette].paint(*_p, _composeArea.x() + st::historyAttach.iconPosition.x(), controlsTop + st::historyAttach.iconPosition.y(), _rect.width());
auto right = st::historySendRight + st::historySend.width;
st::historyRecordVoice[_palette].paintInCenter(*_p, QRect(_composeArea.x() + _composeArea.width() - right, controlsTop, st::historySend.width, st::historySend.height));
auto right = st::historySendRight + st::historySendSize.width();
st::historyRecordVoice[_palette].paintInCenter(*_p, QRect(_composeArea.x() + _composeArea.width() - right, controlsTop, st::historySendSize.width(), st::historySendSize.height()));
right += st::historyAttachEmoji.width;
auto attachEmojiLeft = _composeArea.x() + _composeArea.width() - right;
@ -431,8 +431,8 @@ void Generator::paintComposeArea() {
auto fieldLeft = _composeArea.x() + st::historyAttach.width + fakeMargin;
auto fieldTop = _composeArea.y() + _composeArea.height() - st::historyAttach.height + st::historySendPadding + fakeMargin;
auto fieldWidth = _composeArea.width() - st::historyAttach.width - st::historySend.width - st::historySendRight - st::historyAttachEmoji.width - 2 * fakeMargin;
auto fieldHeight = st::historySend.height - 2 * st::historySendPadding - 2 * fakeMargin;
auto fieldWidth = _composeArea.width() - st::historyAttach.width - st::historySendSize.width() - st::historySendRight - st::historyAttachEmoji.width - 2 * fakeMargin;
auto fieldHeight = st::historySendSize.height() - 2 * st::historySendPadding - 2 * fakeMargin;
auto field = QRect(fieldLeft, fieldTop, fieldWidth, fieldHeight);
_p->fillRect(field, st::historyComposeField.bgColor[_palette]);

View File

@ -3,4 +3,4 @@ AppVersionStrMajor 0.10
AppVersionStrSmall 0.10.20
AppVersionStr 0.10.20
AlphaChannel 0
BetaVersion 10020004
BetaVersion 10020005