Make tabbed selector working in scheduled section.

This commit is contained in:
John Preston 2019-08-16 15:44:20 +03:00
parent 385a7eb00d
commit 3e895d0e85
27 changed files with 341 additions and 250 deletions

View File

@ -711,7 +711,7 @@ void EditCaptionBox::setupEmojiPanel() {
st::emojiPanMinHeight / 2,
st::emojiPanMinHeight);
_emojiPanel->hide();
_emojiPanel->getSelector()->emojiChosen(
_emojiPanel->selector()->emojiChosen(
) | rpl::start_with_next([=](EmojiPtr emoji) {
Ui::InsertEmojiAtCursor(_field->textCursor(), emoji);
}, lifetime());

View File

@ -1688,7 +1688,7 @@ void SendFilesBox::setupEmojiPanel() {
st::emojiPanMinHeight / 2,
st::emojiPanMinHeight);
_emojiPanel->hide();
_emojiPanel->getSelector()->emojiChosen(
_emojiPanel->selector()->emojiChosen(
) | rpl::start_with_next([=](EmojiPtr emoji) {
Ui::InsertEmojiAtCursor(_caption->textCursor(), emoji);
}, lifetime());

View File

@ -1574,6 +1574,8 @@ int StickersListWidget::megagroupSetInfoLeft() const {
}
void StickersListWidget::paintMegagroupEmptySet(Painter &p, int y, bool buttonSelected) {
p.setPen(st::emojiPanHeaderFg);
auto infoLeft = megagroupSetInfoLeft();
_megagroupSetAbout.drawLeft(p, infoLeft, y, width() - infoLeft, width());

View File

@ -26,20 +26,27 @@ constexpr auto kDelayedHideTimeoutMs = 3000;
TabbedPanel::TabbedPanel(
QWidget *parent,
not_null<Window::SessionController*> controller)
: TabbedPanel(
parent,
controller,
object_ptr<TabbedSelector>(nullptr, controller)) {
not_null<Window::SessionController*> controller,
not_null<TabbedSelector*> selector)
: TabbedPanel(parent, controller, { nullptr }, selector) {
}
TabbedPanel::TabbedPanel(
QWidget *parent,
not_null<Window::SessionController*> controller,
object_ptr<TabbedSelector> selector)
: TabbedPanel(parent, controller, std::move(selector), nullptr) {
}
TabbedPanel::TabbedPanel(
QWidget *parent,
not_null<Window::SessionController*> controller,
object_ptr<TabbedSelector> ownedSelector,
TabbedSelector *nonOwnedSelector)
: RpWidget(parent)
, _controller(controller)
, _selector(std::move(selector))
, _ownedSelector(std::move(ownedSelector))
, _selector(nonOwnedSelector ? nonOwnedSelector : _ownedSelector.data())
, _heightRatio(st::emojiPanHeightRatio)
, _minContentHeight(st::emojiPanMinHeight)
, _maxContentHeight(st::emojiPanMaxHeight) {
@ -106,6 +113,14 @@ TabbedPanel::TabbedPanel(
hide();
}
not_null<TabbedSelector*> TabbedPanel::selector() const {
return _selector;
}
bool TabbedPanel::isSelectorStolen() const {
return (_selector->parent() != this);
}
void TabbedPanel::moveBottomRight(int bottom, int right) {
const auto isNew = (_bottom != bottom || _right != right);
_bottom = bottom;
@ -366,17 +381,6 @@ void TabbedPanel::toggleAnimated() {
}
}
object_ptr<TabbedSelector> TabbedPanel::takeSelector() {
if (!isHidden() && !_hiding) {
startOpacityAnimation(true);
}
return std::move(_selector);
}
QPointer<TabbedSelector> TabbedPanel::getSelector() const {
return _selector.data();
}
void TabbedPanel::hideFinished() {
hide();
_a_show.stop();
@ -450,6 +454,10 @@ bool TabbedPanel::overlaps(const QRect &globalRect) const {
|| inner.marginsRemoved(QMargins(0, st::buttonRadius, 0, st::buttonRadius)).contains(testRect);
}
TabbedPanel::~TabbedPanel() = default;
TabbedPanel::~TabbedPanel() {
if (!_ownedSelector) {
_controller->takeTabbedSelectorOwnershipFrom(this);
}
}
} // namespace ChatHelpers

View File

@ -27,14 +27,16 @@ class TabbedPanel : public Ui::RpWidget {
public:
TabbedPanel(
QWidget *parent,
not_null<Window::SessionController*> controller);
not_null<Window::SessionController*> controller,
not_null<TabbedSelector*> selector);
TabbedPanel(
QWidget *parent,
not_null<Window::SessionController*> controller,
object_ptr<TabbedSelector> selector);
object_ptr<TabbedSelector> takeSelector();
QPointer<TabbedSelector> getSelector() const;
[[nodiscard]] bool isSelectorStolen() const;
[[nodiscard]] not_null<TabbedSelector*> selector() const;
void moveBottomRight(int bottom, int right);
void setDesiredHeightValues(
float64 ratio,
@ -64,6 +66,12 @@ protected:
bool eventFilter(QObject *obj, QEvent *e) override;
private:
TabbedPanel(
QWidget *parent,
not_null<Window::SessionController*> controller,
object_ptr<TabbedSelector> ownedSelector,
TabbedSelector *nonOwnedSelector);
void hideByTimerOrLeave();
void moveByBottom();
bool isDestroying() const {
@ -89,8 +97,9 @@ private:
bool preventAutoHide() const;
void updateContentHeight();
not_null<Window::SessionController*> _controller;
object_ptr<TabbedSelector> _selector;
const not_null<Window::SessionController*> _controller;
const object_ptr<TabbedSelector> _ownedSelector = { nullptr };
const not_null<TabbedSelector*> _selector;
int _contentMaxHeight = 0;
int _contentHeight = 0;

View File

@ -7,56 +7,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "chat_helpers/tabbed_section.h"
#include "styles/style_chat_helpers.h"
#include "chat_helpers/tabbed_selector.h"
#include "window/window_session_controller.h"
#include "styles/style_chat_helpers.h"
namespace ChatHelpers {
TabbedMemento::TabbedMemento(
object_ptr<TabbedSelector> selector,
Fn<void(object_ptr<TabbedSelector>)> returnMethod)
: _selector(std::move(selector))
, _returnMethod(std::move(returnMethod)) {
}
object_ptr<Window::SectionWidget> TabbedMemento::createWidget(
QWidget *parent,
not_null<Window::SessionController*> controller,
Window::Column column,
const QRect &geometry) {
auto result = object_ptr<TabbedSection>(
parent,
controller,
std::move(_selector),
std::move(_returnMethod));
auto result = object_ptr<TabbedSection>(parent, controller);
result->setGeometry(geometry);
return std::move(result);
}
TabbedMemento::~TabbedMemento() {
if (_returnMethod && _selector) {
_returnMethod(std::move(_selector));
}
}
TabbedSection::TabbedSection(
QWidget *parent,
not_null<Window::SessionController*> controller)
: TabbedSection(
parent,
controller,
object_ptr<TabbedSelector>(this, controller),
Fn<void(object_ptr<TabbedSelector>)>()) {
}
TabbedSection::TabbedSection(
QWidget *parent,
not_null<Window::SessionController*> controller,
object_ptr<TabbedSelector> selector,
Fn<void(object_ptr<TabbedSelector>)> returnMethod)
: Window::SectionWidget(parent, controller)
, _selector(std::move(selector))
, _returnMethod(std::move(returnMethod)) {
, _selector(controller->tabbedSelector()) {
_selector->setParent(this);
_selector->setRoundRadius(0);
_selector->setGeometry(rect());
@ -80,14 +51,6 @@ void TabbedSection::resizeEvent(QResizeEvent *e) {
_selector->setGeometry(rect());
}
object_ptr<TabbedSelector> TabbedSection::takeSelector() {
_selector->beforeHiding();
return std::move(_selector);
}
QPointer<TabbedSelector> TabbedSection::getSelector() const {
return _selector.data();
}
bool TabbedSection::showInternal(
not_null<Window::SectionMemento*> memento,
const Window::SectionShow &params) {
@ -104,9 +67,7 @@ QRect TabbedSection::rectForFloatPlayer() const {
TabbedSection::~TabbedSection() {
beforeHiding();
if (_returnMethod) {
_returnMethod(takeSelector());
}
controller()->takeTabbedSelectorOwnershipFrom(this);
}
} // namespace ChatHelpers

View File

@ -16,9 +16,7 @@ class TabbedSelector;
class TabbedMemento : public Window::SectionMemento {
public:
TabbedMemento(
object_ptr<TabbedSelector> selector,
Fn<void(object_ptr<TabbedSelector>)> returnMethod);
TabbedMemento() = default;
TabbedMemento(TabbedMemento &&other) = default;
TabbedMemento &operator=(TabbedMemento &&other) = default;
@ -28,12 +26,6 @@ public:
Window::Column column,
const QRect &geometry) override;
~TabbedMemento();
private:
object_ptr<TabbedSelector> _selector;
Fn<void(object_ptr<TabbedSelector>)> _returnMethod;
};
class TabbedSection : public Window::SectionWidget {
@ -41,18 +33,10 @@ public:
TabbedSection(
QWidget *parent,
not_null<Window::SessionController*> controller);
TabbedSection(
QWidget *parent,
not_null<Window::SessionController*> controller,
object_ptr<TabbedSelector> selector,
Fn<void(object_ptr<TabbedSelector>)> returnMethod);
void beforeHiding();
void afterShown();
object_ptr<TabbedSelector> takeSelector();
QPointer<TabbedSelector> getSelector() const;
bool showInternal(
not_null<Window::SectionMemento*> memento,
const Window::SectionShow &params) override;
@ -73,8 +57,7 @@ protected:
}
private:
object_ptr<TabbedSelector> _selector;
Fn<void(object_ptr<TabbedSelector>)> _returnMethod;
const not_null<TabbedSelector*> _selector;
};

View File

@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/stickers_list_widget.h"
#include "chat_helpers/gifs_list_widget.h"
#include "chat_helpers/stickers.h"
#include "styles/style_chat_helpers.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/shadow.h"
@ -21,10 +20,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "storage/localstorage.h"
#include "data/data_channel.h"
#include "data/data_session.h"
#include "lang/lang_keys.h"
#include "mainwindow.h"
#include "observer_peer.h"
#include "apiwrap.h"
#include "styles/style_chat_helpers.h"
namespace ChatHelpers {
@ -291,8 +292,8 @@ TabbedSelector::TabbedSelector(
createTab(SelectorTab::Gifs),
} }
, _currentTabType(full()
? session().settings().selectorTab()
: SelectorTab::Emoji) {
? session().settings().selectorTab()
: SelectorTab::Emoji) {
resize(st::emojiPanWidth, st::emojiPanMaxHeight);
for (auto &tab : _tabs) {
@ -364,10 +365,16 @@ TabbedSelector::TabbedSelector(
stickers()->showStickerSet(setId);
_showRequests.fire({});
}, lifetime());
session().data().stickersUpdated(
) | rpl::start_with_next([=] {
refreshStickers();
}, lifetime());
}
//setAttribute(Qt::WA_AcceptTouchEvents);
setAttribute(Qt::WA_OpaquePaintEvent, false);
showAll();
hide();
}
TabbedSelector::~TabbedSelector() = default;
@ -651,13 +658,6 @@ void TabbedSelector::afterShown() {
}
}
void TabbedSelector::showMegagroupSet(ChannelData *megagroup) {
if (!full()) {
return;
}
stickers()->showMegagroupSet(megagroup);
}
void TabbedSelector::setCurrentPeer(PeerData *peer) {
if (!full()) {
return;
@ -665,6 +665,7 @@ void TabbedSelector::setCurrentPeer(PeerData *peer) {
gifs()->setInlineQueryPeer(peer);
_currentPeer = peer;
checkRestrictedPeer();
stickers()->showMegagroupSet(peer ? peer->asMegagroup() : nullptr);
}
void TabbedSelector::checkRestrictedPeer() {

View File

@ -70,7 +70,6 @@ public:
void setRoundRadius(int radius);
void refreshStickers();
void showMegagroupSet(ChannelData *megagroup);
void setCurrentPeer(PeerData *peer);
void hideFinished();

View File

@ -11,10 +11,11 @@ namespace Core {
EventFilter::EventFilter(
not_null<QObject*> parent,
not_null<QObject*> object,
Fn<bool(not_null<QEvent*>)> filter)
: QObject(parent)
, _filter(std::move(filter)) {
parent->installEventFilter(this);
object->installEventFilter(this);
}
bool EventFilter::eventFilter(QObject *watched, QEvent *event) {
@ -24,7 +25,14 @@ bool EventFilter::eventFilter(QObject *watched, QEvent *event) {
not_null<QObject*> InstallEventFilter(
not_null<QObject*> object,
Fn<bool(not_null<QEvent*>)> filter) {
return new EventFilter(object, std::move(filter));
return InstallEventFilter(object, object, std::move(filter));
}
not_null<QObject*> InstallEventFilter(
not_null<QObject*> context,
not_null<QObject*> object,
Fn<bool(not_null<QEvent*>)> filter) {
return new EventFilter(context, object, std::move(filter));
}
} // namespace Core

View File

@ -13,6 +13,7 @@ class EventFilter : public QObject {
public:
EventFilter(
not_null<QObject*> parent,
not_null<QObject*> object,
Fn<bool(not_null<QEvent*>)> filter);
protected:
@ -27,4 +28,9 @@ not_null<QObject*> InstallEventFilter(
not_null<QObject*> object,
Fn<bool(not_null<QEvent*>)> filter);
not_null<QObject*> InstallEventFilter(
not_null<QObject*> context,
not_null<QObject*> object,
Fn<bool(not_null<QEvent*>)> filter);
} // namespace Core

View File

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/share_box.h"
#include "boxes/edit_caption_box.h"
#include "core/file_utilities.h"
#include "core/event_filter.h"
#include "ui/toast/toast.h"
#include "ui/special_buttons.h"
#include "ui/emoji_config.h"
@ -130,12 +131,6 @@ void ActivateWindow(not_null<Window::SessionController*> controller) {
Core::App().activateWindowDelayed(window);
}
void InsertEmojiToField(not_null<Ui::InputField*> field, EmojiPtr emoji) {
if (!field->isHidden()) {
Ui::InsertEmojiAtCursor(field->textCursor(), emoji);
}
}
bool ShowHistoryEndInsteadOfUnread(
not_null<Data::Session*> session,
PeerId peerId) {
@ -292,8 +287,6 @@ HistoryWidget::HistoryWidget(
return recordingAnimationCallback(now);
})
, _kbScroll(this, st::botKbScroll)
, _tabbedPanel(this, controller)
, _tabbedSelector(_tabbedPanel->getSelector())
, _attachDragState(DragState::None)
, _attachDragDocument(this)
, _attachDragPhoto(this)
@ -434,11 +427,6 @@ HistoryWidget::HistoryWidget(
_botKeyboardHide->hide();
_botCommandStart->hide();
_tabbedSelectorToggle->installEventFilter(_tabbedPanel);
_tabbedSelectorToggle->addClickHandler([=] {
toggleTabbedSelectorMode();
});
_botKeyboardShow->addClickHandler([=] { toggleKeyboard(); });
_botKeyboardHide->addClickHandler([=] { toggleKeyboard(); });
_botCommandStart->addClickHandler([=] { startBotCommand(); });
@ -658,24 +646,55 @@ HistoryWidget::HistoryWidget(
setupShortcuts();
}
void HistoryWidget::refreshTabbedPanel() {
if (_peer && controller()->hasTabbedSelectorOwnership()) {
createTabbedPanel();
} else {
setTabbedPanel(nullptr);
}
}
void HistoryWidget::initTabbedSelector() {
_tabbedSelector->emojiChosen(
) | rpl::start_with_next([=](EmojiPtr emoji) {
InsertEmojiToField(_field, emoji);
refreshTabbedPanel();
_tabbedSelectorToggle->addClickHandler([=] {
toggleTabbedSelectorMode();
});
const auto selector = controller()->tabbedSelector();
Core::InstallEventFilter(this, selector, [=](not_null<QEvent*> e) {
if (_tabbedPanel && e->type() == QEvent::ParentChange) {
setTabbedPanel(nullptr);
}
return false;
});
selector->emojiChosen(
) | rpl::filter([=] {
return !isHidden() && !_field->isHidden();
}) | rpl::start_with_next([=](EmojiPtr emoji) {
Ui::InsertEmojiAtCursor(_field->textCursor(), emoji);
}, lifetime());
_tabbedSelector->fileChosen(
) | rpl::start_with_next([=](not_null<DocumentData*> document) {
selector->fileChosen(
) | rpl::filter([=] {
return !isHidden();
}) | rpl::start_with_next([=](not_null<DocumentData*> document) {
sendExistingDocument(document);
}, lifetime());
_tabbedSelector->photoChosen(
) | rpl::start_with_next([=](not_null<PhotoData*> photo) {
selector->photoChosen(
) | rpl::filter([=] {
return !isHidden();
}) | rpl::start_with_next([=](not_null<PhotoData*> photo) {
sendExistingPhoto(photo);
}, lifetime());
_tabbedSelector->inlineResultChosen(
) | rpl::start_with_next([=](TabbedSelector::InlineChosen data) {
selector->inlineResultChosen(
) | rpl::filter([=] {
return !isHidden();
}) | rpl::start_with_next([=](TabbedSelector::InlineChosen data) {
sendInlineResult(data.result, data.bot);
}, lifetime());
}
@ -952,11 +971,9 @@ int HistoryWidget::itemTopForHighlight(
void HistoryWidget::start() {
session().data().stickersUpdated(
) | rpl::start_with_next([this] {
_tabbedSelector->refreshStickers();
) | rpl::start_with_next([=] {
updateStickersByEmoji();
}, lifetime());
updateRecentStickers();
session().data().notifySavedGifsUpdated();
subscribe(session().api().fullPeerUpdated(), [this](PeerData *peer) {
fullPeerUpdated(peer);
@ -1072,9 +1089,6 @@ void HistoryWidget::orderWidgets() {
_tabbedPanel->raise();
}
_raiseEmojiSuggestions();
if (_tabbedSelectorToggleTooltip) {
_tabbedSelectorToggleTooltip->raise();
}
_attachDragDocument->raise();
_attachDragPhoto->raise();
}
@ -1297,10 +1311,6 @@ void HistoryWidget::updateSendAction(
}
}
void HistoryWidget::updateRecentStickers() {
_tabbedSelector->refreshStickers();
}
void HistoryWidget::sendActionDone(const MTPBool &result, mtpRequestId req) {
for (auto i = _sendActionRequests.begin(), e = _sendActionRequests.end(); i != e; ++i) {
if (i.value() == req) {
@ -1729,7 +1739,6 @@ void HistoryWidget::showHistory(
_peer = session().data().peer(peerId);
_channel = peerToChannel(_peer->id);
_canSendMessages = _peer->canWrite();
_tabbedSelector->setCurrentPeer(_peer);
_contactStatus = std::make_unique<HistoryView::ContactStatus>(
&controller()->window()->controller(),
this,
@ -1741,6 +1750,8 @@ void HistoryWidget::showHistory(
} else {
_contactStatus = nullptr;
}
refreshTabbedPanel();
controller()->tabbedSelector()->setCurrentPeer(_peer);
if (_peer) {
_unblock->setText(((_peer->isUser()
@ -1818,8 +1829,6 @@ void HistoryWidget::showHistory(
applyDraft();
_send->finishAnimating();
_tabbedSelector->showMegagroupSet(_peer->asMegagroup());
updateControlsGeometry();
connect(_scroll, SIGNAL(geometryChanged()), _list, SLOT(onParentGeometryChanged()));
@ -1854,7 +1863,6 @@ void HistoryWidget::showHistory(
updateTopBarSelection();
clearFieldText();
_tabbedSelector->showMegagroupSet(nullptr);
doneShow();
}
updateForwarding();
@ -3860,20 +3868,36 @@ void HistoryWidget::pushTabbedSelectorToThirdSection(
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(this, [this](
object_ptr<TabbedSelector> selector) {
returnTabbedSelector(std::move(selector));
}));
controller()->resizeForThirdSection();
controller()->showSection(std::move(memento), params.withThirdColumn());
destroyingPanel.destroy();
controller()->showSection(
ChatHelpers::TabbedMemento(),
params.withThirdColumn());
}
bool HistoryWidget::returnTabbedSelector() {
createTabbedPanel();
moveFieldControls();
return true;
}
void HistoryWidget::createTabbedPanel() {
setTabbedPanel(std::make_unique<TabbedPanel>(
this,
controller(),
controller()->tabbedSelector()));
}
void HistoryWidget::setTabbedPanel(std::unique_ptr<TabbedPanel> panel) {
_tabbedPanel = std::move(panel);
if (const auto raw = _tabbedPanel.get()) {
_tabbedSelectorToggle->installEventFilter(raw);
_tabbedSelectorToggle->setColorOverrides(nullptr, nullptr, nullptr);
} else {
_tabbedSelectorToggle->setColorOverrides(
&st::historyAttachEmojiActive,
&st::historyRecordVoiceFgActive,
&st::historyRecordVoiceRippleBgActive);
}
}
void HistoryWidget::toggleTabbedSelectorMode() {
@ -3891,18 +3915,6 @@ void HistoryWidget::toggleTabbedSelectorMode() {
}
}
void HistoryWidget::returnTabbedSelector(
object_ptr<TabbedSelector> selector) {
_tabbedPanel.create(
this,
controller(),
std::move(selector));
_tabbedSelectorToggle->installEventFilter(_tabbedPanel);
_tabbedSelectorToggle->setColorOverrides(nullptr, nullptr, nullptr);
_tabbedSelectorToggleTooltipShown = false;
moveFieldControls();
}
void HistoryWidget::recountChatWidth() {
auto layout = (width() < st::adaptiveChatWideWidth)
? Adaptive::ChatLayout::Normal
@ -3935,7 +3947,6 @@ void HistoryWidget::moveFieldControls() {
auto right = st::historySendRight;
_send->moveToRight(right, buttonsBottom); right += _send->width();
_tabbedSelectorToggle->moveToRight(right, buttonsBottom);
updateTabbedSelectorToggleTooltipGeometry();
_botKeyboardHide->moveToRight(right, buttonsBottom); right += _botKeyboardHide->width();
_botKeyboardShow->moveToRight(right, buttonsBottom);
_botCommandStart->moveToRight(right, buttonsBottom);
@ -3989,15 +4000,6 @@ void HistoryWidget::moveFieldControls() {
}
}
void HistoryWidget::updateTabbedSelectorToggleTooltipGeometry() {
if (_tabbedSelectorToggleTooltip) {
auto toggle = _tabbedSelectorToggle->geometry();
auto margin = st::historyAttachEmojiTooltipDelta;
auto margins = QMargins(margin, margin, margin, margin);
_tabbedSelectorToggleTooltip->pointAt(toggle.marginsRemoved(margins));
}
}
void HistoryWidget::updateFieldSize() {
auto kbShowShown = _history && !_kbShown && _keyboard->hasMarkup();
auto fieldWidth = width() - _attachToggle->width() - st::historySendRight;
@ -6861,4 +6863,6 @@ void HistoryWidget::synteticScrollToY(int y) {
_synteticScrollEvent = false;
}
HistoryWidget::~HistoryWidget() = default;
HistoryWidget::~HistoryWidget() {
setTabbedPanel(nullptr);
}

View File

@ -91,7 +91,9 @@ class MessageField;
class HistoryInner;
struct HistoryMessageMarkupButton;
class HistoryWidget final : public Window::AbstractSectionWidget, public RPCSender {
class HistoryWidget final
: public Window::AbstractSectionWidget
, public RPCSender {
Q_OBJECT
public:
@ -128,10 +130,6 @@ public:
void historyToDown(History *history);
QRect historyRect() const;
void pushTabbedSelectorToThirdSection(
const Window::SectionShow &params);
void updateRecentStickers();
void updateFieldPlaceholder();
void updateStickersByEmoji();
@ -244,6 +242,11 @@ public:
bool sendExistingDocument(not_null<DocumentData*> document);
bool sendExistingPhoto(not_null<PhotoData*> photo);
// Tabbed selector management.
void pushTabbedSelectorToThirdSection(
const Window::SectionShow &params) override;
bool returnTabbedSelector() override;
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
@ -357,6 +360,9 @@ private:
friend inline constexpr bool is_flag_type(TextUpdateEvent) { return true; };
void initTabbedSelector();
void refreshTabbedPanel();
void createTabbedPanel();
void setTabbedPanel(std::unique_ptr<TabbedPanel> panel);
void updateField();
void send(Api::SendOptions options);
@ -366,7 +372,6 @@ private:
void handlePendingHistoryUpdate();
void fullPeerUpdated(PeerData *peer);
void toggleTabbedSelectorMode();
void returnTabbedSelector(object_ptr<TabbedSelector> selector);
void recountChatWidth();
void historyDownClicked();
void showNextUnreadMention();
@ -486,8 +491,6 @@ private:
// like send button, emoji button and others.
void moveFieldControls();
void updateFieldSize();
void updateTabbedSelectorToggleTooltipGeometry();
void checkTabbedSelectorToggleTooltip();
bool canWriteMessage() const;
std::optional<QString> writeRestriction() const;
@ -728,8 +731,6 @@ private:
object_ptr<Ui::RpWidget> _aboutProxyPromotion = { nullptr };
object_ptr<Ui::IconButton> _attachToggle;
object_ptr<Ui::EmojiButton> _tabbedSelectorToggle;
object_ptr<Ui::ImportantTooltip> _tabbedSelectorToggleTooltip = { nullptr };
bool _tabbedSelectorToggleTooltipShown = false;
object_ptr<Ui::IconButton> _botKeyboardShow;
object_ptr<Ui::IconButton> _botKeyboardHide;
object_ptr<Ui::IconButton> _botCommandStart;
@ -763,8 +764,7 @@ private:
QTimer _membersDropdownShowTimer;
object_ptr<InlineBots::Layout::Widget> _inlineResults = { nullptr };
object_ptr<TabbedPanel> _tabbedPanel;
QPointer<TabbedSelector> _tabbedSelector;
std::unique_ptr<TabbedPanel> _tabbedPanel;
DragState _attachDragState;
object_ptr<DragArea> _attachDragDocument, _attachDragPhoto;

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/input_fields.h"
#include "ui/special_buttons.h"
#include "lang/lang_keys.h"
#include "core/event_filter.h"
#include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_section.h"
#include "chat_helpers/tabbed_selector.h"
@ -36,17 +37,18 @@ ComposeControls::ComposeControls(
, _tabbedSelectorToggle(Ui::CreateChild<Ui::EmojiButton>(
_wrap.get(),
st::historyAttachEmoji))
, _field(Ui::CreateChild<Ui::InputField>(
_wrap.get(),
st::historyComposeField,
Ui::InputField::Mode::MultiLine,
tr::lng_message_ph()))
, _tabbedPanel(std::make_unique<ChatHelpers::TabbedPanel>(parent, window))
, _tabbedSelector(_tabbedPanel->getSelector()) {
, _field(
Ui::CreateChild<Ui::InputField>(
_wrap.get(),
st::historyComposeField,
Ui::InputField::Mode::MultiLine,
tr::lng_message_ph())) {
init();
}
ComposeControls::~ComposeControls() = default;
ComposeControls::~ComposeControls() {
setTabbedPanel(nullptr);
}
Main::Session &ComposeControls::session() const {
return _window->session();
@ -138,10 +140,46 @@ void ComposeControls::initField() {
}
void ComposeControls::initTabbedSelector() {
_tabbedSelectorToggle->installEventFilter(_tabbedPanel.get());
if (_window->hasTabbedSelectorOwnership()) {
createTabbedPanel();
} else {
setTabbedPanel(nullptr);
}
_tabbedSelectorToggle->addClickHandler([=] {
toggleTabbedSelectorMode();
});
const auto selector = _window->tabbedSelector();
const auto wrap = _wrap.get();
Core::InstallEventFilter(wrap, selector, [=](not_null<QEvent*> e) {
if (_tabbedPanel && e->type() == QEvent::ParentChange) {
setTabbedPanel(nullptr);
}
return false;
});
selector->emojiChosen(
) | rpl::start_with_next([=](EmojiPtr emoji) {
Ui::InsertEmojiAtCursor(_field->textCursor(), emoji);
}, wrap->lifetime());
selector->fileChosen(
) | rpl::start_with_next([=](not_null<DocumentData*> document) {
//sendExistingDocument(document);
}, wrap->lifetime());
selector->photoChosen(
) | rpl::start_with_next([=](not_null<PhotoData*> photo) {
//sendExistingPhoto(photo);
}, wrap->lifetime());
selector->inlineResultChosen(
) | rpl::start_with_next([=](
ChatHelpers::TabbedSelector::InlineChosen data) {
//sendInlineResult(data.result, data.bot);
}, wrap->lifetime());
}
void ComposeControls::updateControlsGeometry(QSize size) {
@ -205,15 +243,37 @@ void ComposeControls::pushTabbedSelectorToThirdSection(
&st::historyAttachEmojiActive,
&st::historyRecordVoiceFgActive,
&st::historyRecordVoiceRippleBgActive);
auto destroyingPanel = std::move(_tabbedPanel);
auto memento = ChatHelpers::TabbedMemento(
destroyingPanel->takeSelector(),
crl::guard(_wrap.get(), [=](
object_ptr<ChatHelpers::TabbedSelector> selector) {
returnTabbedSelector(std::move(selector));
}));
_window->resizeForThirdSection();
_window->showSection(std::move(memento), params.withThirdColumn());
_window->showSection(
ChatHelpers::TabbedMemento(),
params.withThirdColumn());
}
bool ComposeControls::returnTabbedSelector() {
createTabbedPanel();
updateOuterGeometry(_wrap->geometry());
return true;
}
void ComposeControls::createTabbedPanel() {
setTabbedPanel(std::make_unique<ChatHelpers::TabbedPanel>(
_parent,
_window,
_window->tabbedSelector()));
}
void ComposeControls::setTabbedPanel(
std::unique_ptr<ChatHelpers::TabbedPanel> panel) {
_tabbedPanel = std::move(panel);
if (const auto raw = _tabbedPanel.get()) {
_tabbedSelectorToggle->installEventFilter(raw);
_tabbedSelectorToggle->setColorOverrides(nullptr, nullptr, nullptr);
} else {
_tabbedSelectorToggle->setColorOverrides(
&st::historyAttachEmojiActive,
&st::historyRecordVoiceFgActive,
&st::historyRecordVoiceRippleBgActive);
}
}
void ComposeControls::toggleTabbedSelectorMode() {
@ -231,18 +291,6 @@ void ComposeControls::toggleTabbedSelectorMode() {
}
}
void ComposeControls::returnTabbedSelector(
object_ptr<ChatHelpers::TabbedSelector> selector) {
_tabbedPanel = std::make_unique<ChatHelpers::TabbedPanel>(
_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);

View File

@ -65,6 +65,9 @@ public:
void focus();
[[nodiscard]] rpl::producer<> cancelRequests() const;
void pushTabbedSelectorToThirdSection(const Window::SectionShow &params);
bool returnTabbedSelector();
void showForGrab();
void showStarted();
void showFinished();
@ -80,9 +83,8 @@ private:
void escape();
void toggleTabbedSelectorMode();
void pushTabbedSelectorToThirdSection(const Window::SectionShow &params);
void returnTabbedSelector(
object_ptr<ChatHelpers::TabbedSelector> selector);
void createTabbedPanel();
void setTabbedPanel(std::unique_ptr<ChatHelpers::TabbedPanel> panel);
const not_null<QWidget*> _parent;
const not_null<Window::SessionController*> _window;
@ -96,7 +98,6 @@ private:
const not_null<Ui::InputField*> _field;
std::unique_ptr<InlineBots::Layout::Widget> _inlineResults;
std::unique_ptr<ChatHelpers::TabbedPanel> _tabbedPanel;
const not_null<ChatHelpers::TabbedSelector*> _tabbedSelector;
rpl::event_stream<> _cancelRequests;

View File

@ -257,6 +257,15 @@ void ScheduledWidget::setInternalState(
restoreState(memento);
}
void ScheduledWidget::pushTabbedSelectorToThirdSection(
const Window::SectionShow &params) {
_composeControls->pushTabbedSelectorToThirdSection(params);
}
bool ScheduledWidget::returnTabbedSelector() {
return _composeControls->returnTabbedSelector();
}
std::unique_ptr<Window::SectionMemento> ScheduledWidget::createMemento() {
auto result = std::make_unique<ScheduledMemento>(history());
saveState(result.get());

View File

@ -64,6 +64,11 @@ public:
const QRect &geometry,
not_null<ScheduledMemento*> memento);
// Tabbed selector management.
void pushTabbedSelectorToThirdSection(
const Window::SectionShow &params) override;
bool returnTabbedSelector() override;
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;

View File

@ -24,7 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "mainwidget.h"
#include "window/main_window.h"
#include "mainwindow.h"
#include "styles/style_overview.h"
#include "styles/style_info.h"
#include "platform/platform_info.h"

View File

@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/section_memento.h"
#include "window/section_widget.h"
#include "window/window_connecting_widget.h"
#include "chat_helpers/tabbed_selector.h" // TabbedSelector::refreshStickers
#include "chat_helpers/message_field.h"
#include "chat_helpers/stickers.h"
#include "info/info_memento.h"
@ -1667,11 +1668,7 @@ void MainWidget::ui_showPeerHistory(
auto noPeer = !_history->peer();
auto onlyDialogs = noPeer && Adaptive::OneColumn();
if (_mainSection) {
_mainSection->hide();
_mainSection->deleteLater();
_mainSection = nullptr;
}
_mainSection.destroy();
updateControlsGeometry();
@ -1969,11 +1966,6 @@ void MainWidget::showNewSection(
}
updateControlsGeometry();
} else {
if (_mainSection) {
_mainSection->hide();
_mainSection->deleteLater();
_mainSection = nullptr;
}
_mainSection = std::move(newMainSection);
updateControlsGeometry();
_history->finishAnimating();
@ -2688,6 +2680,12 @@ int MainWidget::contentScrollAddToY() const {
return _contentScrollAddToY;
}
void MainWidget::returnTabbedSelector() {
if (!_mainSection || !_mainSection->returnTabbedSelector()) {
_history->returnTabbedSelector();
}
}
void MainWidget::keyPressEvent(QKeyEvent *e) {
}
@ -3471,7 +3469,7 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
if (writeRecentStickers) {
Local::writeRecentStickers();
}
_history->updateRecentStickers();
_controller->tabbedSelector()->refreshStickers();
}
void MainWidget::activate() {

View File

@ -106,12 +106,14 @@ public:
MainWidget(QWidget *parent, not_null<Window::SessionController*> controller);
Main::Session &session() const;
[[nodiscard]] Main::Session &session() const;
bool isMainSectionShown() const;
bool isThirdSectionShown() const;
[[nodiscard]] bool isMainSectionShown() const;
[[nodiscard]] bool isThirdSectionShown() const;
int contentScrollAddToY() const;
[[nodiscard]] int contentScrollAddToY() const;
void returnTabbedSelector();
void showAnimated(const QPixmap &bgAnimCache, bool back = false);

View File

@ -656,9 +656,6 @@ void MainWindow::setInactivePress(bool inactive) {
}
}
MainWindow::~MainWindow() {
// We want to delete all widgets before the _controller.
_body.destroy();
}
MainWindow::~MainWindow() = default;
} // namespace Window

View File

@ -92,6 +92,8 @@ public:
virtual void updateWindowIcon();
void clearWidgets();
public slots:
bool minimizeToTray();
void updateGlobalMenu() {
@ -115,7 +117,6 @@ protected:
virtual void handleActiveChangedHook() {
}
void clearWidgets();
virtual void clearWidgetsHook() {
}

View File

@ -39,23 +39,31 @@ public:
, _controller(controller) {
}
Main::Session &session() const;
[[nodiscard]] Main::Session &session() const;
// Tabbed selector management.
virtual void pushTabbedSelectorToThirdSection(
const Window::SectionShow &params) {
}
virtual bool returnTabbedSelector() {
return false;
}
// Float player interface.
virtual bool wheelEventFromFloatPlayer(QEvent *e) {
return false;
}
virtual QRect rectForFloatPlayer() const {
[[nodiscard]] virtual QRect rectForFloatPlayer() const {
return mapToGlobal(rect());
}
protected:
not_null<Window::SessionController*> controller() const {
[[nodiscard]] not_null<Window::SessionController*> controller() const {
return _controller;
}
private:
not_null<Window::SessionController*> _controller;
const not_null<Window::SessionController*> _controller;
};

View File

@ -28,7 +28,10 @@ Controller::Controller(not_null<Main::Account*> account)
_widget.init();
}
Controller::~Controller() = default;
Controller::~Controller() {
// We want to delete all widgets before the _sessionController.
_widget.clearWidgets();
}
void Controller::firstShow() {
_widget.firstShow();

View File

@ -69,8 +69,8 @@ private:
anim::type animated);
not_null<Main::Account*> _account;
std::unique_ptr<SessionController> _sessionController;
::MainWindow _widget;
std::unique_ptr<SessionController> _sessionController;
rpl::lifetime _lifetime;

View File

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "passport/passport_form_controller.h"
#include "chat_helpers/tabbed_selector.h"
#include "core/shortcuts.h"
#include "base/unixtime.h"
#include "boxes/calendar_box.h"
@ -99,9 +100,11 @@ void SessionNavigation::showSettings(const SectionShow &params) {
SessionController::SessionController(
not_null<Main::Session*> session,
not_null<MainWindow*> window)
not_null<::MainWindow*> window)
: SessionNavigation(session)
, _window(window) {
, _window(window)
, _tabbedSelector(
std::make_unique<ChatHelpers::TabbedSelector>(window, this)) {
init();
subscribe(session->api().fullPeerUpdated(), [=](PeerData *peer) {
@ -122,6 +125,28 @@ SessionController::SessionController(
}, lifetime());
}
auto SessionController::tabbedSelector() const
-> not_null<ChatHelpers::TabbedSelector*> {
return _tabbedSelector.get();
}
void SessionController::takeTabbedSelectorOwnershipFrom(
not_null<QWidget*> parent) {
if (_tabbedSelector->parent() == parent) {
if (const auto chats = _window->chatsWidget()) {
chats->returnTabbedSelector();
}
if (_tabbedSelector->parent() == parent) {
_tabbedSelector->hide();
_tabbedSelector->setParent(window());
}
}
}
bool SessionController::hasTabbedSelectorOwnership() const {
return (_tabbedSelector->parent() == window());
}
void SessionController::showEditPeerBox(PeerData *peer) {
_showEditPeer = peer;
session().api().requestFullPeer(peer);

View File

@ -13,9 +13,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "dialogs/dialogs_key.h"
class MainWidget;
class MainWindow;
class HistoryMessage;
class HistoryService;
namespace ChatHelpers {
class TabbedSelector;
} // namespace ChatHelpers
namespace Main {
class Session;
} // namespace Main
@ -146,12 +151,17 @@ class SessionController
public:
SessionController(
not_null<Main::Session*> session,
not_null<MainWindow*> window);
not_null<::MainWindow*> window);
not_null<MainWindow*> window() const {
[[nodiscard]] not_null<::MainWindow*> window() const {
return _window;
}
[[nodiscard]] auto tabbedSelector() const
-> not_null<ChatHelpers::TabbedSelector*>;
void takeTabbedSelectorOwnershipFrom(not_null<QWidget*> parent);
[[nodiscard]] bool hasTabbedSelectorOwnership() const;
// This is needed for History TopBar updating when searchInChat
// is changed in the Dialogs::Widget of the current window.
rpl::variable<Dialogs::Key> searchInChat;
@ -292,7 +302,7 @@ private:
void pushToChatEntryHistory(Dialogs::RowDescriptor row);
bool chatEntryHistoryMove(int steps);
const not_null<MainWindow*> _window;
const not_null<::MainWindow*> _window;
std::unique_ptr<Passport::FormController> _passportForm;
@ -300,6 +310,9 @@ private:
base::Observable<void> _gifPauseLevelChanged;
base::Observable<void> _floatPlayerAreaUpdated;
// Depends on _gifPause*.
const std::unique_ptr<ChatHelpers::TabbedSelector> _tabbedSelector;
rpl::variable<Dialogs::RowDescriptor> _activeChatEntry;
base::Variable<bool> _dialogsListFocused = { false };
base::Variable<bool> _dialogsListDisplayForced = { false };