mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 23:53:58 +02:00
Show comments bar when no unread bar.
This commit is contained in:
parent
cf48152853
commit
9abca29f4c
9 changed files with 121 additions and 63 deletions
|
@ -2104,7 +2104,7 @@ void History::addUnreadBar() {
|
|||
}
|
||||
if (const auto count = chatListUnreadCount()) {
|
||||
_unreadBarView = _firstUnreadView;
|
||||
_unreadBarView->createUnreadBar();
|
||||
_unreadBarView->createUnreadBar(tr::lng_unread_bar_some());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -144,8 +144,8 @@ TextSelection ShiftItemSelection(
|
|||
return ShiftItemSelection(selection, byText.length());
|
||||
}
|
||||
|
||||
void UnreadBar::init() {
|
||||
text = tr::lng_unread_bar_some(tr::now);
|
||||
void UnreadBar::init(const QString &string) {
|
||||
text = string;
|
||||
width = st::semiboldFont->width(text);
|
||||
}
|
||||
|
||||
|
@ -440,12 +440,18 @@ bool Element::computeIsAttachToPrevious(not_null<Element*> previous) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Element::createUnreadBar() {
|
||||
void Element::createUnreadBar(rpl::producer<QString> text) {
|
||||
if (!AddComponents(UnreadBar::Bit())) {
|
||||
return;
|
||||
}
|
||||
const auto bar = Get<UnreadBar>();
|
||||
bar->init();
|
||||
std::move(
|
||||
text
|
||||
) | rpl::start_with_next([=](const QString &text) {
|
||||
if (const auto bar = Get<UnreadBar>()) {
|
||||
bar->init(text);
|
||||
}
|
||||
}, bar->lifetime);
|
||||
if (data()->mainView() == this) {
|
||||
recountAttachToPreviousInBlocks();
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ TextSelection ShiftItemSelection(
|
|||
// Any HistoryView::Element can have this Component for
|
||||
// displaying the unread messages bar above the message.
|
||||
struct UnreadBar : public RuntimeComponent<UnreadBar, Element> {
|
||||
void init();
|
||||
void init(const QString &string);
|
||||
|
||||
static int height();
|
||||
static int marginTop();
|
||||
|
@ -127,6 +127,7 @@ struct UnreadBar : public RuntimeComponent<UnreadBar, Element> {
|
|||
|
||||
QString text;
|
||||
int width = 0;
|
||||
rpl::lifetime lifetime;
|
||||
|
||||
};
|
||||
|
||||
|
@ -206,7 +207,7 @@ public:
|
|||
|
||||
bool computeIsAttachToPrevious(not_null<Element*> previous);
|
||||
|
||||
void createUnreadBar();
|
||||
void createUnreadBar(rpl::producer<QString> text);
|
||||
void destroyUnreadBar();
|
||||
|
||||
int displayedDateHeight() const;
|
||||
|
|
|
@ -394,13 +394,23 @@ void ListWidget::animatedScrollTo(
|
|||
_delegate->listScrollTo(scrollTop);
|
||||
return;
|
||||
}
|
||||
const auto transition = (type == AnimatedScroll::Full)
|
||||
? anim::sineInOut
|
||||
: anim::easeOutCubic;
|
||||
if (delta > 0 && scrollTop == height() - (_visibleBottom - _visibleTop)) {
|
||||
// Animated scroll to bottom.
|
||||
_scrollToAnimation.start(
|
||||
[=] { scrollToAnimationCallback(FullMsgId(), 0); },
|
||||
-delta,
|
||||
0,
|
||||
st::slideDuration,
|
||||
transition);
|
||||
return;
|
||||
}
|
||||
const auto index = findNearestItem(attachPosition);
|
||||
Assert(index >= 0 && index < int(_items.size()));
|
||||
const auto attachTo = _items[index];
|
||||
const auto attachToId = attachTo->data()->fullId();
|
||||
const auto transition = (type == AnimatedScroll::Full)
|
||||
? anim::sineInOut
|
||||
: anim::easeOutCubic;
|
||||
const auto initial = scrollTop - delta;
|
||||
_delegate->listScrollTo(initial);
|
||||
|
||||
|
@ -422,6 +432,14 @@ bool ListWidget::animatedScrolling() const {
|
|||
void ListWidget::scrollToAnimationCallback(
|
||||
FullMsgId attachToId,
|
||||
int relativeTo) {
|
||||
if (!attachToId) {
|
||||
// Animated scroll to bottom.
|
||||
const auto current = int(std::round(_scrollToAnimation.value(0)));
|
||||
_delegate->listScrollTo(height()
|
||||
- (_visibleBottom - _visibleTop)
|
||||
+ current);
|
||||
return;
|
||||
}
|
||||
const auto attachTo = session().data().message(attachToId);
|
||||
const auto attachToView = viewForItem(attachTo);
|
||||
if (!attachToView) {
|
||||
|
@ -483,11 +501,14 @@ void ListWidget::updateHighlightedMessage() {
|
|||
}
|
||||
|
||||
void ListWidget::checkUnreadBarCreation() {
|
||||
if (!_unreadBarElement) {
|
||||
if (const auto index = _delegate->listUnreadBarView(_items)) {
|
||||
_unreadBarElement = _items[*index].get();
|
||||
_unreadBarElement->createUnreadBar();
|
||||
refreshAttachmentsAtIndex(*index);
|
||||
if (!_bar.element) {
|
||||
if (auto data = _delegate->listMessagesBar(_items); data.bar.element) {
|
||||
_bar = std::move(data.bar);
|
||||
_barText = std::move(data.text);
|
||||
_bar.element->createUnreadBar(_barText.value());
|
||||
const auto i = ranges::find(_items, not_null{ _bar.element });
|
||||
Assert(i != end(_items));
|
||||
refreshAttachmentsAtIndex(i - begin(_items));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -507,10 +528,10 @@ void ListWidget::restoreScrollState() {
|
|||
return;
|
||||
}
|
||||
if (!_scrollTopState.item) {
|
||||
if (!_unreadBarElement) {
|
||||
if (!_bar.element || !_bar.focus) {
|
||||
return;
|
||||
}
|
||||
_scrollTopState.item = _unreadBarElement->data()->position();
|
||||
_scrollTopState.item = _bar.element->data()->position();
|
||||
_scrollTopState.shift = st::lineWidth + st::historyUnreadBarMargin;
|
||||
}
|
||||
const auto index = findNearestItem(_scrollTopState.item);
|
||||
|
@ -2605,11 +2626,11 @@ void ListWidget::viewReplaced(not_null<const Element*> was, Element *now) {
|
|||
if (_visibleTopItem == was) _visibleTopItem = now;
|
||||
if (_scrollDateLastItem == was) _scrollDateLastItem = now;
|
||||
if (_overElement == was) _overElement = now;
|
||||
if (_unreadBarElement == was) {
|
||||
const auto bar = _unreadBarElement->Get<UnreadBar>();
|
||||
_unreadBarElement = now;
|
||||
if (_bar.element == was.get()) {
|
||||
const auto bar = _bar.element->Get<UnreadBar>();
|
||||
_bar.element = now;
|
||||
if (now && bar) {
|
||||
_unreadBarElement->createUnreadBar();
|
||||
_bar.element->createUnreadBar(_barText.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,16 @@ struct SelectedItem {
|
|||
bool canDelete = false;
|
||||
bool canForward = false;
|
||||
bool canSendNow = false;
|
||||
};
|
||||
|
||||
struct MessagesBar {
|
||||
Element *element = nullptr;
|
||||
bool focus = false;
|
||||
};
|
||||
|
||||
struct MessagesBarData {
|
||||
MessagesBar bar;
|
||||
rpl::producer<QString> text;
|
||||
};
|
||||
|
||||
using SelectedItems = std::vector<SelectedItem>;
|
||||
|
@ -70,7 +79,7 @@ public:
|
|||
not_null<HistoryItem*> second) = 0;
|
||||
virtual void listSelectionChanged(SelectedItems &&items) = 0;
|
||||
virtual void listVisibleItemsChanged(HistoryItemsList &&items) = 0;
|
||||
virtual std::optional<int> listUnreadBarView(
|
||||
virtual MessagesBarData listMessagesBar(
|
||||
const std::vector<not_null<Element*>> &elements) = 0;
|
||||
virtual void listContentRefreshed() = 0;
|
||||
virtual ClickHandlerPtr listDateLink(not_null<Element*> view) = 0;
|
||||
|
@ -493,7 +502,8 @@ private:
|
|||
ClickHandlerPtr _scrollDateLink;
|
||||
SingleQueuedInvokation _applyUpdatedScrollState;
|
||||
|
||||
Element *_unreadBarElement = nullptr;
|
||||
MessagesBar _bar;
|
||||
rpl::variable<QString> _barText;
|
||||
|
||||
MouseAction _mouseAction = MouseAction::None;
|
||||
TextSelectType _mouseSelectType = TextSelectType::Letters;
|
||||
|
|
|
@ -1212,26 +1212,7 @@ void RepliesWidget::saveState(not_null<RepliesMemento*> memento) {
|
|||
void RepliesWidget::restoreState(not_null<RepliesMemento*> memento) {
|
||||
const auto setReplies = [&](std::shared_ptr<Data::RepliesList> replies) {
|
||||
_replies = std::move(replies);
|
||||
|
||||
rpl::single(
|
||||
tr::lng_contacts_loading()
|
||||
) | rpl::then(rpl::combine(
|
||||
_replies->fullCount(),
|
||||
_areComments.value()
|
||||
) | rpl::map([=](int count, bool areComments) {
|
||||
return count
|
||||
? (areComments
|
||||
? tr::lng_comments_header
|
||||
: tr::lng_replies_header)(
|
||||
lt_count,
|
||||
rpl::single(count) | tr::to_count())
|
||||
: (areComments
|
||||
? tr::lng_comments_header_none
|
||||
: tr::lng_replies_header_none)();
|
||||
})) | rpl::flatten_latest(
|
||||
) | rpl::start_with_next([=](const QString &text) {
|
||||
_topBar->setCustomTitle(text);
|
||||
}, lifetime());
|
||||
_topBar->setCustomTitle(tr::lng_manage_discussion_group(tr::now));
|
||||
};
|
||||
if (auto replies = memento->getReplies()) {
|
||||
setReplies(std::move(replies));
|
||||
|
@ -1447,15 +1428,19 @@ void RepliesWidget::listSelectionChanged(SelectedItems &&items) {
|
|||
_topBar->showSelected(state);
|
||||
}
|
||||
|
||||
void RepliesWidget::readTill(MsgId tillId) {
|
||||
void RepliesWidget::readTill(not_null<HistoryItem*> item) {
|
||||
if (!_commentsRoot) {
|
||||
return;
|
||||
}
|
||||
const auto now = _commentsRoot->commentsReadTill();
|
||||
if (now < tillId) {
|
||||
_commentsRoot->setCommentsReadTill(tillId);
|
||||
const auto was = _commentsRoot->commentsReadTill();
|
||||
const auto now = item->id;
|
||||
const auto fast = item->out();
|
||||
if (was < now) {
|
||||
_commentsRoot->setCommentsReadTill(now);
|
||||
if (!_readRequestTimer.isActive()) {
|
||||
_readRequestTimer.callOnce(kReadRequestTimeout);
|
||||
_readRequestTimer.callOnce(fast ? 0 : kReadRequestTimeout);
|
||||
} else if (fast && _readRequestTimer.remainingTime() > 0) {
|
||||
_readRequestTimer.callOnce(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1466,31 +1451,66 @@ void RepliesWidget::listVisibleItemsChanged(HistoryItemsList &&items) {
|
|||
return IsServerMsgId(item->id);
|
||||
});
|
||||
if (good != end(reversed)) {
|
||||
readTill((*good)->id);
|
||||
readTill(*good);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<int> RepliesWidget::listUnreadBarView(
|
||||
MessagesBarData RepliesWidget::listMessagesBar(
|
||||
const std::vector<not_null<Element*>> &elements) {
|
||||
if (!_commentsRoot) {
|
||||
return std::nullopt;
|
||||
if (!_commentsRoot || elements.empty()) {
|
||||
return MessagesBarData();
|
||||
}
|
||||
const auto rootBar = [&] {
|
||||
const auto fromRoot = (elements.front()->data().get() == _root);
|
||||
if (elements.size() < 2 || !fromRoot) {
|
||||
return MessagesBarData();
|
||||
}
|
||||
auto text = rpl::combine(
|
||||
_replies->fullCount(),
|
||||
_areComments.value()
|
||||
) | rpl::map([=](int count, bool areComments) {
|
||||
return count
|
||||
? (areComments
|
||||
? tr::lng_comments_header
|
||||
: tr::lng_replies_header)(
|
||||
lt_count,
|
||||
rpl::single(count) | tr::to_count())
|
||||
: (areComments
|
||||
? tr::lng_comments_header_none
|
||||
: tr::lng_replies_header_none)();
|
||||
}) | rpl::flatten_latest();
|
||||
|
||||
return MessagesBarData{
|
||||
// Designated initializers here crash MSVC 16.7.3.
|
||||
MessagesBar{
|
||||
.element = elements[1],
|
||||
.focus = false,
|
||||
},
|
||||
std::move(text),
|
||||
};
|
||||
};
|
||||
const auto till = _commentsRoot->commentsReadTill();
|
||||
if (till < 2) {
|
||||
return std::nullopt;
|
||||
return rootBar();
|
||||
}
|
||||
for (auto i = 0, count = int(elements.size()); i != count; ++i) {
|
||||
const auto item = elements[i]->data();
|
||||
if (item->id > till) {
|
||||
if (IsServerMsgId(item->id) && item->id > till) {
|
||||
if (item->out()) {
|
||||
_commentsRoot->setCommentsReadTill(item->id);
|
||||
_readRequestTimer.callOnce(kReadRequestTimeout);
|
||||
readTill(item);
|
||||
} else {
|
||||
return i;
|
||||
return MessagesBarData{
|
||||
// Designated initializers here crash MSVC 16.7.3.
|
||||
MessagesBar{
|
||||
.element = elements[i],
|
||||
.focus = true,
|
||||
},
|
||||
tr::lng_unread_bar_some(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
return rootBar();
|
||||
}
|
||||
|
||||
void RepliesWidget::listContentRefreshed() {
|
||||
|
|
|
@ -116,7 +116,7 @@ public:
|
|||
not_null<HistoryItem*> second) override;
|
||||
void listSelectionChanged(SelectedItems &&items) override;
|
||||
void listVisibleItemsChanged(HistoryItemsList &&items) override;
|
||||
std::optional<int> listUnreadBarView(
|
||||
MessagesBarData listMessagesBar(
|
||||
const std::vector<not_null<Element*>> &elements) override;
|
||||
void listContentRefreshed() override;
|
||||
ClickHandlerPtr listDateLink(not_null<Element*> view) override;
|
||||
|
@ -155,7 +155,7 @@ private:
|
|||
void refreshRootView();
|
||||
void setupDragArea();
|
||||
void sendReadTillRequest();
|
||||
void readTill(MsgId id);
|
||||
void readTill(not_null<HistoryItem*> item);
|
||||
|
||||
void setupScrollDownButton();
|
||||
void scrollDownClicked();
|
||||
|
|
|
@ -1134,9 +1134,9 @@ void ScheduledWidget::listSelectionChanged(SelectedItems &&items) {
|
|||
void ScheduledWidget::listVisibleItemsChanged(HistoryItemsList &&items) {
|
||||
}
|
||||
|
||||
std::optional<int> ScheduledWidget::listUnreadBarView(
|
||||
MessagesBarData ScheduledWidget::listMessagesBar(
|
||||
const std::vector<not_null<Element*>> &elements) {
|
||||
return std::nullopt;
|
||||
return MessagesBarData();
|
||||
}
|
||||
|
||||
void ScheduledWidget::listContentRefreshed() {
|
||||
|
|
|
@ -106,7 +106,7 @@ public:
|
|||
not_null<HistoryItem*> second) override;
|
||||
void listSelectionChanged(SelectedItems &&items) override;
|
||||
void listVisibleItemsChanged(HistoryItemsList &&items) override;
|
||||
std::optional<int> listUnreadBarView(
|
||||
MessagesBarData listMessagesBar(
|
||||
const std::vector<not_null<Element*>> &elements) override;
|
||||
void listContentRefreshed() override;
|
||||
ClickHandlerPtr listDateLink(not_null<Element*> view) override;
|
||||
|
|
Loading…
Add table
Reference in a new issue