Use new message bar for pinned message.

This commit is contained in:
John Preston 2020-10-10 15:04:28 +03:00
parent ae298818a8
commit 67290eed58
6 changed files with 473 additions and 238 deletions

View file

@ -561,6 +561,8 @@ PRIVATE
history/view/history_view_message.cpp history/view/history_view_message.cpp
history/view/history_view_message.h history/view/history_view_message.h
history/view/history_view_object.h history/view/history_view_object.h
history/view/history_view_pinned_bar.cpp
history/view/history_view_pinned_bar.h
history/view/history_view_pinned_tracker.cpp history/view/history_view_pinned_tracker.cpp
history/view/history_view_pinned_tracker.h history/view/history_view_pinned_tracker.h
history/view/history_view_replies_section.cpp history/view/history_view_replies_section.cpp

View file

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/ripple_animation.h" #include "ui/effects/ripple_animation.h"
#include "ui/text/text_utilities.h" // Ui::Text::ToUpper #include "ui/text/text_utilities.h" // Ui::Text::ToUpper
#include "ui/text/format_values.h" #include "ui/text/format_values.h"
#include "ui/chat/message_bar.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "ui/special_buttons.h" #include "ui/special_buttons.h"
#include "inline_bots/inline_bot_result.h" #include "inline_bots/inline_bot_result.h"
@ -62,6 +63,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_scheduled_section.h" #include "history/view/history_view_scheduled_section.h"
#include "history/view/history_view_schedule_box.h" #include "history/view/history_view_schedule_box.h"
#include "history/view/history_view_webpage_preview.h" #include "history/view/history_view_webpage_preview.h"
#include "history/view/history_view_top_bar_widget.h"
#include "history/view/history_view_contact_status.h"
#include "history/view/history_view_pinned_tracker.h"
#include "history/view/history_view_pinned_bar.h"
#include "history/view/media/history_view_media.h" #include "history/view/media/history_view_media.h"
#include "profile/profile_block_group_members.h" #include "profile/profile_block_group_members.h"
#include "info/info_memento.h" #include "info/info_memento.h"
@ -86,9 +91,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/player/media_player_instance.h" #include "media/player/media_player_instance.h"
#include "core/application.h" #include "core/application.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "history/view/history_view_top_bar_widget.h"
#include "history/view/history_view_contact_status.h"
#include "history/view/history_view_pinned_tracker.h"
#include "base/qthelp_regex.h" #include "base/qthelp_regex.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/item_text_options.h" #include "ui/item_text_options.h"
@ -552,7 +554,6 @@ HistoryWidget::HistoryWidget(
UpdateFlag::Rights UpdateFlag::Rights
| UpdateFlag::Migration | UpdateFlag::Migration
| UpdateFlag::UnavailableReason | UpdateFlag::UnavailableReason
| UpdateFlag::PinnedMessage
| UpdateFlag::IsBlocked | UpdateFlag::IsBlocked
| UpdateFlag::Admins | UpdateFlag::Admins
| UpdateFlag::Members | UpdateFlag::Members
@ -590,14 +591,6 @@ HistoryWidget::HistoryWidget(
updateControlsVisibility(); updateControlsVisibility();
updateControlsGeometry(); updateControlsGeometry();
} }
if (flags & UpdateFlag::PinnedMessage) {
if (pinnedMsgVisibilityUpdated()) {
updateHistoryGeometry();
updateControlsVisibility();
updateControlsGeometry();
this->update();
}
}
if (flags & UpdateFlag::Slowmode) { if (flags & UpdateFlag::Slowmode) {
updateSendButtonType(); updateSendButtonType();
} }
@ -1142,7 +1135,7 @@ void HistoryWidget::orderWidgets() {
_contactStatus->raise(); _contactStatus->raise();
} }
if (_pinnedBar) { if (_pinnedBar) {
_pinnedBar->shadow->raise(); _pinnedBar->raise();
} }
_topShadow->raise(); _topShadow->raise();
if (_membersDropdown) { if (_membersDropdown) {
@ -1698,7 +1691,7 @@ void HistoryWidget::showHistory(
_history->showAtMsgId = _showAtMsgId; _history->showAtMsgId = _showAtMsgId;
destroyUnreadBarOnClose(); destroyUnreadBarOnClose();
showPinnedMessage(FullMsgId()); _pinnedBar = nullptr;
_pinnedTracker = nullptr; _pinnedTracker = nullptr;
_membersDropdown.destroy(); _membersDropdown.destroy();
_scrollToAnimation.stop(); _scrollToAnimation.stop();
@ -1814,7 +1807,6 @@ void HistoryWidget::showHistory(
_updateHistoryItems.stop(); _updateHistoryItems.stop();
setupPinnedTracker(); setupPinnedTracker();
pinnedMsgVisibilityUpdated();
if (_history->scrollTopItem if (_history->scrollTopItem
|| (_migrated && _migrated->scrollTopItem) || (_migrated && _migrated->scrollTopItem)
|| _history->isReadyFor(_showAtMsgId)) { || _history->isReadyFor(_showAtMsgId)) {
@ -2026,13 +2018,15 @@ void HistoryWidget::updateControlsVisibility() {
if (_tabbedPanel) { if (_tabbedPanel) {
_tabbedPanel->hideFast(); _tabbedPanel->hideFast();
} }
if (_pinnedBar) {
_pinnedBar->hide();
}
hideChildren(); hideChildren();
return; return;
} }
if (_pinnedBar) { if (_pinnedBar) {
_pinnedBar->cancel->show(); _pinnedBar->show();
_pinnedBar->shadow->show();
} }
if (_firstLoadRequest && !_scroll->isHidden()) { if (_firstLoadRequest && !_scroll->isHidden()) {
_scroll->hide(); _scroll->hide();
@ -2242,7 +2236,7 @@ void HistoryWidget::showAboutTopPromotion() {
} }
void HistoryWidget::updateMouseTracking() { void HistoryWidget::updateMouseTracking() {
bool trackMouse = !_fieldBarCancel->isHidden() || _pinnedBar; const auto trackMouse = !_fieldBarCancel->isHidden();
setMouseTracking(trackMouse); setMouseTracking(trackMouse);
} }
@ -3180,6 +3174,9 @@ void HistoryWidget::showAnimated(
if (_tabbedPanel) { if (_tabbedPanel) {
_tabbedPanel->hideFast(); _tabbedPanel->hideFast();
} }
if (_pinnedBar) {
_pinnedBar->hide();
}
hideChildren(); hideChildren();
if (params.withTopBarShadow) _topShadow->show(); if (params.withTopBarShadow) _topShadow->show();
@ -3336,14 +3333,12 @@ void HistoryWidget::mouseMoveEvent(QMouseEvent *e) {
void HistoryWidget::updateOverStates(QPoint pos) { void HistoryWidget::updateOverStates(QPoint pos) {
auto inField = pos.y() >= (_scroll->y() + _scroll->height()) && pos.y() < height() && pos.x() >= 0 && pos.x() < width(); auto inField = pos.y() >= (_scroll->y() + _scroll->height()) && pos.y() < height() && pos.x() >= 0 && pos.x() < width();
auto inReplyEditForward = QRect(st::historyReplySkip, _field->y() - st::historySendPadding - st::historyReplyHeight, width() - st::historyReplySkip - _fieldBarCancel->width(), st::historyReplyHeight).contains(pos) && (_editMsgId || replyToId() || readyToForward()); auto inReplyEditForward = QRect(st::historyReplySkip, _field->y() - st::historySendPadding - st::historyReplyHeight, width() - st::historyReplySkip - _fieldBarCancel->width(), st::historyReplyHeight).contains(pos) && (_editMsgId || replyToId() || readyToForward());
auto inPinnedMsg = QRect(0, _topBar->bottomNoMargins(), width(), st::historyReplyHeight).contains(pos) && _pinnedBar; auto inClickable = inReplyEditForward;
auto inClickable = inReplyEditForward || inPinnedMsg;
if (inField != _inField && _recording) { if (inField != _inField && _recording) {
_inField = inField; _inField = inField;
_send->setRecordActive(_inField); _send->setRecordActive(_inField);
} }
_inReplyEditForward = inReplyEditForward; _inReplyEditForward = inReplyEditForward;
_inPinnedMsg = inPinnedMsg;
if (inClickable != _inClickable) { if (inClickable != _inClickable) {
_inClickable = inClickable; _inClickable = inClickable;
setCursor(_inClickable ? style::cur_pointer : style::cur_default); setCursor(_inClickable ? style::cur_pointer : style::cur_default);
@ -4442,10 +4437,10 @@ void HistoryWidget::updateControlsGeometry() {
const auto pinnedBarTop = _topBar->bottomNoMargins(); const auto pinnedBarTop = _topBar->bottomNoMargins();
if (_pinnedBar) { if (_pinnedBar) {
_pinnedBar->cancel->moveToLeft(width() - _pinnedBar->cancel->width(), pinnedBarTop); _pinnedBar->move(0, pinnedBarTop);
_pinnedBar->shadow->setGeometryToLeft(0, pinnedBarTop + st::historyReplyHeight, width(), st::lineWidth); _pinnedBar->resizeToWidth(width());
} }
const auto contactStatusTop = pinnedBarTop + (_pinnedBar ? st::historyReplyHeight : 0); const auto contactStatusTop = pinnedBarTop + (_pinnedBar ? _pinnedBar->height() : 0);
if (_contactStatus) { if (_contactStatus) {
_contactStatus->move(0, contactStatusTop); _contactStatus->move(0, contactStatusTop);
} }
@ -4487,9 +4482,6 @@ void HistoryWidget::itemRemoved(not_null<const HistoryItem*> item) {
while (item == _replyReturn) { while (item == _replyReturn) {
calcNextReplyReturn(); calcNextReplyReturn();
} }
if (_pinnedBar && item->id == _pinnedBar->msgId) {
pinnedMsgVisibilityUpdated();
}
if (_kbReplyTo && item == _kbReplyTo) { if (_kbReplyTo && item == _kbReplyTo) {
toggleKeyboard(); toggleKeyboard();
_kbReplyTo = nullptr; _kbReplyTo = nullptr;
@ -4509,9 +4501,6 @@ void HistoryWidget::itemEdited(not_null<HistoryItem*> item) {
if (item.get() == _replyEditMsg) { if (item.get() == _replyEditMsg) {
updateReplyEditTexts(true); updateReplyEditTexts(true);
} }
if (_pinnedBar && item->id == _pinnedBar->msgId) {
updatePinnedBar(true);
}
} }
void HistoryWidget::updateScrollColors() { void HistoryWidget::updateScrollColors() {
@ -4612,7 +4601,7 @@ void HistoryWidget::updateHistoryGeometry(
auto newScrollHeight = height() - _topBar->height(); auto newScrollHeight = height() - _topBar->height();
if (_pinnedBar) { if (_pinnedBar) {
newScrollHeight -= st::historyReplyHeight; newScrollHeight -= _pinnedBar->height();
} }
if (_contactStatus) { if (_contactStatus) {
newScrollHeight -= _contactStatus->height(); newScrollHeight -= _contactStatus->height();
@ -4848,7 +4837,7 @@ int HistoryWidget::computeMaxFieldHeight() const {
const auto available = height() const auto available = height()
- _topBar->height() - _topBar->height()
- (_contactStatus ? _contactStatus->height() : 0) - (_contactStatus ? _contactStatus->height() : 0)
- (_pinnedBar ? st::historyReplyHeight : 0) - (_pinnedBar ? _pinnedBar->height() : 0)
- ((_editMsgId - ((_editMsgId
|| replyToId() || replyToId()
|| readyToForward() || readyToForward()
@ -4980,9 +4969,9 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
} else { } else {
Ui::showPeerHistory(_peer, _editMsgId ? _editMsgId : replyToId()); Ui::showPeerHistory(_peer, _editMsgId ? _editMsgId : replyToId());
} }
} else if (_inPinnedMsg) { //} else if (_inPinnedMsg) { // #TODO pinned
Assert(_pinnedBar != nullptr); // Assert(_pinnedBar != nullptr);
Ui::showPeerHistory(_peer, _pinnedBar->msgId); // Ui::showPeerHistory(_peer, _pinnedBar->msgId);
} }
} }
@ -5189,48 +5178,6 @@ void HistoryWidget::sendInlineResult(
_field->setFocus(); _field->setFocus();
} }
HistoryWidget::PinnedBar::PinnedBar(MsgId msgId, HistoryWidget *parent)
: msgId(msgId)
, cancel(parent, st::historyReplyCancel)
, shadow(parent) {
}
HistoryWidget::PinnedBar::~PinnedBar() {
cancel.destroyDelayed();
shadow.destroyDelayed();
}
void HistoryWidget::updatePinnedBar(bool force) {
update();
if (!_pinnedBar) {
return;
}
const auto messageId = _pinnedBar->msgId;
if (!force) {
if (_pinnedBar->msg) {
return;
}
}
Assert(_history != nullptr);
if (!_pinnedBar->msg) {
_pinnedBar->msg = session().data().message(
_history->channelId(),
messageId);
}
if (_pinnedBar->msg) {
_pinnedBar->text.setText(
st::messageTextStyle,
_pinnedBar->msg->inReplyText(),
Ui::DialogTextOptions());
update();
} else if (force) {
destroyPinnedBar();
_history->peer->removePinnedMessage(messageId);
updateControlsGeometry();
}
}
void HistoryWidget::updatePinnedViewer() { void HistoryWidget::updatePinnedViewer() {
if (_firstLoadRequest if (_firstLoadRequest
|| _delayedShowAtRequest || _delayedShowAtRequest
@ -5264,80 +5211,90 @@ void HistoryWidget::setupPinnedTracker() {
Expects(_history != nullptr); Expects(_history != nullptr);
_pinnedTracker = std::make_unique<HistoryView::PinnedTracker>(_history); _pinnedTracker = std::make_unique<HistoryView::PinnedTracker>(_history);
_pinnedTracker->shownMessageId( _pinnedBar = std::make_unique<HistoryView::PinnedBar>(
) | rpl::start_with_next([=](MsgId messageId) { this,
showPinnedMessage({ peerToChannel(_peer->id), messageId }); &session(),
}, _list->lifetime()); _pinnedTracker->shownMessageId() | rpl::map([=](MsgId messageId) {
} return FullMsgId{ peerToChannel(_peer->id), messageId };
}),
true);
void HistoryWidget::showPinnedMessage(FullMsgId id) { _pinnedBar->closeClicks(
if (_pinnedId == id) { ) | rpl::start_with_next([=] {
return; hidePinnedMessage();
} }, _pinnedBar->lifetime());
_pinnedId = id;
if (pinnedMsgVisibilityUpdated()) { _pinnedBarHeight = 0;
_pinnedBar->heightValue(
) | rpl::start_with_next([=](int height) {
_topDelta = (height - _pinnedBarHeight);
_pinnedBarHeight = height;
updateHistoryGeometry(); updateHistoryGeometry();
updateControlsVisibility();
updateControlsGeometry(); updateControlsGeometry();
this->update(); _topDelta = 0;
}, _pinnedBar->lifetime());
orderWidgets();
if (_a_show.animating()) {
_pinnedBar->hide();
} }
} }
//
bool HistoryWidget::pinnedMsgVisibilityUpdated() { //bool HistoryWidget::pinnedMsgVisibilityUpdated() {
auto result = false; // auto result = false;
auto pinnedId = _pinnedId; // auto pinnedId = _pinnedId;
if (pinnedId && !_peer->canPinMessages()) { // if (pinnedId && !_peer->canPinMessages()) {
const auto hiddenId = session().settings().hiddenPinnedMessageId( // const auto hiddenId = session().settings().hiddenPinnedMessageId(
_peer->id); // _peer->id);
if (hiddenId == pinnedId.msg) { // if (hiddenId == pinnedId.msg) {
pinnedId = FullMsgId(); // pinnedId = FullMsgId();
} else if (hiddenId) { // } else if (hiddenId) {
session().settings().setHiddenPinnedMessageId(_peer->id, 0); // session().settings().setHiddenPinnedMessageId(_peer->id, 0);
session().saveSettings(); // session().saveSettings();
} // }
} // }
if (pinnedId) { // if (pinnedId) {
if (!_pinnedBar) { // if (!_pinnedBar) {
_pinnedBar = std::make_unique<PinnedBar>(pinnedId.msg, this); // _pinnedBar = std::make_unique<PinnedBar>(pinnedId.msg, this);
if (_a_show.animating()) { // if (_a_show.animating()) {
_pinnedBar->cancel->hide(); // _pinnedBar->cancel->hide();
_pinnedBar->shadow->hide(); // _pinnedBar->bar->widget()->hide();
} else { // _pinnedBar->shadow->hide();
_pinnedBar->cancel->show(); // } else {
_pinnedBar->shadow->show(); // _pinnedBar->cancel->show();
} // _pinnedBar->bar->widget()->show();
_pinnedBar->cancel->addClickHandler([=] { // _pinnedBar->shadow->show();
hidePinnedMessage(); // }
}); // _pinnedBar->cancel->addClickHandler([=] {
orderWidgets(); // hidePinnedMessage();
// });
updatePinnedBar(); // orderWidgets();
result = true; //
// updatePinnedBar();
const auto barTop = unreadBarTop(); // result = true;
if (!barTop || _scroll->scrollTop() != *barTop) { //
synteticScrollToY(_scroll->scrollTop() + st::historyReplyHeight); // const auto barTop = unreadBarTop();
} // if (!barTop || _scroll->scrollTop() != *barTop) {
} else if (_pinnedBar->msgId != pinnedId.msg) { // synteticScrollToY(_scroll->scrollTop() + st::historyReplyHeight);
_pinnedBar->msgId = pinnedId.msg; // }
_pinnedBar->msg = nullptr; // } else if (_pinnedBar->msgId != pinnedId.msg) {
_pinnedBar->text.clear(); // _pinnedBar->msgId = pinnedId.msg;
updatePinnedBar(); // _pinnedBar->msg = nullptr;
} // updatePinnedBar();
if (!_pinnedBar->msg) { // }
requestMessageData(_pinnedBar->msgId); // if (!_pinnedBar->msg) {
} // requestMessageData(_pinnedBar->msgId);
} else if (_pinnedBar) { // }
destroyPinnedBar(); // } else if (_pinnedBar) {
result = true; // destroyPinnedBar();
const auto barTop = unreadBarTop(); // result = true;
if (!barTop || _scroll->scrollTop() != *barTop) { // const auto barTop = unreadBarTop();
synteticScrollToY(_scroll->scrollTop() - st::historyReplyHeight); // if (!barTop || _scroll->scrollTop() != *barTop) {
} // synteticScrollToY(_scroll->scrollTop() - st::historyReplyHeight);
updateControlsGeometry(); // }
} // updateControlsGeometry();
return result; // }
} // return result;
//}
void HistoryWidget::requestMessageData(MsgId msgId) { void HistoryWidget::requestMessageData(MsgId msgId) {
const auto callback = [=](ChannelData *channel, MsgId msgId) { const auto callback = [=](ChannelData *channel, MsgId msgId) {
@ -5349,11 +5306,6 @@ void HistoryWidget::requestMessageData(MsgId msgId) {
crl::guard(this, callback)); crl::guard(this, callback));
} }
void HistoryWidget::destroyPinnedBar() {
_pinnedBar.reset();
_inPinnedMsg = false;
}
bool HistoryWidget::sendExistingDocument( bool HistoryWidget::sendExistingDocument(
not_null<DocumentData*> document, not_null<DocumentData*> document,
Api::SendOptions options) { Api::SendOptions options) {
@ -5622,25 +5574,25 @@ void HistoryWidget::UnpinMessage(not_null<PeerData*> peer, MsgId msgId) {
} }
void HistoryWidget::hidePinnedMessage() { void HistoryWidget::hidePinnedMessage() {
const auto pinnedId = _pinnedId; //const auto pinnedId = _pinnedId; // #TODO pinned
if (!pinnedId) { //if (!pinnedId) {
if (pinnedMsgVisibilityUpdated()) { // if (pinnedMsgVisibilityUpdated()) {
updateControlsGeometry(); // updateControlsGeometry();
update(); // update();
} // }
return; // return;
} //}
if (_peer->canPinMessages()) { //if (_peer->canPinMessages()) {
unpinMessage(pinnedId); // unpinMessage(pinnedId);
} else { //} else {
session().settings().setHiddenPinnedMessageId(_peer->id, pinnedId.msg); // session().settings().setHiddenPinnedMessageId(_peer->id, pinnedId.msg);
session().saveSettings(); // session().saveSettings();
if (pinnedMsgVisibilityUpdated()) { // if (pinnedMsgVisibilityUpdated()) {
updateControlsGeometry(); // updateControlsGeometry();
update(); // update();
} // }
} //}
} }
bool HistoryWidget::lastForceReplyReplied(const FullMsgId &replyTo) const { bool HistoryWidget::lastForceReplyReplied(const FullMsgId &replyTo) const {
@ -6080,13 +6032,12 @@ void HistoryWidget::updateTopBarSelection() {
} }
void HistoryWidget::messageDataReceived(ChannelData *channel, MsgId msgId) { void HistoryWidget::messageDataReceived(ChannelData *channel, MsgId msgId) {
if (!_peer || _peer->asChannel() != channel || !msgId) return; if (!_peer || _peer->asChannel() != channel || !msgId) {
return;
}
if (_editMsgId == msgId || _replyToId == msgId) { if (_editMsgId == msgId || _replyToId == msgId) {
updateReplyEditTexts(true); updateReplyEditTexts(true);
} }
if (_pinnedBar && _pinnedBar->msgId == msgId) {
updatePinnedBar(true);
}
} }
void HistoryWidget::updateReplyEditText(not_null<HistoryItem*> item) { void HistoryWidget::updateReplyEditText(not_null<HistoryItem*> item) {
@ -6420,49 +6371,49 @@ void HistoryWidget::drawRecording(Painter &p, float64 recordActive) {
p.setPen(anim::pen(st::historyRecordCancel, st::historyRecordCancelActive, 1. - recordActive)); p.setPen(anim::pen(st::historyRecordCancel, st::historyRecordCancelActive, 1. - recordActive));
p.drawText(left + (right - left - _recordCancelWidth) / 2, _attachToggle->y() + st::historyRecordTextTop + st::historyRecordFont->ascent, tr::lng_record_cancel(tr::now)); p.drawText(left + (right - left - _recordCancelWidth) / 2, _attachToggle->y() + st::historyRecordTextTop + st::historyRecordFont->ascent, tr::lng_record_cancel(tr::now));
} }
//
void HistoryWidget::drawPinnedBar(Painter &p) { //void HistoryWidget::drawPinnedBar(Painter &p) {
Expects(_pinnedBar != nullptr); // Expects(_pinnedBar != nullptr);
//
auto top = _topBar->bottomNoMargins(); // auto top = _topBar->bottomNoMargins();
p.fillRect(myrtlrect(0, top, width(), st::historyReplyHeight), st::historyPinnedBg); // p.fillRect(myrtlrect(0, top, width(), st::historyReplyHeight), st::historyPinnedBg);
//
top += st::msgReplyPadding.top(); // top += st::msgReplyPadding.top();
QRect rbar(myrtlrect(st::msgReplyBarSkip + st::msgReplyBarPos.x(), top + st::msgReplyBarPos.y(), st::msgReplyBarSize.width(), st::msgReplyBarSize.height())); // QRect rbar(myrtlrect(st::msgReplyBarSkip + st::msgReplyBarPos.x(), top + st::msgReplyBarPos.y(), st::msgReplyBarSize.width(), st::msgReplyBarSize.height()));
p.fillRect(rbar, st::msgInReplyBarColor); // p.fillRect(rbar, st::msgInReplyBarColor);
//
int32 left = st::msgReplyBarSkip + st::msgReplyBarSkip; // //int32 left = st::msgReplyBarSkip + st::msgReplyBarSkip;
if (_pinnedBar->msg) { // //if (_pinnedBar->msg) {
const auto media = _pinnedBar->msg->media(); // // const auto media = _pinnedBar->msg->media();
if (media && media->hasReplyPreview()) { // // if (media && media->hasReplyPreview()) {
if (const auto image = media->replyPreview()) { // // if (const auto image = media->replyPreview()) {
QRect to(left, top, st::msgReplyBarSize.height(), st::msgReplyBarSize.height()); // // QRect to(left, top, st::msgReplyBarSize.height(), st::msgReplyBarSize.height());
p.drawPixmap(to.x(), to.y(), image->pixSingle(image->width() / cIntRetinaFactor(), image->height() / cIntRetinaFactor(), to.width(), to.height(), ImageRoundRadius::Small)); // // 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(); // // left += st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x();
} // // }
p.setPen(st::historyReplyNameFg); // // p.setPen(st::historyReplyNameFg);
p.setFont(st::msgServiceNameFont); // // p.setFont(st::msgServiceNameFont);
const auto poll = media ? media->poll() : nullptr; // // const auto poll = media ? media->poll() : nullptr;
const auto pinnedHeader = (_pinnedBar->msgId < _peer->topPinnedMessageId()) // // const auto pinnedHeader = (_pinnedBar->msgId < _peer->topPinnedMessageId())
? tr::lng_pinned_previous(tr::now) // // ? tr::lng_pinned_previous(tr::now)
: !poll // // : !poll
? tr::lng_pinned_message(tr::now) // // ? tr::lng_pinned_message(tr::now)
: poll->quiz() // // : poll->quiz()
? tr::lng_pinned_quiz(tr::now) // // ? tr::lng_pinned_quiz(tr::now)
: tr::lng_pinned_poll(tr::now); // // : tr::lng_pinned_poll(tr::now);
p.drawText(left, top + st::msgServiceNameFont->ascent, pinnedHeader); // // p.drawText(left, top + st::msgServiceNameFont->ascent, pinnedHeader);
//
p.setPen(st::historyComposeAreaFg); // // p.setPen(st::historyComposeAreaFg);
p.setTextPalette(st::historyComposeAreaPalette); // // p.setTextPalette(st::historyComposeAreaPalette);
_pinnedBar->text.drawElided(p, left, top + st::msgServiceNameFont->height, width() - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right()); // // _pinnedBar->text.drawElided(p, left, top + st::msgServiceNameFont->height, width() - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right());
p.restoreTextPalette(); // // p.restoreTextPalette();
} else { // //} else {
p.setFont(st::msgDateFont); // // p.setFont(st::msgDateFont);
p.setPen(st::historyComposeAreaFgService); // // 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 - _pinnedBar->cancel->width() - st::msgReplyPadding.right())); // // 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 - _pinnedBar->cancel->width() - st::msgReplyPadding.right()));
} // //}
} //}
bool HistoryWidget::paintShowAnimationFrame() { bool HistoryWidget::paintShowAnimationFrame() {
auto progress = _a_show.value(1.); auto progress = _a_show.value(1.);
@ -6513,9 +6464,6 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
} else if (const auto error = writeRestriction()) { } else if (const auto error = writeRestriction()) {
drawRestrictedWrite(p, *error); drawRestrictedWrite(p, *error);
} }
if (_pinnedBar && !_pinnedBar->cancel->isHidden()) {
drawPinnedBar(p);
}
} else { } else {
const auto w = st::msgServiceFont->width(tr::lng_willbe_history(tr::now)) const auto w = st::msgServiceFont->width(tr::lng_willbe_history(tr::now))
+ st::msgPadding.left() + st::msgPadding.left()

View file

@ -66,6 +66,7 @@ class SilentToggle;
class FlatButton; class FlatButton;
class LinkButton; class LinkButton;
class RoundButton; class RoundButton;
class MessageBar;
namespace Toast { namespace Toast {
class Instance; class Instance;
} // namespace Toast } // namespace Toast
@ -94,6 +95,7 @@ class TopBarWidget;
class ContactStatus; class ContactStatus;
class Element; class Element;
class PinnedTracker; class PinnedTracker;
class PinnedBar;
} // namespace HistoryView } // namespace HistoryView
class DragArea; class DragArea;
@ -326,16 +328,6 @@ private slots:
private: private:
using TabbedPanel = ChatHelpers::TabbedPanel; using TabbedPanel = ChatHelpers::TabbedPanel;
using TabbedSelector = ChatHelpers::TabbedSelector; using TabbedSelector = ChatHelpers::TabbedSelector;
struct PinnedBar {
PinnedBar(MsgId msgId, HistoryWidget *parent);
~PinnedBar();
MsgId msgId = 0;
HistoryItem *msg = nullptr;
Ui::Text::String text;
object_ptr<Ui::IconButton> cancel;
object_ptr<Ui::PlainShadow> shadow;
};
enum ScrollChangeType { enum ScrollChangeType {
ScrollChangeNone, ScrollChangeNone,
@ -492,10 +484,6 @@ private:
void updateReplyEditTexts(bool force = false); void updateReplyEditTexts(bool force = false);
void updateReplyEditText(not_null<HistoryItem*> item); void updateReplyEditText(not_null<HistoryItem*> item);
void showPinnedMessage(FullMsgId id);
void updatePinnedBar(bool force = false);
bool pinnedMsgVisibilityUpdated();
void destroyPinnedBar();
void updatePinnedViewer(); void updatePinnedViewer();
void setupPinnedTracker(); void setupPinnedTracker();
@ -511,7 +499,6 @@ private:
int left, int left,
int top) const; int top) const;
void drawRecording(Painter &p, float64 recordActive); void drawRecording(Painter &p, float64 recordActive);
void drawPinnedBar(Painter &p);
void drawRestrictedWrite(Painter &p, const QString &error); void drawRestrictedWrite(Painter &p, const QString &error);
bool paintShowAnimationFrame(); bool paintShowAnimationFrame();
@ -614,9 +601,9 @@ private:
object_ptr<Ui::IconButton> _fieldBarCancel; object_ptr<Ui::IconButton> _fieldBarCancel;
FullMsgId _pinnedId;
std::unique_ptr<PinnedBar> _pinnedBar;
std::unique_ptr<HistoryView::PinnedTracker> _pinnedTracker; std::unique_ptr<HistoryView::PinnedTracker> _pinnedTracker;
std::unique_ptr<HistoryView::PinnedBar> _pinnedBar;
int _pinnedBarHeight = 0;
mtpRequestId _saveEditMsgRequestId = 0; mtpRequestId _saveEditMsgRequestId = 0;
@ -705,7 +692,6 @@ private:
bool _recording = false; bool _recording = false;
bool _inField = false; bool _inField = false;
bool _inReplyEditForward = false; bool _inReplyEditForward = false;
bool _inPinnedMsg = false;
bool _inClickable = false; bool _inClickable = false;
int _recordingSamples = 0; int _recordingSamples = 0;
int _recordCancelWidth; int _recordCancelWidth;

View file

@ -0,0 +1,229 @@
/*
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_pinned_bar.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "data/data_session.h"
#include "data/data_changes.h"
#include "data/data_poll.h"
#include "ui/widgets/shadow.h"
#include "ui/widgets/buttons.h"
#include "history/history_item.h"
#include "history/history.h"
#include "apiwrap.h"
#include "styles/style_chat.h"
namespace HistoryView {
namespace {
[[nodiscard]] rpl::producer<Ui::MessageBarContent> ContentByItem(
not_null<HistoryItem*> item) {
return item->history()->session().changes().messageFlagsValue(
item,
Data::MessageUpdate::Flag::Edited
) | rpl::map([=] {
const auto media = item->media();
const auto poll = media ? media->poll() : nullptr;
return Ui::MessageBarContent{
.id = item->id,
.title = ((item->id < item->history()->peer->topPinnedMessageId())
? tr::lng_pinned_previous(tr::now)
: !poll
? tr::lng_pinned_message(tr::now)
: poll->quiz()
? tr::lng_pinned_quiz(tr::now)
: tr::lng_pinned_poll(tr::now)),
.text = item->inReplyText(),
};
});
}
[[nodiscard]] rpl::producer<Ui::MessageBarContent> ContentByItemId(
not_null<Main::Session*> session,
FullMsgId id,
bool alreadyLoaded = false) {
if (!id) {
return rpl::single(Ui::MessageBarContent());
} else if (const auto item = session->data().message(id)) {
return ContentByItem(item);
} else if (alreadyLoaded) {
return rpl::single(Ui::MessageBarContent()); // Deleted message?..
}
auto load = rpl::make_producer<Ui::MessageBarContent>([=](auto consumer) {
consumer.put_next(Ui::MessageBarContent{
.text = tr::lng_contacts_loading(tr::now),
});
const auto channel = id.channel
? session->data().channel(id.channel).get()
: nullptr;
const auto callback = [=](ChannelData *channel, MsgId id) {
consumer.put_done();
};
session->api().requestMessageData(channel, id.msg, callback);
return rpl::lifetime();
});
return std::move(
load
) | rpl::then(rpl::deferred([=] {
return ContentByItemId(session, id, true);
}));
}
} // namespace
PinnedBar::PinnedBar(
not_null<QWidget*> parent,
not_null<Main::Session*> session,
rpl::producer<FullMsgId> itemId,
bool withClose)
: _wrap(parent, object_ptr<Ui::RpWidget>(parent))
, _close(withClose
? std::make_unique<Ui::IconButton>(
_wrap.entity(),
st::historyReplyCancel)
: nullptr)
, _shadow(std::make_unique<Ui::PlainShadow>(_wrap.parentWidget())) {
_wrap.hide(anim::type::instant);
_shadow->hide();
_wrap.entity()->paintRequest(
) | rpl::start_with_next([=](QRect clip) {
QPainter(_wrap.entity()).fillRect(clip, st::historyPinnedBg);
}, lifetime());
_wrap.setAttribute(Qt::WA_OpaquePaintEvent);
rpl::duplicate(
itemId
) | rpl::distinct_until_changed(
) | rpl::map([=](FullMsgId id) {
return ContentByItemId(session, id);
}) | rpl::flatten_latest(
) | rpl::filter([=](const Ui::MessageBarContent &content) {
return !content.title.isEmpty() || !content.text.text.isEmpty();
}) | rpl::start_with_next([=](Ui::MessageBarContent &&content) {
const auto creating = !_bar;
if (creating) {
createControls();
}
_bar->set(std::move(content));
if (creating) {
_bar->finishAnimating();
}
}, lifetime());
std::move(
itemId
) | rpl::map([=](FullMsgId id) {
return !id;
}) | rpl::start_with_next([=](bool hidden) {
_shouldBeShown = !hidden;
if (!_forceHidden) {
_wrap.toggle(_shouldBeShown, anim::type::normal);
} else if (!_shouldBeShown) {
_bar = nullptr;
}
}, lifetime());
}
void PinnedBar::createControls() {
Expects(!_bar);
_bar = std::make_unique<Ui::MessageBar>(
_wrap.entity(),
st::defaultMessageBar);
if (_close) {
_close->raise();
}
_bar->widget()->move(0, 0);
_bar->widget()->show();
_wrap.entity()->resize(_wrap.entity()->width(), _bar->widget()->height());
_wrap.geometryValue(
) | rpl::start_with_next([=](QRect rect) {
_shadow->setGeometry(
rect.x(),
rect.y() + rect.height(),
rect.width(),
st::lineWidth);
_bar->widget()->resizeToWidth(
rect.width() - (_close ? _close->width() : 0));
const auto hidden = _wrap.isHidden() || !rect.height();
if (_shadow->isHidden() != hidden) {
_shadow->setVisible(!hidden);
}
if (_close) {
_close->moveToRight(0, 0);
}
}, _bar->widget()->lifetime());
_wrap.shownValue(
) | rpl::skip(
1
) | rpl::filter([=](bool shown) {
return !shown && !_forceHidden;
}) | rpl::start_with_next([=] {
_bar = nullptr;
}, _bar->widget()->lifetime());
Ensures(_bar != nullptr);
}
void PinnedBar::show() {
if (!_forceHidden) {
return;
}
_forceHidden = false;
if (_shouldBeShown) {
_wrap.show(anim::type::instant);
_shadow->show();
}
}
void PinnedBar::hide() {
if (_forceHidden) {
return;
}
_forceHidden = true;
_wrap.hide(anim::type::instant);
_shadow->hide();
}
void PinnedBar::raise() {
_wrap.raise();
_shadow->raise();
}
void PinnedBar::move(int x, int y) {
_wrap.move(x, y);
}
void PinnedBar::resizeToWidth(int width) {
_wrap.entity()->resizeToWidth(width);
}
int PinnedBar::height() const {
return !_forceHidden
? _wrap.height()
: _shouldBeShown
? st::historyReplyHeight
: 0;
}
rpl::producer<int> PinnedBar::heightValue() const {
return _wrap.heightValue();
}
rpl::producer<> PinnedBar::closeClicks() const {
return !_close
? (rpl::never<>() | rpl::type_erased())
: (_close->clicks() | rpl::map([] { return rpl::empty_value(); }));
}
} // namespace HistoryView

View file

@ -0,0 +1,59 @@
/*
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 "ui/wrap/slide_wrap.h"
#include "ui/chat/message_bar.h"
namespace Main {
class Session;
} // namespace Main
namespace Ui {
class IconButton;
class PlainShadow;
} // namespace Ui
namespace HistoryView {
class PinnedBar final {
public:
PinnedBar(
not_null<QWidget*> parent,
not_null<Main::Session*> session,
rpl::producer<FullMsgId> itemId,
bool withClose = false);
void show();
void hide();
void raise();
void move(int x, int y);
void resizeToWidth(int width);
[[nodiscard]] int height() const;
[[nodiscard]] rpl::producer<int> heightValue() const;
[[nodiscard]] rpl::producer<> closeClicks() const;
[[nodiscard]] rpl::lifetime &lifetime() {
return _wrap.lifetime();
}
private:
void createControls();
Ui::SlideWrap<> _wrap;
std::unique_ptr<Ui::MessageBar> _bar;
std::unique_ptr<Ui::IconButton> _close;
std::unique_ptr<Ui::PlainShadow> _shadow;
rpl::event_stream<Ui::MessageBarContent> _content;
bool _shouldBeShown = false;
bool _forceHidden = false;
};
} // namespace HistoryView

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_options.h" #include "ui/text/text_options.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/palette.h"
namespace Ui { namespace Ui {
@ -205,7 +206,7 @@ void MessageBar::paint(Painter &p) {
const auto imageShown = _animation const auto imageShown = _animation
? _animation->imageShown.value(imageFinal) ? _animation->imageShown.value(imageFinal)
: imageFinal; : imageFinal;
if (progress == 1. && imageShown == 1. && _animation) { if (progress == 1. && imageShown == imageFinal && _animation) {
_animation = nullptr; _animation = nullptr;
} }
const auto body = [&] { const auto body = [&] {
@ -237,6 +238,13 @@ void MessageBar::paint(Painter &p) {
? (shiftTo - shiftFull) ? (shiftTo - shiftFull)
: (shiftTo + shiftFull); : (shiftTo + shiftFull);
const auto bar = QRect(
st::msgReplyBarSkip + st::msgReplyBarPos.x(),
st::msgReplyPadding.top() + st::msgReplyBarPos.y(),
st::msgReplyBarSize.width(),
st::msgReplyBarSize.height());
p.fillRect(bar, st::msgInReplyBarColor);
if (!_animation) { if (!_animation) {
if (!_image.isNull()) { if (!_image.isNull()) {
p.drawPixmap(image, _image); p.drawPixmap(image, _image);
@ -261,6 +269,7 @@ void MessageBar::paint(Painter &p) {
_animation->imageFrom); _animation->imageFrom);
p.setOpacity(progress); p.setOpacity(progress);
p.drawPixmap(rect.translated(0, shiftTo), _animation->imageTo); p.drawPixmap(rect.translated(0, shiftTo), _animation->imageTo);
p.setOpacity(1.);
} else { } else {
p.drawPixmap(rect, _image); p.drawPixmap(rect, _image);
} }
@ -277,6 +286,7 @@ void MessageBar::paint(Painter &p) {
_animation->bodyOrTextFrom); _animation->bodyOrTextFrom);
p.setOpacity(progress); p.setOpacity(progress);
p.drawPixmap(body.x(), text.y() + shiftTo, _animation->bodyOrTextTo); p.drawPixmap(body.x(), text.y() + shiftTo, _animation->bodyOrTextTo);
p.setOpacity(1.);
} }
if (!_animation || _animation->bodyAnimation != BodyAnimation::Full) { if (!_animation || _animation->bodyAnimation != BodyAnimation::Full) {
p.setPen(_st.titleFg); p.setPen(_st.titleFg);
@ -289,6 +299,7 @@ void MessageBar::paint(Painter &p) {
_animation->bodyOrTextFrom); _animation->bodyOrTextFrom);
p.setOpacity(progress); p.setOpacity(progress);
p.drawPixmap(body.x(), body.y() + shiftTo, _animation->bodyOrTextTo); p.drawPixmap(body.x(), body.y() + shiftTo, _animation->bodyOrTextTo);
p.setOpacity(1.);
} }
} }