mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-08 08:04:08 +02:00
Implement local pinned bar hiding.
This commit is contained in:
parent
67290eed58
commit
91a0416037
10 changed files with 167 additions and 131 deletions
|
@ -166,6 +166,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_pinned_quiz" = "Pinned quiz";
|
"lng_pinned_quiz" = "Pinned quiz";
|
||||||
"lng_pinned_unpin_sure" = "Would you like to unpin this message?";
|
"lng_pinned_unpin_sure" = "Would you like to unpin this message?";
|
||||||
"lng_pinned_pin_sure" = "Would you like to pin this message?";
|
"lng_pinned_pin_sure" = "Would you like to pin this message?";
|
||||||
|
"lng_pinned_pin_old_sure" = "Do you want to pin an older message while leaving a more recent one pinned?";
|
||||||
"lng_pinned_pin" = "Pin";
|
"lng_pinned_pin" = "Pin";
|
||||||
"lng_pinned_unpin" = "Unpin";
|
"lng_pinned_unpin" = "Unpin";
|
||||||
"lng_pinned_notify" = "Notify all members";
|
"lng_pinned_notify" = "Notify all members";
|
||||||
|
|
|
@ -448,7 +448,7 @@ PinMessageBox::PinMessageBox(
|
||||||
, _text(
|
, _text(
|
||||||
this,
|
this,
|
||||||
(_pinningOld
|
(_pinningOld
|
||||||
? "Do you want to pin an older message while leaving a more recent one pinned?" // #TODO pinned
|
? tr::lng_pinned_pin_old_sure(tr::now)
|
||||||
: tr::lng_pinned_pin_sure(tr::now)),
|
: tr::lng_pinned_pin_sure(tr::now)),
|
||||||
st::boxLabel) {
|
st::boxLabel) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
#include "main/main_session_settings.h"
|
||||||
#include "main/main_account.h"
|
#include "main/main_account.h"
|
||||||
#include "main/main_domain.h"
|
#include "main/main_domain.h"
|
||||||
#include "main/main_app_config.h"
|
#include "main/main_app_config.h"
|
||||||
|
@ -469,14 +470,12 @@ void PeerData::ensurePinnedMessagesCreated() {
|
||||||
if (!_pinnedMessages) {
|
if (!_pinnedMessages) {
|
||||||
_pinnedMessages = std::make_unique<Data::PinnedMessages>(
|
_pinnedMessages = std::make_unique<Data::PinnedMessages>(
|
||||||
peerToChannel(id));
|
peerToChannel(id));
|
||||||
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerData::removeEmptyPinnedMessages() {
|
void PeerData::removeEmptyPinnedMessages() {
|
||||||
if (_pinnedMessages && _pinnedMessages->empty()) {
|
if (_pinnedMessages && _pinnedMessages->empty()) {
|
||||||
_pinnedMessages = nullptr;
|
_pinnedMessages = nullptr;
|
||||||
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,18 +488,30 @@ bool PeerData::messageIdTooSmall(MsgId messageId) const {
|
||||||
|
|
||||||
void PeerData::setTopPinnedMessageId(MsgId messageId) {
|
void PeerData::setTopPinnedMessageId(MsgId messageId) {
|
||||||
if (messageIdTooSmall(messageId)) {
|
if (messageIdTooSmall(messageId)) {
|
||||||
|
clearPinnedMessages();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (session().settings().hiddenPinnedMessageId(id) != messageId) {
|
||||||
|
session().settings().setHiddenPinnedMessageId(id, 0);
|
||||||
|
session().saveSettingsDelayed();
|
||||||
|
}
|
||||||
ensurePinnedMessagesCreated();
|
ensurePinnedMessagesCreated();
|
||||||
_pinnedMessages->setTopId(messageId);
|
_pinnedMessages->setTopId(messageId);
|
||||||
|
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerData::clearPinnedMessages(MsgId lessThanId) {
|
void PeerData::clearPinnedMessages(MsgId lessThanId) {
|
||||||
|
if (lessThanId == ServerMaxMsgId
|
||||||
|
&& session().settings().hiddenPinnedMessageId(id) != 0) {
|
||||||
|
session().settings().setHiddenPinnedMessageId(id, 0);
|
||||||
|
session().saveSettingsDelayed();
|
||||||
|
}
|
||||||
if (!_pinnedMessages) {
|
if (!_pinnedMessages) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_pinnedMessages->clearLessThanId(lessThanId);
|
_pinnedMessages->clearLessThanId(lessThanId);
|
||||||
removeEmptyPinnedMessages();
|
removeEmptyPinnedMessages();
|
||||||
|
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerData::addPinnedMessage(MsgId messageId) {
|
void PeerData::addPinnedMessage(MsgId messageId) {
|
||||||
|
@ -509,6 +520,7 @@ void PeerData::addPinnedMessage(MsgId messageId) {
|
||||||
}
|
}
|
||||||
ensurePinnedMessagesCreated();
|
ensurePinnedMessagesCreated();
|
||||||
_pinnedMessages->add(messageId);
|
_pinnedMessages->add(messageId);
|
||||||
|
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerData::addPinnedSlice(
|
void PeerData::addPinnedSlice(
|
||||||
|
@ -532,6 +544,7 @@ void PeerData::addPinnedSlice(
|
||||||
}
|
}
|
||||||
ensurePinnedMessagesCreated();
|
ensurePinnedMessagesCreated();
|
||||||
_pinnedMessages->add(std::move(ids), noSkipRange, std::nullopt);
|
_pinnedMessages->add(std::move(ids), noSkipRange, std::nullopt);
|
||||||
|
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerData::removePinnedMessage(MsgId messageId) {
|
void PeerData::removePinnedMessage(MsgId messageId) {
|
||||||
|
@ -540,6 +553,7 @@ void PeerData::removePinnedMessage(MsgId messageId) {
|
||||||
}
|
}
|
||||||
_pinnedMessages->remove(messageId);
|
_pinnedMessages->remove(messageId);
|
||||||
removeEmptyPinnedMessages();
|
removeEmptyPinnedMessages();
|
||||||
|
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerData::canExportChatHistory() const {
|
bool PeerData::canExportChatHistory() const {
|
||||||
|
|
|
@ -1005,9 +1005,12 @@ void History::applyServiceChanges(
|
||||||
case mtpc_messageActionPinMessage: {
|
case mtpc_messageActionPinMessage: {
|
||||||
if (const auto replyTo = data.vreply_to()) {
|
if (const auto replyTo = data.vreply_to()) {
|
||||||
replyTo->match([&](const MTPDmessageReplyHeader &data) {
|
replyTo->match([&](const MTPDmessageReplyHeader &data) {
|
||||||
|
const auto id = data.vreply_to_msg_id().v;
|
||||||
if (item) {
|
if (item) {
|
||||||
//item->history()->peer->setTopPinnedMessageId( // #TODO pinned
|
item->history()->peer->addPinnedSlice(
|
||||||
// data.vreply_to_msg_id().v);
|
{ id },
|
||||||
|
{ id, ServerMaxMsgId },
|
||||||
|
std::nullopt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -563,6 +563,7 @@ HistoryWidget::HistoryWidget(
|
||||||
| UpdateFlag::ChannelLinkedChat
|
| UpdateFlag::ChannelLinkedChat
|
||||||
| UpdateFlag::Slowmode
|
| UpdateFlag::Slowmode
|
||||||
| UpdateFlag::BotStartToken
|
| UpdateFlag::BotStartToken
|
||||||
|
| UpdateFlag::PinnedMessage
|
||||||
) | rpl::filter([=](const Data::PeerUpdate &update) {
|
) | rpl::filter([=](const Data::PeerUpdate &update) {
|
||||||
return (update.peer.get() == _peer);
|
return (update.peer.get() == _peer);
|
||||||
}) | rpl::map([](const Data::PeerUpdate &update) {
|
}) | rpl::map([](const Data::PeerUpdate &update) {
|
||||||
|
@ -603,6 +604,9 @@ HistoryWidget::HistoryWidget(
|
||||||
| UpdateFlag::ChannelLinkedChat)) {
|
| UpdateFlag::ChannelLinkedChat)) {
|
||||||
handlePeerUpdate();
|
handlePeerUpdate();
|
||||||
}
|
}
|
||||||
|
if (_pinnedTracker && (flags & UpdateFlag::PinnedMessage)) {
|
||||||
|
checkPinnedBarState();
|
||||||
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
rpl::merge(
|
rpl::merge(
|
||||||
|
@ -5211,12 +5215,50 @@ void HistoryWidget::setupPinnedTracker() {
|
||||||
Expects(_history != nullptr);
|
Expects(_history != nullptr);
|
||||||
|
|
||||||
_pinnedTracker = std::make_unique<HistoryView::PinnedTracker>(_history);
|
_pinnedTracker = std::make_unique<HistoryView::PinnedTracker>(_history);
|
||||||
|
_pinnedBar = nullptr;
|
||||||
|
checkPinnedBarState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryWidget::checkPinnedBarState() {
|
||||||
|
Expects(_pinnedTracker != nullptr);
|
||||||
|
|
||||||
|
const auto hiddenId = _peer->canPinMessages()
|
||||||
|
? MsgId(0)
|
||||||
|
: session().settings().hiddenPinnedMessageId(_peer->id);
|
||||||
|
const auto currentPinnedId = _peer->topPinnedMessageId();
|
||||||
|
if (currentPinnedId == hiddenId) {
|
||||||
|
if (_pinnedBar) {
|
||||||
|
_pinnedTracker->reset();
|
||||||
|
auto qobject = base::unique_qptr{
|
||||||
|
Ui::WrapAsQObject(this, std::move(_pinnedBar)).get()
|
||||||
|
};
|
||||||
|
auto destroyer = [this, object = std::move(qobject)]() mutable {
|
||||||
|
object = nullptr;
|
||||||
|
updateHistoryGeometry();
|
||||||
|
updateControlsGeometry();
|
||||||
|
};
|
||||||
|
base::call_delayed(
|
||||||
|
st::defaultMessageBar.duration,
|
||||||
|
this,
|
||||||
|
std::move(destroyer));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_pinnedBar || !currentPinnedId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shown = _pinnedTracker->shownMessageId(
|
||||||
|
) | rpl::map([=](HistoryView::PinnedId messageId) {
|
||||||
|
return HistoryView::PinnedBarId{
|
||||||
|
FullMsgId{ peerToChannel(_peer->id), messageId.message },
|
||||||
|
messageId.type
|
||||||
|
};
|
||||||
|
});
|
||||||
_pinnedBar = std::make_unique<HistoryView::PinnedBar>(
|
_pinnedBar = std::make_unique<HistoryView::PinnedBar>(
|
||||||
this,
|
this,
|
||||||
&session(),
|
&session(),
|
||||||
_pinnedTracker->shownMessageId() | rpl::map([=](MsgId messageId) {
|
std::move(shown),
|
||||||
return FullMsgId{ peerToChannel(_peer->id), messageId };
|
|
||||||
}),
|
|
||||||
true);
|
true);
|
||||||
|
|
||||||
_pinnedBar->closeClicks(
|
_pinnedBar->closeClicks(
|
||||||
|
@ -5233,68 +5275,13 @@ void HistoryWidget::setupPinnedTracker() {
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
_topDelta = 0;
|
_topDelta = 0;
|
||||||
}, _pinnedBar->lifetime());
|
}, _pinnedBar->lifetime());
|
||||||
|
|
||||||
orderWidgets();
|
orderWidgets();
|
||||||
|
|
||||||
if (_a_show.animating()) {
|
if (_a_show.animating()) {
|
||||||
_pinnedBar->hide();
|
_pinnedBar->hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
//bool HistoryWidget::pinnedMsgVisibilityUpdated() {
|
|
||||||
// auto result = false;
|
|
||||||
// auto pinnedId = _pinnedId;
|
|
||||||
// if (pinnedId && !_peer->canPinMessages()) {
|
|
||||||
// const auto hiddenId = session().settings().hiddenPinnedMessageId(
|
|
||||||
// _peer->id);
|
|
||||||
// if (hiddenId == pinnedId.msg) {
|
|
||||||
// pinnedId = FullMsgId();
|
|
||||||
// } else if (hiddenId) {
|
|
||||||
// session().settings().setHiddenPinnedMessageId(_peer->id, 0);
|
|
||||||
// session().saveSettings();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (pinnedId) {
|
|
||||||
// if (!_pinnedBar) {
|
|
||||||
// _pinnedBar = std::make_unique<PinnedBar>(pinnedId.msg, this);
|
|
||||||
// if (_a_show.animating()) {
|
|
||||||
// _pinnedBar->cancel->hide();
|
|
||||||
// _pinnedBar->bar->widget()->hide();
|
|
||||||
// _pinnedBar->shadow->hide();
|
|
||||||
// } else {
|
|
||||||
// _pinnedBar->cancel->show();
|
|
||||||
// _pinnedBar->bar->widget()->show();
|
|
||||||
// _pinnedBar->shadow->show();
|
|
||||||
// }
|
|
||||||
// _pinnedBar->cancel->addClickHandler([=] {
|
|
||||||
// hidePinnedMessage();
|
|
||||||
// });
|
|
||||||
// orderWidgets();
|
|
||||||
//
|
|
||||||
// updatePinnedBar();
|
|
||||||
// result = true;
|
|
||||||
//
|
|
||||||
// const auto barTop = unreadBarTop();
|
|
||||||
// if (!barTop || _scroll->scrollTop() != *barTop) {
|
|
||||||
// synteticScrollToY(_scroll->scrollTop() + st::historyReplyHeight);
|
|
||||||
// }
|
|
||||||
// } else if (_pinnedBar->msgId != pinnedId.msg) {
|
|
||||||
// _pinnedBar->msgId = pinnedId.msg;
|
|
||||||
// _pinnedBar->msg = nullptr;
|
|
||||||
// updatePinnedBar();
|
|
||||||
// }
|
|
||||||
// if (!_pinnedBar->msg) {
|
|
||||||
// requestMessageData(_pinnedBar->msgId);
|
|
||||||
// }
|
|
||||||
// } else if (_pinnedBar) {
|
|
||||||
// destroyPinnedBar();
|
|
||||||
// result = true;
|
|
||||||
// const auto barTop = unreadBarTop();
|
|
||||||
// if (!barTop || _scroll->scrollTop() != *barTop) {
|
|
||||||
// synteticScrollToY(_scroll->scrollTop() - st::historyReplyHeight);
|
|
||||||
// }
|
|
||||||
// updateControlsGeometry();
|
|
||||||
// }
|
|
||||||
// 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) {
|
||||||
|
@ -5574,25 +5561,25 @@ void HistoryWidget::UnpinMessage(not_null<PeerData*> peer, MsgId msgId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::hidePinnedMessage() {
|
void HistoryWidget::hidePinnedMessage() {
|
||||||
//const auto pinnedId = _pinnedId; // #TODO pinned
|
Expects(_pinnedBar != nullptr);
|
||||||
//if (!pinnedId) {
|
|
||||||
// if (pinnedMsgVisibilityUpdated()) {
|
|
||||||
// updateControlsGeometry();
|
|
||||||
// update();
|
|
||||||
// }
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (_peer->canPinMessages()) {
|
const auto id = _pinnedTracker->currentMessageId();
|
||||||
// unpinMessage(pinnedId);
|
if (!id.message) {
|
||||||
//} else {
|
return;
|
||||||
// session().settings().setHiddenPinnedMessageId(_peer->id, pinnedId.msg);
|
}
|
||||||
// session().saveSettings();
|
if (_peer->canPinMessages()) {
|
||||||
// if (pinnedMsgVisibilityUpdated()) {
|
unpinMessage({ peerToChannel(_peer->id), id.message });
|
||||||
// updateControlsGeometry();
|
} else {
|
||||||
// update();
|
const auto top = _peer->topPinnedMessageId();
|
||||||
// }
|
if (top) {
|
||||||
//}
|
session().settings().setHiddenPinnedMessageId(_peer->id, top);
|
||||||
|
session().saveSettingsDelayed();
|
||||||
|
|
||||||
|
checkPinnedBarState();
|
||||||
|
} else {
|
||||||
|
session().api().requestFullPeer(_peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryWidget::lastForceReplyReplied(const FullMsgId &replyTo) const {
|
bool HistoryWidget::lastForceReplyReplied(const FullMsgId &replyTo) const {
|
||||||
|
@ -6373,16 +6360,6 @@ void HistoryWidget::drawRecording(Painter &p, float64 recordActive) {
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//void HistoryWidget::drawPinnedBar(Painter &p) {
|
//void HistoryWidget::drawPinnedBar(Painter &p) {
|
||||||
// Expects(_pinnedBar != nullptr);
|
|
||||||
//
|
|
||||||
// auto top = _topBar->bottomNoMargins();
|
|
||||||
// p.fillRect(myrtlrect(0, top, width(), st::historyReplyHeight), st::historyPinnedBg);
|
|
||||||
//
|
|
||||||
// top += st::msgReplyPadding.top();
|
|
||||||
// QRect rbar(myrtlrect(st::msgReplyBarSkip + st::msgReplyBarPos.x(), top + st::msgReplyBarPos.y(), st::msgReplyBarSize.width(), st::msgReplyBarSize.height()));
|
|
||||||
// p.fillRect(rbar, st::msgInReplyBarColor);
|
|
||||||
//
|
|
||||||
// //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()) {
|
||||||
|
@ -6392,22 +6369,6 @@ void HistoryWidget::drawRecording(Painter &p, float64 recordActive) {
|
||||||
// // }
|
// // }
|
||||||
// // 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.setFont(st::msgServiceNameFont);
|
|
||||||
// // const auto poll = media ? media->poll() : nullptr;
|
|
||||||
// // const auto pinnedHeader = (_pinnedBar->msgId < _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);
|
|
||||||
// // p.drawText(left, top + st::msgServiceNameFont->ascent, pinnedHeader);
|
|
||||||
//
|
|
||||||
// // p.setPen(st::historyComposeAreaFg);
|
|
||||||
// // p.setTextPalette(st::historyComposeAreaPalette);
|
|
||||||
// // _pinnedBar->text.drawElided(p, left, top + st::msgServiceNameFont->height, width() - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right());
|
|
||||||
// // p.restoreTextPalette();
|
|
||||||
// //} else {
|
// //} else {
|
||||||
// // p.setFont(st::msgDateFont);
|
// // p.setFont(st::msgDateFont);
|
||||||
// // p.setPen(st::historyComposeAreaFgService);
|
// // p.setPen(st::historyComposeAreaFgService);
|
||||||
|
|
|
@ -486,6 +486,7 @@ private:
|
||||||
|
|
||||||
void updatePinnedViewer();
|
void updatePinnedViewer();
|
||||||
void setupPinnedTracker();
|
void setupPinnedTracker();
|
||||||
|
void checkPinnedBarState();
|
||||||
|
|
||||||
void sendInlineResult(
|
void sendInlineResult(
|
||||||
not_null<InlineBots::Result*> result,
|
not_null<InlineBots::Result*> result,
|
||||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_poll.h"
|
#include "data/data_poll.h"
|
||||||
#include "ui/widgets/shadow.h"
|
#include "ui/widgets/shadow.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
#include "history/view/history_view_pinned_tracker.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
@ -23,7 +24,8 @@ namespace HistoryView {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<Ui::MessageBarContent> ContentByItem(
|
[[nodiscard]] rpl::producer<Ui::MessageBarContent> ContentByItem(
|
||||||
not_null<HistoryItem*> item) {
|
not_null<HistoryItem*> item,
|
||||||
|
PinnedIdType type) {
|
||||||
return item->history()->session().changes().messageFlagsValue(
|
return item->history()->session().changes().messageFlagsValue(
|
||||||
item,
|
item,
|
||||||
Data::MessageUpdate::Flag::Edited
|
Data::MessageUpdate::Flag::Edited
|
||||||
|
@ -32,7 +34,9 @@ namespace {
|
||||||
const auto poll = media ? media->poll() : nullptr;
|
const auto poll = media ? media->poll() : nullptr;
|
||||||
return Ui::MessageBarContent{
|
return Ui::MessageBarContent{
|
||||||
.id = item->id,
|
.id = item->id,
|
||||||
.title = ((item->id < item->history()->peer->topPinnedMessageId())
|
.title = ((type == PinnedIdType::First)
|
||||||
|
? "First message"
|
||||||
|
: (type == PinnedIdType::Middle)
|
||||||
? 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)
|
||||||
|
@ -46,12 +50,12 @@ namespace {
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<Ui::MessageBarContent> ContentByItemId(
|
[[nodiscard]] rpl::producer<Ui::MessageBarContent> ContentByItemId(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
FullMsgId id,
|
PinnedBarId id,
|
||||||
bool alreadyLoaded = false) {
|
bool alreadyLoaded = false) {
|
||||||
if (!id) {
|
if (!id.message) {
|
||||||
return rpl::single(Ui::MessageBarContent());
|
return rpl::single(Ui::MessageBarContent());
|
||||||
} else if (const auto item = session->data().message(id)) {
|
} else if (const auto item = session->data().message(id.message)) {
|
||||||
return ContentByItem(item);
|
return ContentByItem(item, id.type);
|
||||||
} else if (alreadyLoaded) {
|
} else if (alreadyLoaded) {
|
||||||
return rpl::single(Ui::MessageBarContent()); // Deleted message?..
|
return rpl::single(Ui::MessageBarContent()); // Deleted message?..
|
||||||
}
|
}
|
||||||
|
@ -59,13 +63,13 @@ namespace {
|
||||||
consumer.put_next(Ui::MessageBarContent{
|
consumer.put_next(Ui::MessageBarContent{
|
||||||
.text = tr::lng_contacts_loading(tr::now),
|
.text = tr::lng_contacts_loading(tr::now),
|
||||||
});
|
});
|
||||||
const auto channel = id.channel
|
const auto channel = id.message.channel
|
||||||
? session->data().channel(id.channel).get()
|
? session->data().channel(id.message.channel).get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto callback = [=](ChannelData *channel, MsgId id) {
|
const auto callback = [=](ChannelData *channel, MsgId id) {
|
||||||
consumer.put_done();
|
consumer.put_done();
|
||||||
};
|
};
|
||||||
session->api().requestMessageData(channel, id.msg, callback);
|
session->api().requestMessageData(channel, id.message.msg, callback);
|
||||||
return rpl::lifetime();
|
return rpl::lifetime();
|
||||||
});
|
});
|
||||||
return std::move(
|
return std::move(
|
||||||
|
@ -80,7 +84,7 @@ namespace {
|
||||||
PinnedBar::PinnedBar(
|
PinnedBar::PinnedBar(
|
||||||
not_null<QWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
rpl::producer<FullMsgId> itemId,
|
rpl::producer<PinnedBarId> itemId,
|
||||||
bool withClose)
|
bool withClose)
|
||||||
: _wrap(parent, object_ptr<Ui::RpWidget>(parent))
|
: _wrap(parent, object_ptr<Ui::RpWidget>(parent))
|
||||||
, _close(withClose
|
, _close(withClose
|
||||||
|
@ -101,7 +105,7 @@ PinnedBar::PinnedBar(
|
||||||
rpl::duplicate(
|
rpl::duplicate(
|
||||||
itemId
|
itemId
|
||||||
) | rpl::distinct_until_changed(
|
) | rpl::distinct_until_changed(
|
||||||
) | rpl::map([=](FullMsgId id) {
|
) | rpl::map([=](PinnedBarId id) {
|
||||||
return ContentByItemId(session, id);
|
return ContentByItemId(session, id);
|
||||||
}) | rpl::flatten_latest(
|
}) | rpl::flatten_latest(
|
||||||
) | rpl::filter([=](const Ui::MessageBarContent &content) {
|
) | rpl::filter([=](const Ui::MessageBarContent &content) {
|
||||||
|
@ -119,15 +123,18 @@ PinnedBar::PinnedBar(
|
||||||
|
|
||||||
std::move(
|
std::move(
|
||||||
itemId
|
itemId
|
||||||
) | rpl::map([=](FullMsgId id) {
|
) | rpl::map([=](PinnedBarId id) {
|
||||||
return !id;
|
return !id.message;
|
||||||
}) | rpl::start_with_next([=](bool hidden) {
|
}) | rpl::start_with_next_done([=](bool hidden) {
|
||||||
_shouldBeShown = !hidden;
|
_shouldBeShown = !hidden;
|
||||||
if (!_forceHidden) {
|
if (!_forceHidden) {
|
||||||
_wrap.toggle(_shouldBeShown, anim::type::normal);
|
_wrap.toggle(_shouldBeShown, anim::type::normal);
|
||||||
} else if (!_shouldBeShown) {
|
} else if (!_shouldBeShown) {
|
||||||
_bar = nullptr;
|
_bar = nullptr;
|
||||||
}
|
}
|
||||||
|
}, [=] {
|
||||||
|
_forceHidden = true;
|
||||||
|
_wrap.toggle(false, anim::type::normal);
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,25 @@ class PlainShadow;
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
|
|
||||||
|
enum class PinnedIdType;
|
||||||
|
struct PinnedBarId {
|
||||||
|
FullMsgId message;
|
||||||
|
PinnedIdType type = PinnedIdType();
|
||||||
|
|
||||||
|
bool operator<(const PinnedBarId &other) const {
|
||||||
|
return std::tie(message, type) < std::tie(other.message, other.type);
|
||||||
|
}
|
||||||
|
bool operator==(const PinnedBarId &other) const {
|
||||||
|
return std::tie(message, type) == std::tie(other.message, other.type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class PinnedBar final {
|
class PinnedBar final {
|
||||||
public:
|
public:
|
||||||
PinnedBar(
|
PinnedBar(
|
||||||
not_null<QWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
rpl::producer<FullMsgId> itemId,
|
rpl::producer<PinnedBarId> itemId,
|
||||||
bool withClose = false);
|
bool withClose = false);
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
|
|
|
@ -40,15 +40,23 @@ PinnedTracker::~PinnedTracker() {
|
||||||
_history->owner().histories().cancelRequest(_afterRequestId);
|
_history->owner().histories().cancelRequest(_afterRequestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<MsgId> PinnedTracker::shownMessageId() const {
|
rpl::producer<PinnedId> PinnedTracker::shownMessageId() const {
|
||||||
return _current.value();
|
return _current.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PinnedTracker::reset() {
|
||||||
|
_current.reset(currentMessageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
PinnedId PinnedTracker::currentMessageId() const {
|
||||||
|
return _current.current();
|
||||||
|
}
|
||||||
|
|
||||||
void PinnedTracker::refreshData() {
|
void PinnedTracker::refreshData() {
|
||||||
const auto now = _history->peer->currentPinnedMessages();
|
const auto now = _history->peer->currentPinnedMessages();
|
||||||
if (!now) {
|
if (!now) {
|
||||||
_dataLifetime.destroy();
|
_dataLifetime.destroy();
|
||||||
_current = MsgId(0);
|
_current = PinnedId();
|
||||||
} else if (_data.get() != now) {
|
} else if (_data.get() != now) {
|
||||||
_dataLifetime.destroy();
|
_dataLifetime.destroy();
|
||||||
_data = now;
|
_data = now;
|
||||||
|
@ -65,7 +73,7 @@ void PinnedTracker::trackAround(MsgId messageId) {
|
||||||
_dataLifetime.destroy();
|
_dataLifetime.destroy();
|
||||||
_aroundId = messageId;
|
_aroundId = messageId;
|
||||||
if (!_aroundId) {
|
if (!_aroundId) {
|
||||||
_current = MsgId(0);
|
_current = PinnedId();
|
||||||
} else if (const auto now = _data.get()) {
|
} else if (const auto now = _data.get()) {
|
||||||
setupViewer(now);
|
setupViewer(now);
|
||||||
}
|
}
|
||||||
|
@ -90,10 +98,19 @@ void PinnedTracker::setupViewer(not_null<Data::PinnedMessages*> data) {
|
||||||
Data::LoadDirection::After,
|
Data::LoadDirection::After,
|
||||||
empty ? _aroundId : snapshot.ids.back());
|
empty ? _aroundId : snapshot.ids.back());
|
||||||
}
|
}
|
||||||
|
if (snapshot.ids.empty()) {
|
||||||
|
_current = PinnedId();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto type = (!after && (snapshot.skippedAfter == 0))
|
||||||
|
? PinnedIdType::Last
|
||||||
|
: (before < 2 && (snapshot.skippedBefore == 0))
|
||||||
|
? PinnedIdType::First
|
||||||
|
: PinnedIdType::Middle;
|
||||||
if (i != begin(snapshot.ids)) {
|
if (i != begin(snapshot.ids)) {
|
||||||
_current = *(i - 1);
|
_current = PinnedId{ *(i - 1), type };
|
||||||
} else if (snapshot.skippedBefore == 0) {
|
} else if (snapshot.skippedBefore == 0) {
|
||||||
_current = 0;
|
_current = PinnedId{ snapshot.ids.front(), type };
|
||||||
}
|
}
|
||||||
}, _dataLifetime);
|
}, _dataLifetime);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,32 @@ enum class LoadDirection : char;
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
|
|
||||||
|
enum class PinnedIdType {
|
||||||
|
First,
|
||||||
|
Middle,
|
||||||
|
Last,
|
||||||
|
};
|
||||||
|
struct PinnedId {
|
||||||
|
MsgId message = 0;
|
||||||
|
PinnedIdType type = PinnedIdType::Middle;
|
||||||
|
|
||||||
|
bool operator<(const PinnedId &other) const {
|
||||||
|
return std::tie(message, type) < std::tie(other.message, other.type);
|
||||||
|
}
|
||||||
|
bool operator==(const PinnedId &other) const {
|
||||||
|
return std::tie(message, type) == std::tie(other.message, other.type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class PinnedTracker final {
|
class PinnedTracker final {
|
||||||
public:
|
public:
|
||||||
explicit PinnedTracker(not_null<History*> history);
|
explicit PinnedTracker(not_null<History*> history);
|
||||||
~PinnedTracker();
|
~PinnedTracker();
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<MsgId> shownMessageId() const;
|
[[nodiscard]] rpl::producer<PinnedId> shownMessageId() const;
|
||||||
|
[[nodiscard]] PinnedId currentMessageId() const;
|
||||||
void trackAround(MsgId messageId);
|
void trackAround(MsgId messageId);
|
||||||
|
void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refreshData();
|
void refreshData();
|
||||||
|
@ -36,7 +55,7 @@ private:
|
||||||
const not_null<History*> _history;
|
const not_null<History*> _history;
|
||||||
|
|
||||||
base::weak_ptr<Data::PinnedMessages> _data;
|
base::weak_ptr<Data::PinnedMessages> _data;
|
||||||
rpl::variable<MsgId> _current = MsgId();
|
rpl::variable<PinnedId> _current;
|
||||||
rpl::lifetime _dataLifetime;
|
rpl::lifetime _dataLifetime;
|
||||||
|
|
||||||
MsgId _aroundId = 0;
|
MsgId _aroundId = 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue