Add button to show all pinned messages.

This commit is contained in:
John Preston 2020-10-20 21:31:47 +03:00
parent 6b38b94db4
commit d742fa32de
13 changed files with 99 additions and 224 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -5239,10 +5239,22 @@ void HistoryWidget::checkPinnedBarState() {
messageId.count
};
});
auto barContent = HistoryView::PinnedBarContent(
&session(),
std::move(shown));
_pinnedBar = std::make_unique<Ui::PinnedBar>(
this,
HistoryView::PinnedBarContent(&session(), std::move(shown)),
true);
std::move(barContent));
Info::Profile::SharedMediaCountValue(
_peer,
nullptr,
Storage::SharedMediaType::Pinned
) | rpl::map([=](int count) {
return (count > 1);
}) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](bool many) {
refreshPinnedBarButton(many);
}, _pinnedBar->lifetime());
rpl::single(
rpl::empty_value()
@ -5259,18 +5271,11 @@ void HistoryWidget::checkPinnedBarState() {
});
}, _pinnedBar->lifetime());
_pinnedBar->closeClicks(
) | rpl::start_with_next([=] {
hidePinnedMessage();
}, _pinnedBar->lifetime());
_pinnedBar->barClicks(
) | rpl::start_with_next([=] {
const auto id = _pinnedTracker->currentMessageId();
if (id.message) {
controller()->showSection(
HistoryView::PinnedMemento(_history, id.message));
//Ui::showPeerHistory(_peer, id.message);
Ui::showPeerHistory(_peer, id.message);
}
}, _pinnedBar->lifetime());
@ -5291,6 +5296,26 @@ void HistoryWidget::checkPinnedBarState() {
}
}
void HistoryWidget::refreshPinnedBarButton(bool many) {
const auto close = !many;
auto button = object_ptr<Ui::IconButton>(
this,
close ? st::historyReplyCancel : st::historyPinnedShowAll);
button->clicks(
) | rpl::start_with_next([=] {
if (close) {
hidePinnedMessage();
} else {
const auto id = _pinnedTracker->currentMessageId();
if (id.message) {
controller()->showSection(
HistoryView::PinnedMemento(_history, id.message));
}
}
}, button->lifetime());
_pinnedBar->setRightButton(std::move(button));
}
void HistoryWidget::requestMessageData(MsgId msgId) {
const auto callback = [=](ChannelData *channel, MsgId msgId) {
messageDataReceived(channel, msgId);

View File

@ -481,6 +481,7 @@ private:
void updatePinnedViewer();
void setupPinnedTracker();
void checkPinnedBarState();
void refreshPinnedBarButton(bool many);
void sendInlineResult(
not_null<InlineBots::Result*> result,

View File

@ -56,6 +56,19 @@ namespace {
} // namespace
PinnedMemento::PinnedMemento(
not_null<History*> history,
MsgId highlightId)
: _history(history)
, _highlightId(highlightId) {
_list.setAroundPosition({
.fullId = FullMsgId(
history->channelId(),
highlightId),
.date = TimeId(0),
});
}
object_ptr<Window::SectionWidget> PinnedMemento::createWidget(
QWidget *parent,
not_null<Window::SessionController*> controller,

View File

@ -148,12 +148,9 @@ private:
class PinnedMemento : public Window::SectionMemento {
public:
PinnedMemento(
explicit PinnedMemento(
not_null<History*> history,
MsgId highlightId = 0)
: _history(history)
, _highlightId(highlightId) {
}
MsgId highlightId = 0);
object_ptr<Window::SectionWidget> createWidget(
QWidget *parent,

View File

@ -12,19 +12,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer.h"
#include "data/data_channel.h"
#include "data/data_session.h"
#include "data/data_histories.h"
#include "main/main_session.h"
#include "storage/storage_facade.h"
#include "storage/storage_shared_media.h"
#include "history/history.h"
#include "history/history_item.h"
#include "apiwrap.h"
namespace HistoryView {
namespace {
namespace{
constexpr auto kLoadedLimit = 4;
constexpr auto kPerPage = 40;
} // namespace
@ -37,10 +34,7 @@ PinnedTracker::PinnedTracker(not_null<History*> history) : _history(history) {
}, _lifetime);
}
PinnedTracker::~PinnedTracker() {
_history->owner().histories().cancelRequest(_beforeRequestId);
_history->owner().histories().cancelRequest(_afterRequestId);
}
PinnedTracker::~PinnedTracker() = default;
rpl::producer<PinnedId> PinnedTracker::shownMessageId() const {
return _current.value();
@ -90,16 +84,6 @@ void PinnedTracker::setupViewer(not_null<Data::PinnedMessages*> data) {
const auto empty = snapshot.ids.empty();
const auto before = (i - begin(snapshot.ids));
const auto after = (end(snapshot.ids) - i);
//if (before < kLoadedLimit && !snapshot.skippedBefore) {
// load(
// Data::LoadDirection::Before,
// empty ? _aroundId : snapshot.ids.front());
//}
//if (after < kLoadedLimit && !snapshot.skippedAfter) {
// load(
// Data::LoadDirection::After,
// empty ? _aroundId : snapshot.ids.back());
//}
if (snapshot.ids.empty()) {
_current = PinnedId();
return;
@ -119,156 +103,5 @@ void PinnedTracker::setupViewer(not_null<Data::PinnedMessages*> data) {
}
}, _dataLifetime);
}
//
//void PinnedTracker::load(Data::LoadDirection direction, MsgId id) {
// const auto requestId = (direction == Data::LoadDirection::Before)
// ? &_beforeRequestId
// : &_afterRequestId;
// const auto aroundId = (direction == Data::LoadDirection::Before)
// ? &_beforeId
// : &_afterId;
// if (*requestId) {
// if (*aroundId == id) {
// return;
// }
// _history->owner().histories().cancelRequest(*requestId);
// }
// *aroundId = id;
// const auto send = [=](Fn<void()> finish) {
// const auto offsetId = [&] {
// switch (direction) {
// case Data::LoadDirection::Before: return id;
// case Data::LoadDirection::After: return id + 1;
// }
// Unexpected("Direction in PinnedTracker::load");
// }();
// const auto addOffset = [&] {
// switch (direction) {
// case Data::LoadDirection::Before: return 0;
// case Data::LoadDirection::After: return -kPerPage;
// }
// Unexpected("Direction in PinnedTracker::load");
// }();
// return _history->session().api().request(MTPmessages_Search(
// MTP_flags(0),
// _history->peer->input,
// MTP_string(QString()),
// MTP_inputPeerEmpty(),
// MTPint(), // top_msg_id
// MTP_inputMessagesFilterPinned(),
// MTP_int(0),
// MTP_int(0),
// MTP_int(offsetId),
// MTP_int(addOffset),
// MTP_int(kPerPage),
// MTP_int(0), // max_id
// MTP_int(0), // min_id
// MTP_int(0) // hash
// )).done([=](const MTPmessages_Messages &result) {
// *aroundId = 0;
// *requestId = 0;
// finish();
//
// apply(direction, id, result);
// }).fail([=](const RPCError &error) {
// *aroundId = 0;
// *requestId = 0;
// finish();
// }).send();
// };
// _beforeRequestId = _history->owner().histories().sendRequest(
// _history,
// Data::Histories::RequestType::History,
// send);
//}
//
//void PinnedTracker::apply(
// Data::LoadDirection direction,
// MsgId aroundId,
// const MTPmessages_Messages &result) {
// auto noSkipRange = MsgRange{ aroundId, aroundId };
// auto fullCount = std::optional<int>();
// auto messages = [&] {
// switch (result.type()) {
// case mtpc_messages_messages: {
// auto &d = result.c_messages_messages();
// _history->owner().processUsers(d.vusers());
// _history->owner().processChats(d.vchats());
// fullCount = d.vmessages().v.size();
// return &d.vmessages().v;
// } break;
//
// case mtpc_messages_messagesSlice: {
// auto &d = result.c_messages_messagesSlice();
// _history->owner().processUsers(d.vusers());
// _history->owner().processChats(d.vchats());
// fullCount = d.vcount().v;
// return &d.vmessages().v;
// } break;
//
// case mtpc_messages_channelMessages: {
// auto &d = result.c_messages_channelMessages();
// if (auto channel = _history->peer->asChannel()) {
// channel->ptsReceived(d.vpts().v);
// } else {
// LOG(("API Error: received messages.channelMessages when "
// "no channel was passed! (PinnedTracker::apply)"));
// }
// _history->owner().processUsers(d.vusers());
// _history->owner().processChats(d.vchats());
// fullCount = d.vcount().v;
// return &d.vmessages().v;
// } break;
//
// case mtpc_messages_messagesNotModified: {
// LOG(("API Error: received messages.messagesNotModified! "
// "(PinnedTracker::apply)"));
// return (const QVector<MTPMessage>*)nullptr;
// } break;
// }
// Unexpected("messages.Messages type in PinnedTracker::apply.");
// }();
//
// if (!messages) {
// return;
// }
//
// const auto addType = NewMessageType::Existing;
// auto list = std::vector<MsgId>();
// list.reserve(messages->size());
// for (const auto &message : *messages) {
// const auto item = _history->owner().addNewMessage(
// message,
// MTPDmessage_ClientFlags(),
// addType);
// if (item) {
// const auto itemId = item->id;
// if (item->isPinned()) {
// list.push_back(itemId);
// }
// accumulate_min(noSkipRange.from, itemId);
// accumulate_max(noSkipRange.till, itemId);
// }
// }
// if (aroundId && list.empty()) {
// noSkipRange = [&]() -> MsgRange {
// switch (direction) {
// case Data::LoadDirection::Before: // All old loaded.
// return { 0, noSkipRange.till };
// case Data::LoadDirection::Around: // All loaded.
// return { 0, ServerMaxMsgId };
// case Data::LoadDirection::After: // All new loaded.
// return { noSkipRange.from, ServerMaxMsgId };
// }
// Unexpected("Direction in PinnedTracker::apply.");
// }();
// }
// _history->session().storage().add(Storage::SharedMediaAddSlice(
// _history->peer->id,
// Storage::SharedMediaType::Pinned,
// std::move(list),
// noSkipRange,
// fullCount));
//}
} // namespace HistoryView

View File

@ -48,11 +48,6 @@ public:
private:
void refreshData();
void setupViewer(not_null<Data::PinnedMessages*> data);
//void load(Data::LoadDirection direction, MsgId id);
//void apply(
// Data::LoadDirection direction,
// MsgId aroundId,
// const MTPmessages_Messages &result);
const not_null<History*> _history;
@ -61,10 +56,6 @@ private:
rpl::lifetime _dataLifetime;
MsgId _aroundId = 0;
MsgId _beforeId = 0;
MsgId _afterId = 0;
MsgId _beforeRequestId = 0;
MsgId _afterRequestId = 0;
rpl::lifetime _lifetime;

View File

@ -111,9 +111,10 @@ RepliesMemento::RepliesMemento(
: RepliesMemento(commentsItem->history(), commentsItem->id, commentId) {
if (commentId) {
_list.setAroundPosition({
.fullId = FullMsgId(commentsItem->history()->channelId(), commentId),
.fullId = FullMsgId(
commentsItem->history()->channelId(),
commentId),
.date = TimeId(0),
});
} else if (commentsItem->computeRepliesInboxReadTillFull() == MsgId(1)) {
_list.setAroundPosition(Data::MinMessagePosition);

View File

@ -361,6 +361,10 @@ historyReplyCancel: IconButton {
color: windowBgOver;
}
}
historyPinnedShowAll: IconButton(historyReplyCancel) {
icon: icon {{ "pinned_show_all", historyReplyCancelFg }};
iconOver: icon {{ "pinned_show_all", historyReplyCancelFgOver }};
}
msgBotKbDuration: 200;
msgBotKbFont: semiboldFont;

View File

@ -19,14 +19,8 @@ namespace Ui {
PinnedBar::PinnedBar(
not_null<QWidget*> parent,
rpl::producer<MessageBarContent> content,
bool withClose)
rpl::producer<MessageBarContent> content)
: _wrap(parent, object_ptr<RpWidget>(parent))
, _close(withClose
? std::make_unique<IconButton>(
_wrap.entity(),
st::historyReplyCancel)
: nullptr)
, _shadow(std::make_unique<PlainShadow>(_wrap.parentWidget())) {
_wrap.hide(anim::type::instant);
_shadow->hide();
@ -73,7 +67,33 @@ PinnedBar::PinnedBar(
}, lifetime());
}
PinnedBar::~PinnedBar() = default;
PinnedBar::~PinnedBar() {
_rightButton.destroy();
}
void PinnedBar::setRightButton(object_ptr<Ui::RpWidget> button) {
_rightButton.destroy();
_rightButton = std::move(button);
if (_rightButton) {
_rightButton->setParent(_wrap.entity());
_rightButton->show();
}
if (_bar) {
updateControlsGeometry(_wrap.geometry());
}
}
void PinnedBar::updateControlsGeometry(QRect wrapGeometry) {
_bar->widget()->resizeToWidth(
wrapGeometry.width() - (_rightButton ? _rightButton->width() : 0));
const auto hidden = _wrap.isHidden() || !wrapGeometry.height();
if (_shadow->isHidden() != hidden) {
_shadow->setVisible(!hidden);
}
if (_rightButton) {
_rightButton->moveToRight(0, 0);
}
}
void PinnedBar::setShadowGeometryPostprocess(Fn<QRect(QRect)> postprocess) {
_shadowGeometryPostprocess = std::move(postprocess);
@ -97,8 +117,8 @@ void PinnedBar::createControls() {
_bar = std::make_unique<MessageBar>(
_wrap.entity(),
st::defaultMessageBar);
if (_close) {
_close->raise();
if (_rightButton) {
_rightButton->raise();
}
// Clicks.
@ -126,15 +146,7 @@ void PinnedBar::createControls() {
_wrap.geometryValue(
) | rpl::start_with_next([=](QRect rect) {
updateShadowGeometry(rect);
_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);
}
updateControlsGeometry(rect);
}, _bar->widget()->lifetime());
_wrap.shownValue(
@ -198,12 +210,6 @@ 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(); }));
}
rpl::producer<> PinnedBar::barClicks() const {
return _barClicks.events();
}

View File

@ -6,7 +6,9 @@ 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 "base/object_ptr.h"
namespace Ui {
@ -14,13 +16,13 @@ struct MessageBarContent;
class MessageBar;
class IconButton;
class PlainShadow;
class RpWidget;
class PinnedBar final {
public:
PinnedBar(
not_null<QWidget*> parent,
rpl::producer<Ui::MessageBarContent> content,
bool withClose = false);
rpl::producer<Ui::MessageBarContent> content);
~PinnedBar();
void show();
@ -30,11 +32,12 @@ public:
void setShadowGeometryPostprocess(Fn<QRect(QRect)> postprocess);
void setRightButton(object_ptr<Ui::RpWidget> button);
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::producer<> barClicks() const;
[[nodiscard]] rpl::lifetime &lifetime() {
@ -44,10 +47,11 @@ public:
private:
void createControls();
void updateShadowGeometry(QRect wrapGeometry);
void updateControlsGeometry(QRect wrapGeometry);
Ui::SlideWrap<> _wrap;
std::unique_ptr<Ui::MessageBar> _bar;
std::unique_ptr<Ui::IconButton> _close;
object_ptr<Ui::RpWidget> _rightButton = { nullptr };
std::unique_ptr<Ui::PlainShadow> _shadow;
rpl::event_stream<> _barClicks;
Fn<QRect(QRect)> _shadowGeometryPostprocess;