Skip to content

Commit

Permalink
Add jump-to-end button to chat preview.
Browse files Browse the repository at this point in the history
  • Loading branch information
john-preston committed Sep 5, 2024
1 parent 40cf962 commit 6fce718
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 22 deletions.
3 changes: 2 additions & 1 deletion Telegram/SourceFiles/data/data_history_messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ rpl::producer<MessagesSlice> HistoryMessagesViewer(
};
const auto messageId = (aroundId.fullId.msg == ShowAtUnreadMsgId)
? computeUnreadAroundId()
: (aroundId.fullId.msg == ShowAtTheEndMsgId)
: ((aroundId.fullId.msg == ShowAtTheEndMsgId)
|| (aroundId == MaxMessagePosition))
? (ServerMaxMsgId - 1)
: (aroundId.fullId.peer == history->peer->id)
? aroundId.fullId.msg
Expand Down
84 changes: 77 additions & 7 deletions Telegram/SourceFiles/history/view/history_view_chat_preview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ For license and copyright information please follow this link:
#include "data/data_session.h"
#include "data/data_thread.h"
#include "history/view/reactions/history_view_reactions_button.h"
#include "history/view/history_view_corner_buttons.h"
#include "history/view/history_view_list_widget.h"
#include "history/history.h"
#include "history/history_item.h"
Expand Down Expand Up @@ -52,7 +53,8 @@ namespace {

class Item final
: public Ui::Menu::ItemBase
, private HistoryView::ListDelegate {
, private ListDelegate
, private CornerButtonsDelegate {
public:
Item(not_null<Ui::RpWidget*> parent, not_null<Data::Thread*> thread);

Expand All @@ -73,6 +75,7 @@ class Item final
void setupHistory();
void updateInnerVisibleArea();

// ListDelegate delegate.
Context listContext() override;
bool listScrollTo(int top, bool syntetic = true) override;
void listCancelRequest() override;
Expand Down Expand Up @@ -164,6 +167,16 @@ class Item final
std::unique_ptr<QMimeData> data,
Fn<void()> finished) override;

// CornerButtonsDelegate delegate.
void cornerButtonsShowAtPosition(
Data::MessagePosition position) override;
Data::Thread *cornerButtonsThread() override;
FullMsgId cornerButtonsCurrentId() override;
bool cornerButtonsIgnoreVisibility() override;
std::optional<bool> cornerButtonsDownShown() override;
bool cornerButtonsUnreadMayBeShown() override;
bool cornerButtonsHas(CornerButtonType type) override;

const not_null<QAction*> _dummyAction;
const not_null<Main::Session*> _session;
const not_null<Data::Thread*> _thread;
Expand All @@ -176,7 +189,8 @@ class Item final
const std::unique_ptr<Ui::ElasticScroll> _scroll;
const std::unique_ptr<Ui::FlatButton> _markRead;

QPointer<HistoryView::ListWidget> _inner;
QPointer<ListWidget> _inner;
std::unique_ptr<CornerButtons> _cornerButtons;
rpl::event_stream<ChatPreviewAction> _actions;

QImage _bg;
Expand Down Expand Up @@ -446,11 +460,16 @@ void Item::setupHistory() {
this,
_session,
static_cast<ListDelegate*>(this)));
_cornerButtons = std::make_unique<CornerButtons>(
_scroll.get(),
_chatStyle.get(),
static_cast<CornerButtonsDelegate*>(this));

_markRead->shownValue() | rpl::start_with_next([=](bool shown) {
const auto top = _top->height();
const auto bottom = shown ? _markRead->height() : 0;
_scroll->setGeometry(rect().marginsRemoved({ 0, top, 0, bottom }));
_cornerButtons->updatePositions();
}, _markRead->lifetime());

_scroll->scrolls(
Expand Down Expand Up @@ -495,6 +514,7 @@ void Item::paintEvent(QPaintEvent *e) {
void Item::updateInnerVisibleArea() {
const auto scrollTop = _scroll->scrollTop();
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
_cornerButtons->updateJumpDownVisibility();
}

Context Item::listContext() {
Expand Down Expand Up @@ -592,18 +612,28 @@ MessagesBarData Item::listMessagesBar(
return {};
}

auto skipped = false;
const auto hidden = _replies && (repliesTill < 2);
for (auto i = 0, count = int(elements.size()); i != count; ++i) {
const auto item = elements[i]->data();
if (!item->isRegular()
|| item->out()
|| (_replies && !item->replyToId())) {
if (!item->isRegular() || (_replies && !item->replyToId())) {
continue;
}
const auto inHistory = (item->history() == _history);
if ((_replies && item->id > repliesTill)
const auto unread = (_replies && item->id > repliesTill)
|| (migratedTill && (inHistory || item->id > migratedTill))
|| (historyTill && inHistory && item->id > historyTill)) {
|| (historyTill && inHistory && item->id > historyTill);
if (!unread) {
skipped = true;
}
if (item->out()) {
continue;
}
if (unread) {
if (!skipped) {
// Don't show jumping unread bar if scrolling up from bottom.
return {};
}
return {
.bar = {
.element = elements[i],
Expand Down Expand Up @@ -800,6 +830,46 @@ void Item::listLaunchDrag(
Fn<void()> finished) {
}

void Item::cornerButtonsShowAtPosition(Data::MessagePosition position) {
if (position == Data::UnreadMessagePosition) {
position = Data::MaxMessagePosition;
}
_inner->showAtPosition(
position,
{},
_cornerButtons->doneJumpFrom(position.fullId, {}, true));
}

Data::Thread *Item::cornerButtonsThread() {
return _thread;
}

FullMsgId Item::cornerButtonsCurrentId() {
return {};
}

bool Item::cornerButtonsIgnoreVisibility() {
return false;
}

std::optional<bool> Item::cornerButtonsDownShown() {
const auto top = _scroll->scrollTop() + st::historyToDownShownAfter;
if (top < _scroll->scrollTopMax()) {
return true;
} else if (_inner->loadedAtBottomKnown()) {
return !_inner->loadedAtBottom();
}
return std::nullopt;
}

bool Item::cornerButtonsUnreadMayBeShown() {
return _inner->loadedAtBottomKnown();
}

bool Item::cornerButtonsHas(CornerButtonType type) {
return (type == CornerButtonType::Down);
}

} // namespace

ChatPreview MakeChatPreview(
Expand Down
49 changes: 36 additions & 13 deletions Telegram/SourceFiles/history/view/history_view_corner_buttons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ For license and copyright information please follow this link:
*/
#include "history/view/history_view_corner_buttons.h"

#include "ui/widgets/scroll_area.h"
#include "ui/chat/chat_style.h"
#include "ui/controls/jump_down_button.h"
#include "ui/widgets/elastic_scroll.h"
#include "ui/widgets/scroll_area.h"
#include "base/qt/qt_key_modifiers.h"
#include "history/history.h"
#include "history/history_item.h"
Expand All @@ -33,17 +34,41 @@ CornerButtons::CornerButtons(
not_null<Ui::ScrollArea*> parent,
not_null<const Ui::ChatStyle*> st,
not_null<CornerButtonsDelegate*> delegate)
: _scroll(parent)
: CornerButtons(
parent,
[=](QEvent *e) { return parent->viewportEvent(e); },
st,
delegate) {
}

CornerButtons::CornerButtons(
not_null<Ui::ElasticScroll*> parent,
not_null<const Ui::ChatStyle*> st,
not_null<CornerButtonsDelegate*> delegate)
: CornerButtons(
parent,
[=](QEvent *e) { return parent->viewportEvent(e); },
st,
delegate) {
}

CornerButtons::CornerButtons(
not_null<QWidget*> parent,
Fn<bool(QEvent*)> scrollViewportEvent,
not_null<const Ui::ChatStyle*> st,
not_null<CornerButtonsDelegate*> delegate)
: _parent(parent)
, _scrollViewportEvent(std::move(scrollViewportEvent))
, _delegate(delegate)
, _down(
parent,
st->value(parent->lifetime(), st::historyToDown))
st->value(_stLifetime, st::historyToDown))
, _mentions(
parent,
st->value(parent->lifetime(), st::historyUnreadMentions))
st->value(_stLifetime, st::historyUnreadMentions))
, _reactions(
parent,
st->value(parent->lifetime(), st::historyUnreadReactions)) {
st->value(_stLifetime, st::historyUnreadReactions)) {
_down.widget->addClickHandler([=] { downClick(); });
_mentions.widget->addClickHandler([=] { mentionsClick(); });
_reactions.widget->addClickHandler([=] { reactionsClick(); });
Expand All @@ -68,7 +93,7 @@ bool CornerButtons::eventFilter(QObject *o, QEvent *e) {
&& (o == _down.widget
|| o == _mentions.widget
|| o == _reactions.widget)) {
return _scroll->viewportEvent(e);
return _scrollViewportEvent(e);
}
return QObject::eventFilter(o, e);
}
Expand Down Expand Up @@ -200,9 +225,7 @@ void CornerButtons::showAt(MsgId id) {
}
}

void CornerButtons::updateVisibility(
CornerButtonType type,
bool shown) {
void CornerButtons::updateVisibility(Type type, bool shown) {
auto &button = buttonByType(type);
if (button.shown != shown) {
button.shown = shown;
Expand Down Expand Up @@ -291,7 +314,7 @@ void CornerButtons::updatePositions() {
historyDownShown);
_down.widget->moveToRight(
st::historyToDownPosition.x(),
_scroll->height() - top);
_parent->height() - top);
}
{
const auto right = anim::interpolate(
Expand All @@ -302,7 +325,7 @@ void CornerButtons::updatePositions() {
0,
_down.widget->height() + skip,
historyDownShown);
const auto top = _scroll->height()
const auto top = _parent->height()
- _mentions.widget->height()
- st::historyToDownPosition.y()
- shift;
Expand All @@ -321,7 +344,7 @@ void CornerButtons::updatePositions() {
0,
_mentions.widget->height() + skip,
unreadMentionsShown);
const auto top = _scroll->height()
const auto top = _parent->height()
- _reactions.widget->height()
- st::historyToDownPosition.y()
- shift;
Expand Down Expand Up @@ -355,7 +378,7 @@ Fn<void(bool found)> CornerButtons::doneJumpFrom(
}
if (!found && !ignoreMessageNotFound) {
Ui::Toast::Show(
_scroll.get(),
_parent.get(),
tr::lng_message_not_found(tr::now));
}
};
Expand Down
16 changes: 15 additions & 1 deletion Telegram/SourceFiles/history/view/history_view_corner_buttons.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct FullMsgId;
namespace Ui {
class ChatStyle;
class ScrollArea;
class ElasticScroll;
class JumpDownButton;
} // namespace Ui

Expand Down Expand Up @@ -61,6 +62,10 @@ class CornerButtons final : private QObject {
not_null<Ui::ScrollArea*> parent,
not_null<const Ui::ChatStyle*> st,
not_null<CornerButtonsDelegate*> delegate);
CornerButtons(
not_null<Ui::ElasticScroll*> parent,
not_null<const Ui::ChatStyle*> st,
not_null<CornerButtonsDelegate*> delegate);

using Type = CornerButtonType;

Expand Down Expand Up @@ -91,6 +96,12 @@ class CornerButtons final : private QObject {
bool ignoreMessageNotFound = false);

private:
CornerButtons(
not_null<QWidget*> parent,
Fn<bool(QEvent*)> scrollViewportEvent,
not_null<const Ui::ChatStyle*> st,
not_null<CornerButtonsDelegate*> delegate);

bool eventFilter(QObject *o, QEvent *e) override;

void computeCurrentReplyReturn();
Expand All @@ -99,9 +110,12 @@ class CornerButtons final : private QObject {
[[nodiscard]] History *lookupHistory() const;
void showAt(MsgId id);

const not_null<Ui::ScrollArea*> _scroll;
const not_null<QWidget*> _parent;
const Fn<bool(QEvent*)> _scrollViewportEvent;
const not_null<CornerButtonsDelegate*> _delegate;

rpl::lifetime _stLifetime;

CornerButton _down;
CornerButton _mentions;
CornerButton _reactions;
Expand Down

0 comments on commit 6fce718

Please sign in to comment.