diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp index 897be1926..5a70f2c12 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp @@ -103,6 +103,7 @@ TabbedPanel::TabbedPanel( setAttribute(Qt::WA_OpaquePaintEvent, false); hideChildren(); + hide(); } void TabbedPanel::moveBottomRight(int bottom, int right) { diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_panel.h b/Telegram/SourceFiles/chat_helpers/tabbed_panel.h index 7a04003ca..677bf6836 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_panel.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_panel.h @@ -25,7 +25,9 @@ class TabbedSelector; class TabbedPanel : public Ui::RpWidget { public: - TabbedPanel(QWidget *parent, not_null controller); + TabbedPanel( + QWidget *parent, + not_null controller); TabbedPanel( QWidget *parent, not_null controller, diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 0ab055df0..b085b91bf 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -443,7 +443,6 @@ HistoryWidget::HistoryWidget( _botKeyboardHide->addClickHandler([=] { toggleKeyboard(); }); _botCommandStart->addClickHandler([=] { startBotCommand(); }); - _tabbedPanel->hide(); _attachDragDocument->hide(); _attachDragPhoto->hide(); @@ -3879,8 +3878,7 @@ void HistoryWidget::pushTabbedSelectorToThirdSection( void HistoryWidget::toggleTabbedSelectorMode() { if (_tabbedPanel) { - if (controller()->canShowThirdSection() - && !Adaptive::OneColumn()) { + if (controller()->canShowThirdSection() && !Adaptive::OneColumn()) { session().settings().setTabbedSelectorSectionEnabled(true); session().saveSettingsDelayed(); pushTabbedSelectorToThirdSection( @@ -3899,7 +3897,6 @@ void HistoryWidget::returnTabbedSelector( this, controller(), std::move(selector)); - _tabbedPanel->hide(); _tabbedSelectorToggle->installEventFilter(_tabbedPanel); _tabbedSelectorToggle->setColorOverrides(nullptr, nullptr, nullptr); _tabbedSelectorToggleTooltipShown = false; @@ -3928,7 +3925,7 @@ void HistoryWidget::moveFieldControls() { } // _attachToggle --------- _inlineResults -------------------------------------- _tabbedPanel --------- _fieldBarCancel -// (_attachDocument|_attachPhoto) _field (_scheduled) (_silent|_cmdStart|_kbShow) (_kbHide|_tabbedSelectorToggle) [_broadcast] _send +// (_attachDocument|_attachPhoto) _field (_scheduled) (_silent|_cmdStart|_kbShow) (_kbHide|_tabbedSelectorToggle) _send // (_botStart|_unblock|_joinChannel|{_muteUnmute&_discuss}) auto buttonsBottom = bottom - _attachToggle->height(); diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index ac1580e9e..4b023a287 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -320,6 +320,41 @@ private: using TabbedPanel = ChatHelpers::TabbedPanel; using TabbedSelector = ChatHelpers::TabbedSelector; using DragState = Storage::MimeDataState; + struct BotCallbackInfo { + UserData *bot; + FullMsgId msgId; + int row, col; + bool game; + }; + struct PinnedBar { + PinnedBar(MsgId msgId, HistoryWidget *parent); + ~PinnedBar(); + + MsgId msgId = 0; + HistoryItem *msg = nullptr; + Ui::Text::String text; + object_ptr cancel; + object_ptr shadow; + }; + enum ScrollChangeType { + ScrollChangeNone, + + // When we toggle a pinned message. + ScrollChangeAdd, + + // When loading a history part while scrolling down. + ScrollChangeNoJumpToBottom, + }; + struct ScrollChange { + ScrollChangeType type; + int value; + }; + enum class TextUpdateEvent { + SaveDraft = (1 << 0), + SendTyping = (1 << 1), + }; + using TextUpdateEvents = base::flags; + friend inline constexpr bool is_flag_type(TextUpdateEvent) { return true; }; void initTabbedSelector(); void updateField(); @@ -488,35 +523,9 @@ private: void handlePeerMigration(); - MsgId _replyToId = 0; - Ui::Text::String _replyToName; - int _replyToNameVersion = 0; - - HistoryItemsList _toForward; - Ui::Text::String _toForwardFrom, _toForwardText; - int _toForwardNameVersion = 0; - - MsgId _editMsgId = 0; - - HistoryItem *_replyEditMsg = nullptr; - Ui::Text::String _replyEditMsgText; - mutable base::Timer _updateEditTimeLeftDisplay; - - object_ptr _fieldBarCancel; void updateReplyEditTexts(bool force = false); void updateReplyEditText(not_null item); - struct PinnedBar { - PinnedBar(MsgId msgId, HistoryWidget *parent); - ~PinnedBar(); - - MsgId msgId = 0; - HistoryItem *msg = nullptr; - Ui::Text::String text; - object_ptr cancel; - object_ptr shadow; - }; - std::unique_ptr _pinnedBar; void updatePinnedBar(bool force = false); bool pinnedMsgVisibilityUpdated(); void destroyPinnedBar(); @@ -542,7 +551,6 @@ private: // destroys _history and _migrated unread bars void destroyUnreadBar(); - mtpRequestId _saveEditMsgRequestId = 0; void saveEditMsg(); void saveEditMsgDone(History *history, const MTPUpdates &updates, mtpRequestId req); bool saveEditMsgFail(History *history, const RPCError &error, mtpRequestId req); @@ -550,49 +558,13 @@ private: void checkPreview(); void requestPreview(); void gotPreview(QString links, const MTPMessageMedia &media, mtpRequestId req); - - QStringList _parsedLinks; - QString _previewLinks; - WebPageData *_previewData = nullptr; - typedef QMap PreviewCache; - PreviewCache _previewCache; - mtpRequestId _previewRequest = 0; - Ui::Text::String _previewTitle; - Ui::Text::String _previewDescription; - base::Timer _previewTimer; - bool _previewCancelled = false; - - bool _replyForwardPressed = false; - - HistoryItem *_replyReturn = nullptr; - QList _replyReturns; - bool messagesFailed(const RPCError &error, mtpRequestId requestId); void addMessagesToFront(PeerData *peer, const QVector &messages); void addMessagesToBack(PeerData *peer, const QVector &messages); - struct BotCallbackInfo { - UserData *bot; - FullMsgId msgId; - int row, col; - bool game; - }; void botCallbackDone(BotCallbackInfo info, const MTPmessages_BotCallbackAnswer &answer, mtpRequestId req); bool botCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req); - enum ScrollChangeType { - ScrollChangeNone, - - // When we toggle a pinned message. - ScrollChangeAdd, - - // When loading a history part while scrolling down. - ScrollChangeNoJumpToBottom, - }; - struct ScrollChange { - ScrollChangeType type; - int value; - }; void updateHistoryGeometry(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 }); void updateListSize(); @@ -613,13 +585,6 @@ private: void countHistoryShowFrom(); - enum class TextUpdateEvent { - SaveDraft = (1 << 0), - SendTyping = (1 << 1), - }; - using TextUpdateEvents = base::flags; - friend inline constexpr bool is_flag_type(TextUpdateEvent) { return true; }; - void writeDrafts(Data::Draft **localDraft, Data::Draft **editDraft); void writeDrafts(History *history); void setFieldText( @@ -650,6 +615,58 @@ private: void handleSupportSwitch(not_null updated); + void inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result); + bool inlineBotResolveFail(QString name, const RPCError &error); + + bool isBotStart() const; + bool isBlocked() const; + bool isJoinChannel() const; + bool isMuteUnmute() const; + bool updateCmdStartShown(); + void updateSendButtonType(); + bool showRecordButton() const; + bool showInlineBotCancel() const; + void refreshSilentToggle(); + + void setupScheduledToggle(); + void refreshScheduledToggle(); + + MsgId _replyToId = 0; + Ui::Text::String _replyToName; + int _replyToNameVersion = 0; + + HistoryItemsList _toForward; + Ui::Text::String _toForwardFrom, _toForwardText; + int _toForwardNameVersion = 0; + + MsgId _editMsgId = 0; + + HistoryItem *_replyEditMsg = nullptr; + Ui::Text::String _replyEditMsgText; + mutable base::Timer _updateEditTimeLeftDisplay; + + object_ptr _fieldBarCancel; + + std::unique_ptr _pinnedBar; + + mtpRequestId _saveEditMsgRequestId = 0; + + QStringList _parsedLinks; + QString _previewLinks; + WebPageData *_previewData = nullptr; + typedef QMap PreviewCache; + PreviewCache _previewCache; + mtpRequestId _previewRequest = 0; + Ui::Text::String _previewTitle; + Ui::Text::String _previewDescription; + base::Timer _previewTimer; + bool _previewCancelled = false; + + bool _replyForwardPressed = false; + + HistoryItem *_replyReturn = nullptr; + QList _replyReturns; + PeerData *_peer = nullptr; ChannelId _channel = NoChannel; @@ -699,21 +716,6 @@ private: bool _inlineLookingUpBot = false; mtpRequestId _inlineBotResolveRequestId = 0; bool _isInlineBot = false; - void inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result); - bool inlineBotResolveFail(QString name, const RPCError &error); - - bool isBotStart() const; - bool isBlocked() const; - bool isJoinChannel() const; - bool isMuteUnmute() const; - bool updateCmdStartShown(); - void updateSendButtonType(); - bool showRecordButton() const; - bool showInlineBotCancel() const; - void refreshSilentToggle(); - - void setupScheduledToggle(); - void refreshScheduledToggle(); std::unique_ptr _contactStatus; diff --git a/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp new file mode 100644 index 000000000..f57ac36b4 --- /dev/null +++ b/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp @@ -0,0 +1,251 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "history/view/history_view_compose_controls.h" + +#include "ui/widgets/input_fields.h" +#include "ui/special_buttons.h" +#include "lang/lang_keys.h" +#include "chat_helpers/tabbed_panel.h" +#include "chat_helpers/tabbed_section.h" +#include "chat_helpers/tabbed_selector.h" +#include "chat_helpers/message_field.h" +#include "chat_helpers/emoji_suggestions_widget.h" +#include "window/window_session_controller.h" +#include "inline_bots/inline_results_widget.h" +#include "styles/style_history.h" + +namespace HistoryView { + +ComposeControls::ComposeControls( + not_null parent, + not_null window, + Mode mode) +: _parent(parent) +, _window(window) +, _mode(mode) +, _wrap(std::make_unique(parent)) +, _send(Ui::CreateChild(_wrap.get())) +, _attachToggle(Ui::CreateChild( + _wrap.get(), + st::historyAttach)) +, _tabbedSelectorToggle(Ui::CreateChild( + _wrap.get(), + st::historyAttachEmoji)) +, _field(Ui::CreateChild( + _wrap.get(), + st::historyComposeField, + Ui::InputField::Mode::MultiLine, + tr::lng_message_ph())) +, _tabbedPanel(std::make_unique(parent, window)) +, _tabbedSelector(_tabbedPanel->getSelector()) { + init(); +} + +ComposeControls::~ComposeControls() = default; + +Main::Session &ComposeControls::session() const { + return _window->session(); +} + +void ComposeControls::move(int x, int y) { + _wrap->move(x, y); +} + +void ComposeControls::resizeToWidth(int width) { + _wrap->resizeToWidth(width); + updateHeight(); +} + +rpl::producer ComposeControls::height() const { + return _wrap->heightValue(); +} + +int ComposeControls::heightCurrent() const { + return _wrap->height(); +} + +void ComposeControls::focus() { + _field->setFocus(); +} + +rpl::producer<> ComposeControls::cancelRequests() const { + return _cancelRequests.events(); +} + +void ComposeControls::showStarted() { + if (_inlineResults) { + _inlineResults->hideFast(); + } + if (_tabbedPanel) { + _tabbedPanel->hideFast(); + } + _wrap->hide(); +} + +void ComposeControls::showFinished() { + if (_inlineResults) { + _inlineResults->hideFast(); + } + if (_tabbedPanel) { + _tabbedPanel->hideFast(); + } + _wrap->show(); +} + +void ComposeControls::showForGrab() { + showFinished(); +} + +void ComposeControls::init() { + initField(); + initTabbedSelector(); + + _wrap->sizeValue( + ) | rpl::start_with_next([=](QSize size) { + updateControlsGeometry(size); + }, _wrap->lifetime()); + + _wrap->geometryValue( + ) | rpl::start_with_next([=](QRect rect) { + updateOuterGeometry(rect); + }, _wrap->lifetime()); + + _wrap->paintRequest( + ) | rpl::start_with_next([=](QRect clip) { + paintBackground(clip); + }, _wrap->lifetime()); +} + +void ComposeControls::initField() { + _field->setMaxHeight(st::historyComposeFieldMaxHeight); + //Ui::Connect(_field, &Ui::InputField::submitted, [=] { send(); }); + Ui::Connect(_field, &Ui::InputField::cancelled, [=] { escape(); }); + //Ui::Connect(_field, &Ui::InputField::tabbed, [=] { fieldTabbed(); }); + Ui::Connect(_field, &Ui::InputField::resized, [=] { updateHeight(); }); + //Ui::Connect(_field, &Ui::InputField::focused, [=] { fieldFocused(); }); + //Ui::Connect(_field, &Ui::InputField::changed, [=] { fieldChanged(); }); + InitMessageField(_window, _field); + const auto suggestions = Ui::Emoji::SuggestionsController::Init( + _parent, + _field, + &_window->session()); + _raiseEmojiSuggestions = [=] { suggestions->raise(); }; +} + +void ComposeControls::initTabbedSelector() { + _tabbedSelectorToggle->installEventFilter(_tabbedPanel.get()); + _tabbedSelectorToggle->addClickHandler([=] { + toggleTabbedSelectorMode(); + }); +} + +void ComposeControls::updateControlsGeometry(QSize size) { + // _attachToggle -- _inlineResults ------ _tabbedPanel -- _fieldBarCancel + // (_attachDocument|_attachPhoto) _field _tabbedSelectorToggle _send + + const auto fieldWidth = size.width() + - _attachToggle->width() + - st::historySendRight + - _send->width() + - _tabbedSelectorToggle->width(); + _field->resizeToWidth(fieldWidth); + + const auto buttonsTop = size.height() - _attachToggle->height(); + + auto left = 0; + _attachToggle->moveToLeft(left, buttonsTop); + left += _attachToggle->width(); + _field->moveToLeft( + left, + size.height() - _field->height() - st::historySendPadding); + + auto right = st::historySendRight; + _send->moveToRight(right, buttonsTop); + right += _send->width(); + _tabbedSelectorToggle->moveToRight(right, buttonsTop); +} + +void ComposeControls::updateOuterGeometry(QRect rect) { + if (_inlineResults) { + _inlineResults->moveBottom(rect.y()); + } + if (_tabbedPanel) { + _tabbedPanel->moveBottomRight( + rect.y() + rect.height() - _attachToggle->height(), + rect.x() + rect.width()); + } +} + +void ComposeControls::paintBackground(QRect clip) { + Painter p(_wrap.get()); + + p.fillRect(clip, st::historyComposeAreaBg); +} + +void ComposeControls::escape() { + _cancelRequests.fire({}); +} + +void ComposeControls::pushTabbedSelectorToThirdSection( + const Window::SectionShow ¶ms) { + if (!_tabbedPanel) { + return; + //} else if (!_canSendMessages) { + // session().settings().setTabbedReplacedWithInfo(true); + // _window->showPeerInfo(_peer, params.withThirdColumn()); + // return; + } + session().settings().setTabbedReplacedWithInfo(false); + _tabbedSelectorToggle->setColorOverrides( + &st::historyAttachEmojiActive, + &st::historyRecordVoiceFgActive, + &st::historyRecordVoiceRippleBgActive); + auto destroyingPanel = std::move(_tabbedPanel); + auto memento = ChatHelpers::TabbedMemento( + destroyingPanel->takeSelector(), + crl::guard(_wrap.get(), [=]( + object_ptr selector) { + returnTabbedSelector(std::move(selector)); + })); + _window->resizeForThirdSection(); + _window->showSection(std::move(memento), params.withThirdColumn()); +} + +void ComposeControls::toggleTabbedSelectorMode() { + if (_tabbedPanel) { + if (_window->canShowThirdSection() && !Adaptive::OneColumn()) { + session().settings().setTabbedSelectorSectionEnabled(true); + session().saveSettingsDelayed(); + pushTabbedSelectorToThirdSection( + Window::SectionShow::Way::ClearStack); + } else { + _tabbedPanel->toggleAnimated(); + } + } else { + _window->closeThirdSection(); + } +} + +void ComposeControls::returnTabbedSelector( + object_ptr selector) { + _tabbedPanel = std::make_unique( + _parent, + _window, + std::move(selector)); + _tabbedPanel->hide(); + _tabbedSelectorToggle->installEventFilter(_tabbedPanel.get()); + _tabbedSelectorToggle->setColorOverrides(nullptr, nullptr, nullptr); + updateOuterGeometry(_wrap->geometry()); +} + +void ComposeControls::updateHeight() { + const auto height = _field->height() + 2 * st::historySendPadding; + _wrap->resize(_wrap->width(), height); +} + +} // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_compose_controls.h b/Telegram/SourceFiles/history/view/history_view_compose_controls.h new file mode 100644 index 000000000..e417df1b1 --- /dev/null +++ b/Telegram/SourceFiles/history/view/history_view_compose_controls.h @@ -0,0 +1,121 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "base/unique_qptr.h" +#include "ui/rp_widget.h" +#include "ui/effects/animations.h" + +namespace ChatHelpers { +class TabbedPanel; +class TabbedSelector; +} // namespace ChatHelpers + +namespace InlineBots { +namespace Layout { +class ItemBase; +class Widget; +} // namespace Layout +class Result; +} // namespace InlineBots + +namespace Ui { +class SendButton; +class IconButton; +class EmojiButton; +class InputField; +} // namespace Ui + +namespace Main { +class Session; +} // namespace Main + +namespace Window { +class SessionController; +struct SectionShow; +} // namespace Window + +namespace HistoryView { + +class ComposeControls final { +public: + enum class Mode { + Normal, + Scheduled, + }; + + ComposeControls( + not_null parent, + not_null window, + Mode mode); + ~ComposeControls(); + + [[nodiscard]] Main::Session &session() const; + + void move(int x, int y); + void resizeToWidth(int width); + [[nodiscard]] rpl::producer height() const; + [[nodiscard]] int heightCurrent() const; + + void focus(); + [[nodiscard]] rpl::producer<> cancelRequests() const; + + void showForGrab(); + void showStarted(); + void showFinished(); + +private: + void init(); + void initField(); + void initTabbedSelector(); + void updateHeight(); + void updateControlsGeometry(QSize size); + void updateOuterGeometry(QRect rect); + void paintBackground(QRect clip); + + void escape(); + void toggleTabbedSelectorMode(); + void pushTabbedSelectorToThirdSection(const Window::SectionShow ¶ms); + void returnTabbedSelector( + object_ptr selector); + + const not_null _parent; + const not_null _window; + Mode _mode = Mode::Normal; + + const std::unique_ptr _wrap; + + const not_null _send; + const not_null _attachToggle; + const not_null _tabbedSelectorToggle; + const not_null _field; + std::unique_ptr _inlineResults; + std::unique_ptr _tabbedPanel; + const not_null _tabbedSelector; + + rpl::event_stream<> _cancelRequests; + + bool _recording = false; + bool _inField = false; + bool _inReplyEditForward = false; + bool _inClickable = false; + int _recordingSamples = 0; + int _recordCancelWidth; + + rpl::lifetime _uploaderSubscriptions; + + // This can animate for a very long time (like in music playing), + // so it should be a Basic, not a Simple animation. + Ui::Animations::Basic _recordingAnimation; + anim::value _recordingLevel; + + Fn _raiseEmojiSuggestions; + +}; + +} // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 348aaf957..1e87e97c2 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "history/view/history_view_scheduled_section.h" +#include "history/view/history_view_compose_controls.h" #include "history/view/history_view_top_bar_widget.h" #include "history/view/history_view_list_widget.h" #include "history/history.h" @@ -50,6 +51,10 @@ ScheduledWidget::ScheduledWidget( , _scroll(this, st::historyScroll, false) , _topBar(this, controller) , _topBarShadow(this) +, _composeControls(std::make_unique( + this, + controller, + ComposeControls::Mode::Scheduled)) , _scrollDown(_scroll, st::historyToDown) { _topBar->setActiveChat(_history, TopBarWidget::Section::Scheduled); @@ -83,6 +88,21 @@ ScheduledWidget::ScheduledWidget( connect(_scroll, &Ui::ScrollArea::scrolled, [=] { onScroll(); }); setupScrollDownButton(); + setupComposeControls(); +} + +ScheduledWidget::~ScheduledWidget() = default; + +void ScheduledWidget::setupComposeControls() { + _composeControls->height( + ) | rpl::start_with_next([=] { + updateControlsGeometry(); + }, lifetime()); + + _composeControls->cancelRequests( + ) | rpl::start_with_next([=] { + controller()->showBackFromStack(); + }, lifetime()); } void ScheduledWidget::setupScrollDownButton() { @@ -207,13 +227,14 @@ Dialogs::RowDescriptor ScheduledWidget::activeChat() const { QPixmap ScheduledWidget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) { _topBar->updateControlsVisibility(); if (params.withTopBarShadow) _topBarShadow->hide(); + _composeControls->showForGrab(); auto result = Ui::GrabWidget(this); if (params.withTopBarShadow) _topBarShadow->show(); return result; } void ScheduledWidget::doSetInnerFocus() { - _inner->setFocus(); + _composeControls->focus(); } bool ScheduledWidget::showInternal( @@ -254,6 +275,7 @@ void ScheduledWidget::resizeEvent(QResizeEvent *e) { if (!width() || !height()) { return; } + _composeControls->resizeToWidth(width()); updateControlsGeometry(); } @@ -267,9 +289,8 @@ void ScheduledWidget::updateControlsGeometry() { _topBarShadow->resize(contentWidth, st::lineWidth); const auto bottom = height(); - const auto scrollHeight = bottom - - _topBar->height(); -// - _showNext->height(); + const auto controlsHeight = _composeControls->heightCurrent(); + const auto scrollHeight = bottom - _topBar->height() - controlsHeight; const auto scrollSize = QSize(contentWidth, scrollHeight); if (_scroll->size() != scrollSize) { _skipScrollEvent = true; @@ -283,6 +304,7 @@ void ScheduledWidget::updateControlsGeometry() { } updateInnerVisibleArea(); } + _composeControls->move(0, bottom - controlsHeight); updateScrollDownPosition(); } @@ -324,10 +346,12 @@ void ScheduledWidget::showAnimatedHook( if (params.withTopBarShadow) { _topBarShadow->show(); } + _composeControls->showStarted(); } void ScheduledWidget::showFinishedHook() { _topBar->setAnimatingMode(false); + _composeControls->showFinished(); } bool ScheduledWidget::wheelEventFromFloatPlayer(QEvent *e) { diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h index 2c672fdf1..a64b2b834 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h @@ -33,6 +33,7 @@ namespace HistoryView { class Element; class TopBarWidget; class ScheduledMemento; +class ComposeControls; class ScheduledWidget final : public Window::SectionWidget @@ -42,6 +43,7 @@ public: QWidget *parent, not_null controller, not_null history); + ~ScheduledWidget(); not_null history() const; Dialogs::RowDescriptor activeChat() const override; @@ -106,6 +108,8 @@ private: void showAtPosition(Data::MessagePosition position); bool showAtPositionNow(Data::MessagePosition position); + void setupComposeControls(); + void setupScrollDownButton(); void scrollDownClicked(); void scrollDownAnimationFinish(); @@ -121,6 +125,7 @@ private: QPointer _inner; object_ptr _topBar; object_ptr _topBarShadow; + std::unique_ptr _composeControls; bool _skipScrollEvent = false; FullMsgId _highlightMessageId; diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index 2c147db36..57fb4d6ef 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -510,16 +510,21 @@ void TopBarWidget::refreshInfoButton() { } void TopBarWidget::resizeEvent(QResizeEvent *e) { + updateSearchVisibility(); updateControlsGeometry(); - const auto smallDialogsColumn = _activeChat.folder() - && (width() < _back->width() + _search->width()); - _search->setVisible(!smallDialogsColumn); } int TopBarWidget::countSelectedButtonsTop(float64 selectedShown) { return (1. - selectedShown) * (-st::topBarHeight); } +void TopBarWidget::updateSearchVisibility() { + const auto historyMode = (_section == Section::History); + const auto smallDialogsColumn = _activeChat.folder() + && (width() < _back->width() + _search->width()); + _search->setVisible(historyMode && !smallDialogsColumn); +} + void TopBarWidget::updateControlsGeometry() { auto hasSelected = (_selectedCount > 0); auto selectedButtonsTop = countSelectedButtonsTop(_selectedShown.value(hasSelected ? 1. : 0.)); @@ -620,9 +625,7 @@ void TopBarWidget::updateControlsVisibility() { _unreadBadge->show(); } const auto historyMode = (_section == Section::History); - const auto smallDialogsColumn = _activeChat.folder() - && (width() < _back->width() + _search->width()); - _search->setVisible(historyMode && !smallDialogsColumn); + updateSearchVisibility(); _menuToggle->setVisible(historyMode && !_activeChat.folder()); _infoToggle->setVisible(historyMode && !_activeChat.folder() diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.h b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.h index 36bfd95ec..02873bde3 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.h @@ -86,6 +86,7 @@ protected: private: void refreshInfoButton(); void refreshLang(); + void updateSearchVisibility(); void updateControlsGeometry(); void selectedShowCallback(); void updateInfoToggleActive(); diff --git a/Telegram/SourceFiles/ui/rp_widget.h b/Telegram/SourceFiles/ui/rp_widget.h index e7f9e4939..abae25cde 100644 --- a/Telegram/SourceFiles/ui/rp_widget.h +++ b/Telegram/SourceFiles/ui/rp_widget.h @@ -77,6 +77,11 @@ inline void DestroyChild(QWidget *child) { delete child; } +template +inline auto Connect(Args &&...args) { + return QObject::connect(std::forward(args)...); +} + void ResizeFitChild( not_null parent, not_null child); diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index fc3339fd4..ce1e5f570 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -318,6 +318,8 @@ <(src_loc)/history/view/media/history_view_wall_paper.cpp <(src_loc)/history/view/media/history_view_web_page.h <(src_loc)/history/view/media/history_view_web_page.cpp +<(src_loc)/history/view/history_view_compose_controls.cpp +<(src_loc)/history/view/history_view_compose_controls.h <(src_loc)/history/view/history_view_contact_status.cpp <(src_loc)/history/view/history_view_contact_status.h <(src_loc)/history/view/history_view_context_menu.cpp