Use Ui::PinnedBar in Replies section.

This commit is contained in:
John Preston 2020-10-13 10:16:16 +03:00
parent 0873db58d0
commit af1854e877
5 changed files with 103 additions and 120 deletions

View File

@ -5258,6 +5258,21 @@ void HistoryWidget::checkPinnedBarState() {
HistoryView::PinnedBarContent(&session(), std::move(shown)), HistoryView::PinnedBarContent(&session(), std::move(shown)),
true); true);
rpl::single(
rpl::empty_value()
) | rpl::then(
base::ObservableViewer(Adaptive::Changed())
) | rpl::map([] {
return Adaptive::OneColumn();
}) | rpl::start_with_next([=](bool one) {
_pinnedBar->setShadowGeometryPostprocess([=](QRect geometry) {
if (!one) {
geometry.setLeft(geometry.left() + st::lineWidth);
}
return geometry;
});
}, _pinnedBar->lifetime());
_pinnedBar->closeClicks( _pinnedBar->closeClicks(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
hidePinnedMessage(); hidePinnedMessage();

View File

@ -11,11 +11,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_top_bar_widget.h" #include "history/view/history_view_top_bar_widget.h"
#include "history/view/history_view_list_widget.h" #include "history/view/history_view_list_widget.h"
#include "history/view/history_view_schedule_box.h" #include "history/view/history_view_schedule_box.h"
#include "history/view/history_view_pinned_bar.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_drag_area.h" #include "history/history_drag_area.h"
#include "history/history_item_components.h" #include "history/history_item_components.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "chat_helpers/send_context_menu.h" // SendMenu::Type. #include "chat_helpers/send_context_menu.h" // SendMenu::Type.
#include "ui/chat/pinned_bar.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "ui/widgets/shadow.h" #include "ui/widgets/shadow.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
@ -23,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/item_text_options.h" #include "ui/item_text_options.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/text/format_values.h" #include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/special_buttons.h" #include "ui/special_buttons.h"
#include "ui/ui_utility.h" #include "ui/ui_utility.h"
#include "ui/toasts/common_toasts.h" #include "ui/toasts/common_toasts.h"
@ -77,6 +80,27 @@ bool CanSendFiles(not_null<const QMimeData*> data) {
return false; return false;
} }
rpl::producer<Ui::MessageBarContent> RootViewContent(
not_null<History*> history,
MsgId rootId) {
return MessageBarContentByItemId(
&history->session(),
FullMsgId{ history->channelId(), rootId }
) | rpl::map([=](Ui::MessageBarContent &&content) {
const auto item = history->owner().message(
history->channelId(),
rootId);
if (!item) {
content.text = Ui::Text::Link(tr::lng_deleted_message(tr::now));
}
const auto sender = (item && item->discussionPostOriginalSender())
? item->discussionPostOriginalSender()
: history->peer.get();
content.title = sender->name.isEmpty() ? "Message" : sender->name;
return std::move(content);
});
}
} // namespace } // namespace
RepliesMemento::RepliesMemento( RepliesMemento::RepliesMemento(
@ -131,8 +155,6 @@ RepliesWidget::RepliesWidget(
this, this,
controller, controller,
ComposeControls::Mode::Normal)) ComposeControls::Mode::Normal))
, _rootView(this, object_ptr<Ui::RpWidget>(this))
, _rootShadow(this)
, _scroll(std::make_unique<Ui::ScrollArea>(this, st::historyScroll, false)) , _scroll(std::make_unique<Ui::ScrollArea>(this, st::historyScroll, false))
, _scrollDown(_scroll.get(), st::historyToDown) , _scrollDown(_scroll.get(), st::historyToDown)
, _readRequestTimer([=] { sendReadTillRequest(); }) { , _readRequestTimer([=] { sendReadTillRequest(); }) {
@ -170,7 +192,6 @@ RepliesWidget::RepliesWidget(
}, _topBar->lifetime()); }, _topBar->lifetime());
_rootView->raise(); _rootView->raise();
_rootShadow->raise();
_topBarShadow->raise(); _topBarShadow->raise();
updateAdaptiveLayout(); updateAdaptiveLayout();
subscribe(Adaptive::Changed(), [=] { updateAdaptiveLayout(); }); subscribe(Adaptive::Changed(), [=] { updateAdaptiveLayout(); });
@ -263,9 +284,7 @@ void RepliesWidget::sendReadTillRequest() {
} }
void RepliesWidget::setupRoot() { void RepliesWidget::setupRoot() {
if (_root) { if (!_root) {
refreshRootView();
} else {
const auto channel = _history->peer->asChannel(); const auto channel = _history->peer->asChannel();
const auto done = crl::guard(this, [=](ChannelData*, MsgId) { const auto done = crl::guard(this, [=](ChannelData*, MsgId) {
_root = lookupRoot(); _root = lookupRoot();
@ -277,86 +296,41 @@ void RepliesWidget::setupRoot() {
_inner->update(); _inner->update();
} }
updatePinnedVisibility(); updatePinnedVisibility();
refreshRootView();
}); });
_history->session().api().requestMessageData(channel, _rootId, done); _history->session().api().requestMessageData(channel, _rootId, done);
} }
} }
void RepliesWidget::setupRootView() { void RepliesWidget::setupRootView() {
const auto raw = _rootView->entity(); auto content = rpl::combine(
raw->resize(raw->width(), st::historyReplyHeight); RootViewContent(_history, _rootId),
raw->paintRequest( _rootVisible.value()
) | rpl::start_with_next([=](QRect clip) { ) | rpl::map([=](Ui::MessageBarContent &&content, bool shown) {
auto p = Painter(raw); return shown ? std::move(content) : Ui::MessageBarContent();
p.fillRect(clip, st::historyPinnedBg); });
_rootView = std::make_unique<Ui::PinnedBar>(this, std::move(content));
auto top = st::msgReplyPadding.top(); rpl::single(
QRect rbar(myrtlrect(st::msgReplyBarSkip + st::msgReplyBarPos.x(), top + st::msgReplyBarPos.y(), st::msgReplyBarSize.width(), st::msgReplyBarSize.height())); rpl::empty_value()
p.fillRect(rbar, st::msgInReplyBarColor); ) | rpl::then(
base::ObservableViewer(Adaptive::Changed())
int32 left = st::msgReplyBarSkip + st::msgReplyBarSkip; ) | rpl::map([] {
if (!_rootTitle.isEmpty()) { return Adaptive::OneColumn();
const auto media = _root ? _root->media() : nullptr; }) | rpl::start_with_next([=](bool one) {
if (media && media->hasReplyPreview()) { _rootView->setShadowGeometryPostprocess([=](QRect geometry) {
if (const auto image = media->replyPreview()) { if (!one) {
QRect to(left, top, st::msgReplyBarSize.height(), st::msgReplyBarSize.height()); geometry.setLeft(geometry.left() + st::lineWidth);
p.drawPixmap(to.x(), to.y(), image->pixSingle(image->width() / cIntRetinaFactor(), image->height() / cIntRetinaFactor(), to.width(), to.height(), ImageRoundRadius::Small));
}
left += st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x();
} }
p.setPen(st::historyReplyNameFg); return geometry;
p.setFont(st::msgServiceNameFont); });
const auto poll = media ? media->poll() : nullptr;
const auto pinnedHeader = !poll
? tr::lng_pinned_message(tr::now)
: poll->quiz()
? tr::lng_pinned_quiz(tr::now)
: tr::lng_pinned_poll(tr::now);
_rootTitle.drawElided(p, left, top, width() - left - st::msgReplyPadding.right());
p.setPen(st::historyComposeAreaFg);
p.setTextPalette(st::historyComposeAreaPalette);
_rootMessage.drawElided(p, left, top + st::msgServiceNameFont->height, width() - left - st::msgReplyPadding.right());
p.restoreTextPalette();
} else {
p.setFont(st::msgDateFont);
p.setPen(st::historyComposeAreaFgService);
p.drawText(left, top + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(tr::lng_profile_loading(tr::now), width() - left - st::msgReplyPadding.right()));
}
}, raw->lifetime());
raw->setCursor(style::cur_pointer);
const auto pressed = raw->lifetime().make_state<bool>();
raw->events(
) | rpl::start_with_next([=](not_null<QEvent*> e) {
const auto mouse = static_cast<QMouseEvent*>(e.get());
if (e->type() == QEvent::MouseButtonPress) {
if (mouse->button() == Qt::LeftButton) {
*pressed = true;
}
} else if (e->type() == QEvent::MouseButtonRelease) {
if (mouse->button() == Qt::LeftButton) {
if (base::take(*pressed)
&& raw->rect().contains(mouse->pos())) {
showAtStart();
}
}
}
}, raw->lifetime());
_rootView->geometryValue(
) | rpl::start_with_next([=](QRect rect) {
_rootShadow->moveToLeft(
_rootShadow->x(),
rect.y() + rect.height());
}, _rootView->lifetime()); }, _rootView->lifetime());
_rootShadow->showOn(_rootView->shownValue()); _rootView->barClicks(
) | rpl::start_with_next([=] {
showAtStart();
}, lifetime());
_rootView->hide(anim::type::instant);
_rootViewHeight = 0; _rootViewHeight = 0;
_rootView->heightValue( _rootView->heightValue(
) | rpl::start_with_next([=](int height) { ) | rpl::start_with_next([=](int height) {
if (const auto delta = height - _rootViewHeight) { if (const auto delta = height - _rootViewHeight) {
@ -366,34 +340,6 @@ void RepliesWidget::setupRootView() {
}, _rootView->lifetime()); }, _rootView->lifetime());
} }
void RepliesWidget::refreshRootView() {
const auto sender = (_root && _root->discussionPostOriginalSender())
? _root->discussionPostOriginalSender()
: _history->peer.get();
_rootTitle.setText(
st::fwdTextStyle,
sender->name,
Ui::NameTextOptions());
if (_rootTitle.isEmpty()) {
_rootTitle.setText(
st::fwdTextStyle,
"Message",
Ui::NameTextOptions());
}
if (_root) {
_rootMessage.setText(
st::messageTextStyle,
_root->inReplyText(),
Ui::DialogTextOptions());
} else {
_rootMessage.setText(
st::messageTextStyle,
textcmdLink(1, tr::lng_deleted_message(tr::now)),
Ui::DialogTextOptions());
}
update();
}
HistoryItem *RepliesWidget::lookupRoot() const { HistoryItem *RepliesWidget::lookupRoot() const {
return _history->owner().message(_history->channelId(), _rootId); return _history->owner().message(_history->channelId(), _rootId);
} }
@ -1332,9 +1278,6 @@ void RepliesWidget::updateAdaptiveLayout() {
_topBarShadow->moveToLeft( _topBarShadow->moveToLeft(
Adaptive::OneColumn() ? 0 : st::lineWidth, Adaptive::OneColumn() ? 0 : st::lineWidth,
_topBar->height()); _topBar->height());
_rootShadow->moveToLeft(
Adaptive::OneColumn() ? 0 : st::lineWidth,
_rootShadow->y());
} }
not_null<History*> RepliesWidget::history() const { not_null<History*> RepliesWidget::history() const {
@ -1518,7 +1461,9 @@ void RepliesWidget::updateControlsGeometry() {
: base::make_optional(_scroll->scrollTop() + topDelta()); : base::make_optional(_scroll->scrollTop() + topDelta());
_topBar->resizeToWidth(contentWidth); _topBar->resizeToWidth(contentWidth);
_topBarShadow->resize(contentWidth, st::lineWidth); _topBarShadow->resize(contentWidth, st::lineWidth);
_rootShadow->resize(contentWidth, st::lineWidth); if (_rootView) {
_rootView->resizeToWidth(contentWidth);
}
_rootView->resizeToWidth(contentWidth); _rootView->resizeToWidth(contentWidth);
const auto bottom = height(); const auto bottom = height();
@ -1606,10 +1551,16 @@ void RepliesWidget::setPinnedVisibility(bool shown) {
updateControlsGeometry(); updateControlsGeometry();
} }
} }
_rootView->toggle(shown, anim::type::instant); if (shown) {
_rootView->show();
} else {
_rootView->hide();
}
_rootVisible = shown;
_rootView->finishAnimating();
_rootViewInited = true; _rootViewInited = true;
} else { } else {
_rootView->toggle(shown, anim::type::normal); _rootVisible = shown;
} }
} }
} }

View File

@ -35,8 +35,7 @@ class ScrollArea;
class PlainShadow; class PlainShadow;
class FlatButton; class FlatButton;
class HistoryDownButton; class HistoryDownButton;
template <typename Widget> class PinnedBar;
class SlideWrap;
} // namespace Ui } // namespace Ui
namespace Profile { namespace Profile {
@ -158,7 +157,6 @@ private:
void setupRoot(); void setupRoot();
void setupRootView(); void setupRootView();
void refreshRootView();
void setupDragArea(); void setupDragArea();
void sendReadTillRequest(); void sendReadTillRequest();
void readTill(not_null<HistoryItem*> item); void readTill(not_null<HistoryItem*> item);
@ -250,12 +248,10 @@ private:
std::unique_ptr<ComposeControls> _composeControls; std::unique_ptr<ComposeControls> _composeControls;
bool _skipScrollEvent = false; bool _skipScrollEvent = false;
Ui::Text::String _rootTitle; std::unique_ptr<Ui::PinnedBar> _rootView;
Ui::Text::String _rootMessage;
object_ptr<Ui::SlideWrap<Ui::RpWidget>> _rootView;
int _rootViewHeight = 0; int _rootViewHeight = 0;
object_ptr<Ui::PlainShadow> _rootShadow;
bool _rootViewInited = false; bool _rootViewInited = false;
rpl::variable<bool> _rootVisible = false;
std::unique_ptr<Ui::ScrollArea> _scroll; std::unique_ptr<Ui::ScrollArea> _scroll;

View File

@ -75,6 +75,22 @@ PinnedBar::PinnedBar(
PinnedBar::~PinnedBar() = default; PinnedBar::~PinnedBar() = default;
void PinnedBar::setShadowGeometryPostprocess(Fn<QRect(QRect)> postprocess) {
_shadowGeometryPostprocess = std::move(postprocess);
updateShadowGeometry(_wrap.geometry());
}
void PinnedBar::updateShadowGeometry(QRect wrapGeometry) {
const auto regular = QRect(
wrapGeometry.x(),
wrapGeometry.y() + wrapGeometry.height(),
wrapGeometry.width(),
st::lineWidth);
_shadow->setGeometry(_shadowGeometryPostprocess
? _shadowGeometryPostprocess(regular)
: regular);
}
void PinnedBar::createControls() { void PinnedBar::createControls() {
Expects(!_bar); Expects(!_bar);
@ -109,11 +125,7 @@ void PinnedBar::createControls() {
_wrap.geometryValue( _wrap.geometryValue(
) | rpl::start_with_next([=](QRect rect) { ) | rpl::start_with_next([=](QRect rect) {
_shadow->setGeometry( updateShadowGeometry(rect);
rect.x(),
rect.y() + rect.height(),
rect.width(),
st::lineWidth);
_bar->widget()->resizeToWidth( _bar->widget()->resizeToWidth(
rect.width() - (_close ? _close->width() : 0)); rect.width() - (_close ? _close->width() : 0));
const auto hidden = _wrap.isHidden() || !rect.height(); const auto hidden = _wrap.isHidden() || !rect.height();
@ -162,6 +174,10 @@ void PinnedBar::raise() {
_shadow->raise(); _shadow->raise();
} }
void PinnedBar::finishAnimating() {
_wrap.finishAnimating();
}
void PinnedBar::move(int x, int y) { void PinnedBar::move(int x, int y) {
_wrap.move(x, y); _wrap.move(x, y);
} }

View File

@ -26,6 +26,9 @@ public:
void show(); void show();
void hide(); void hide();
void raise(); void raise();
void finishAnimating();
void setShadowGeometryPostprocess(Fn<QRect(QRect)> postprocess);
void move(int x, int y); void move(int x, int y);
void resizeToWidth(int width); void resizeToWidth(int width);
@ -40,12 +43,14 @@ public:
private: private:
void createControls(); void createControls();
void updateShadowGeometry(QRect wrapGeometry);
Ui::SlideWrap<> _wrap; Ui::SlideWrap<> _wrap;
std::unique_ptr<Ui::MessageBar> _bar; std::unique_ptr<Ui::MessageBar> _bar;
std::unique_ptr<Ui::IconButton> _close; std::unique_ptr<Ui::IconButton> _close;
std::unique_ptr<Ui::PlainShadow> _shadow; std::unique_ptr<Ui::PlainShadow> _shadow;
rpl::event_stream<> _barClicks; rpl::event_stream<> _barClicks;
Fn<QRect(QRect)> _shadowGeometryPostprocess;
bool _shouldBeShown = false; bool _shouldBeShown = false;
bool _forceHidden = false; bool _forceHidden = false;