diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index cba51885dc..2fd7b43545 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -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..."; diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index 03d6f6da6d..28a8abd507 100644 --- a/Telegram/Resources/winrc/Telegram.rc +++ b/Telegram/Resources/winrc/Telegram.rc @@ -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" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index 33eaa43c40..c5d87b5225 100644 --- a/Telegram/Resources/winrc/Updater.rc +++ b/Telegram/Resources/winrc/Updater.rc @@ -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" diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index 65c5c451dd..c57418a802 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -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"; diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index b20845d8f6..b5c7d2c6ed 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -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; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 95ca7cbde5..10fe2546b4 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -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 @@ -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(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(to)); } else { + if (_recording) { + // Just fix some strange inconsistency. + _send->clearState(); + } if (!_editMsgId) { if (_replyToId || !_field->isEmpty()) { _history->setLocalDraft(std_::make_unique(_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()) { diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index cabbcabba0..6af3b12669 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -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 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 _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; - object_ptr _send; + object_ptr _send; object_ptr _unblock; object_ptr _botStart; object_ptr _joinChannel; @@ -1119,14 +1126,11 @@ private: bool _cmdStartShown = false; object_ptr _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 _recordRipple; int _recordCancelWidth; // This can animate for a very long time (like in music playing), diff --git a/Telegram/SourceFiles/settings/settings_general_widget.cpp b/Telegram/SourceFiles/settings/settings_general_widget.cpp index 3e870a06a9..613bf50213 100644 --- a/Telegram/SourceFiles/settings/settings_general_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_general_widget.cpp @@ -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())); diff --git a/Telegram/SourceFiles/settings/settings_general_widget.h b/Telegram/SourceFiles/settings/settings_general_widget.h index 6b4d4f0995..412b4de405 100644 --- a/Telegram/SourceFiles/settings/settings_general_widget.h +++ b/Telegram/SourceFiles/settings/settings_general_widget.h @@ -70,6 +70,7 @@ private: State _state = State::None; QString _downloadText; + QString _versionText; }; #endif // !TDESKTOP_DISABLE_AUTOUPDATE diff --git a/Telegram/SourceFiles/ui/abstract_button.h b/Telegram/SourceFiles/ui/abstract_button.h index 97fe8e0bea..24b8d20017 100644 --- a/Telegram/SourceFiles/ui/abstract_button.h +++ b/Telegram/SourceFiles/ui/abstract_button.h @@ -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; diff --git a/Telegram/SourceFiles/ui/buttons/history_down_button.cpp b/Telegram/SourceFiles/ui/buttons/history_down_button.cpp index b4b1535c29..696b7c8fc8 100644 --- a/Telegram/SourceFiles/ui/buttons/history_down_button.cpp +++ b/Telegram/SourceFiles/ui/buttons/history_down_button.cpp @@ -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 diff --git a/Telegram/SourceFiles/ui/buttons/history_down_button.h b/Telegram/SourceFiles/ui/buttons/history_down_button.h index d19dce1766..675e33d49f 100644 --- a/Telegram/SourceFiles/ui/buttons/history_down_button.h +++ b/Telegram/SourceFiles/ui/buttons/history_down_button.h @@ -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 &&callback) { + _recordStartCallback = std_::move(callback); + } + void setRecordUpdateCallback(base::lambda &&callback) { + _recordUpdateCallback = std_::move(callback); + } + void setRecordStopCallback(base::lambda &&callback) { + _recordStopCallback = std_::move(callback); + } + void setRecordAnimationCallback(base::lambda &&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 _recordStartCallback; + base::lambda _recordStopCallback; + base::lambda _recordUpdateCallback; + base::lambda _recordAnimationCallback; + +}; + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/widgets/buttons.cpp b/Telegram/SourceFiles/ui/widgets/buttons.cpp index fbb449c5c5..302b435c63 100644 --- a/Telegram/SourceFiles/ui/widgets/buttons.cpp +++ b/Telegram/SourceFiles/ui/widgets/buttons.cpp @@ -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) { diff --git a/Telegram/SourceFiles/ui/widgets/buttons.h b/Telegram/SourceFiles/ui/widgets/buttons.h index 2c4629e2ce..cd536aeeb1 100644 --- a/Telegram/SourceFiles/ui/widgets/buttons.h +++ b/Telegram/SourceFiles/ui/widgets/buttons.h @@ -75,6 +75,7 @@ protected: QPoint disabledRippleStartPosition() const { return QPoint(-0x3FFFFFFF, -0x3FFFFFFF); } + void resetRipples(); private: void ensureRipple(); diff --git a/Telegram/SourceFiles/window/top_bar_widget.cpp b/Telegram/SourceFiles/window/top_bar_widget.cpp index e57a026594..8abc851813 100644 --- a/Telegram/SourceFiles/window/top_bar_widget.cpp +++ b/Telegram/SourceFiles/window/top_bar_widget.cpp @@ -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() { diff --git a/Telegram/SourceFiles/window/top_bar_widget.h b/Telegram/SourceFiles/window/top_bar_widget.h index caae980213..488d5f29b0 100644 --- a/Telegram/SourceFiles/window/top_bar_widget.h +++ b/Telegram/SourceFiles/window/top_bar_widget.h @@ -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 _clearSelection; object_ptr _forward, _delete; diff --git a/Telegram/SourceFiles/window/window.style b/Telegram/SourceFiles/window/window.style index 7db7391eeb..68e77d7538 100644 --- a/Telegram/SourceFiles/window/window.style +++ b/Telegram/SourceFiles/window/window.style @@ -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 diff --git a/Telegram/SourceFiles/window/window_theme_preview.cpp b/Telegram/SourceFiles/window/window_theme_preview.cpp index ea4a0facd2..19b717f1fe 100644 --- a/Telegram/SourceFiles/window/window_theme_preview.cpp +++ b/Telegram/SourceFiles/window/window_theme_preview.cpp @@ -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]); diff --git a/Telegram/build/version b/Telegram/build/version index 0ef9edf861..bd290c082f 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -3,4 +3,4 @@ AppVersionStrMajor 0.10 AppVersionStrSmall 0.10.20 AppVersionStr 0.10.20 AlphaChannel 0 -BetaVersion 10020004 +BetaVersion 10020005