mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Improve items resize in history and feed.
This commit is contained in:
parent
e6baf8ef5b
commit
b91ebad8be
31 changed files with 311 additions and 333 deletions
|
@ -2584,8 +2584,16 @@ void ApiWrap::requestFeedMessages(
|
|||
return;
|
||||
}
|
||||
|
||||
const auto addOffset = 0;
|
||||
// We request messages with overlapping and skip overlapped in response.
|
||||
const auto limit = kFeedMessagesLimit;
|
||||
const auto addOffset = [&] {
|
||||
switch (slice) {
|
||||
case SliceType::Before: return -2;
|
||||
case SliceType::Around: return -limit / 2;
|
||||
case SliceType::After: return 1 - limit;
|
||||
}
|
||||
Unexpected("Direction in PrepareSearchRequest");
|
||||
}();
|
||||
const auto sourcesHash = int32(0);
|
||||
const auto hash = int32(0);
|
||||
const auto flags = (messageId && messageId.fullId.channel)
|
||||
|
@ -2634,16 +2642,24 @@ void ApiWrap::feedMessagesDone(
|
|||
|
||||
auto ids = std::vector<Data::MessagePosition>();
|
||||
auto noSkipRange = Data::MessagesRange(messageId, messageId);
|
||||
auto accumulateFrom = [](auto &from, const auto &candidate) {
|
||||
const auto accumulateFrom = [](auto &from, const auto &candidate) {
|
||||
if (!from || from > candidate) {
|
||||
from = candidate;
|
||||
}
|
||||
};
|
||||
auto accumulateTill = [](auto &till, const auto &candidate) {
|
||||
const auto accumulateTill = [](auto &till, const auto &candidate) {
|
||||
if (!till || till < candidate) {
|
||||
till = candidate;
|
||||
}
|
||||
};
|
||||
const auto checkPosition = [&](const auto &position) {
|
||||
if (slice == SliceType::Before && !(position < messageId)) {
|
||||
return false;
|
||||
} else if (slice == SliceType::After && !(messageId < position)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
App::feedUsers(data.vusers);
|
||||
App::feedChats(data.vchats);
|
||||
if (!messages.empty()) {
|
||||
|
@ -2651,6 +2667,9 @@ void ApiWrap::feedMessagesDone(
|
|||
for (const auto &msg : messages) {
|
||||
if (const auto item = App::histories().addNewMessage(msg, type)) {
|
||||
const auto position = item->position();
|
||||
if (!checkPosition(position)) {
|
||||
continue;
|
||||
}
|
||||
ids.push_back(position);
|
||||
accumulateFrom(noSkipRange.from, position);
|
||||
accumulateTill(noSkipRange.till, position);
|
||||
|
@ -2658,14 +2677,14 @@ void ApiWrap::feedMessagesDone(
|
|||
}
|
||||
ranges::reverse(ids);
|
||||
}
|
||||
if (data.has_min_position()) {
|
||||
if (data.has_min_position() && !ids.empty()) {
|
||||
accumulateFrom(
|
||||
noSkipRange.from,
|
||||
Data::FeedPositionFromMTP(data.vmin_position));
|
||||
} else {
|
||||
noSkipRange.from = Data::MinMessagePosition;
|
||||
}
|
||||
if (data.has_max_position()) {
|
||||
if (data.has_max_position() && !ids.empty()) {
|
||||
accumulateTill(
|
||||
noSkipRange.till,
|
||||
Data::FeedPositionFromMTP(data.vmax_position));
|
||||
|
|
|
@ -1241,9 +1241,9 @@ namespace {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void historyRegItem(HistoryItem *item) {
|
||||
MsgsData *data = fetchMsgsData(item->channelId());
|
||||
MsgsData::const_iterator i = data->constFind(item->id);
|
||||
void historyRegItem(not_null<HistoryItem*> item) {
|
||||
const auto data = fetchMsgsData(item->channelId());
|
||||
const auto i = data->constFind(item->id);
|
||||
if (i == data->cend()) {
|
||||
data->insert(item->id, item);
|
||||
} else if (i.value() != item) {
|
||||
|
@ -1253,17 +1253,17 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
void historyUnregItem(HistoryItem *item) {
|
||||
auto data = fetchMsgsData(item->channelId(), false);
|
||||
void historyUnregItem(not_null<HistoryItem*> item) {
|
||||
const auto data = fetchMsgsData(item->channelId(), false);
|
||||
if (!data) return;
|
||||
|
||||
auto i = data->find(item->id);
|
||||
const auto i = data->find(item->id);
|
||||
if (i != data->cend()) {
|
||||
if (i.value() == item) {
|
||||
data->erase(i);
|
||||
}
|
||||
}
|
||||
auto j = ::dependentItems.find(item);
|
||||
const auto j = ::dependentItems.find(item);
|
||||
if (j != ::dependentItems.cend()) {
|
||||
DependentItemsSet items;
|
||||
std::swap(items, j.value());
|
||||
|
@ -1281,10 +1281,10 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
void historyUpdateDependent(HistoryItem *item) {
|
||||
DependentItems::iterator j = ::dependentItems.find(item);
|
||||
void historyUpdateDependent(not_null<HistoryItem*> item) {
|
||||
const auto j = ::dependentItems.find(item);
|
||||
if (j != ::dependentItems.cend()) {
|
||||
for_const (HistoryItem *dependent, j.value()) {
|
||||
for_const (const auto dependent, j.value()) {
|
||||
dependent->updateDependencyItem();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,9 +164,9 @@ namespace App {
|
|||
inline HistoryItem *histItemById(const FullMsgId &msgId) {
|
||||
return histItemById(msgId.channel, msgId.msg);
|
||||
}
|
||||
void historyRegItem(HistoryItem *item);
|
||||
void historyUnregItem(HistoryItem *item);
|
||||
void historyUpdateDependent(HistoryItem *item);
|
||||
void historyRegItem(not_null<HistoryItem*> item);
|
||||
void historyUnregItem(not_null<HistoryItem*> item);
|
||||
void historyUpdateDependent(not_null<HistoryItem*> item);
|
||||
void historyClearMsgs();
|
||||
void historyClearItems();
|
||||
void historyRegDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/empty_userpic.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "data/data_session.h"
|
||||
#include "auth_session.h"
|
||||
#include "observer_peer.h"
|
||||
|
||||
|
@ -598,6 +599,7 @@ void DeleteMessagesBox::deleteAndClear() {
|
|||
App::main()->deleteMessages(i.key(), i.value(), forEveryone);
|
||||
}
|
||||
Ui::hideLayer();
|
||||
Auth().data().sendHistoryChangeNotifications();
|
||||
}
|
||||
|
||||
ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, bool isChannel, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants)
|
||||
|
|
|
@ -158,9 +158,17 @@ rpl::producer<not_null<const ViewElement*>> Session::viewLayoutChanged() const {
|
|||
|
||||
void Session::notifyItemIdChange(IdChange event) {
|
||||
_itemIdChanges.fire_copy(event);
|
||||
enumerateItemViews(
|
||||
event.item,
|
||||
[](not_null<ViewElement*> view) { view->refreshDataId(); });
|
||||
|
||||
const auto refreshViewDataId = [](not_null<ViewElement*> view) {
|
||||
view->refreshDataId();
|
||||
};
|
||||
enumerateItemViews(event.item, refreshViewDataId);
|
||||
if (const auto group = Auth().data().groups().find(event.item)) {
|
||||
const auto leader = group->items.back();
|
||||
if (leader != event.item) {
|
||||
enumerateItemViews(leader, refreshViewDataId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rpl::producer<Session::IdChange> Session::itemIdChanged() const {
|
||||
|
@ -198,9 +206,7 @@ rpl::producer<not_null<const HistoryItem*>> Session::itemResizeRequest() const {
|
|||
}
|
||||
|
||||
void Session::requestViewResize(not_null<ViewElement*> view) {
|
||||
if (view == view->data()->mainView()) {
|
||||
view->setPendingResize();
|
||||
}
|
||||
view->setPendingResize();
|
||||
_viewResizeRequest.fire_copy(view);
|
||||
}
|
||||
|
||||
|
@ -252,8 +258,8 @@ rpl::producer<not_null<const History*>> Session::historyCleared() const {
|
|||
}
|
||||
|
||||
void Session::notifyHistoryChangeDelayed(not_null<History*> history) {
|
||||
history->setHasPendingResizedItems();
|
||||
_historiesChanged.insert(history);
|
||||
history->setPendingResize();
|
||||
}
|
||||
|
||||
rpl::producer<not_null<History*>> Session::historyChanged() const {
|
||||
|
|
|
@ -47,9 +47,6 @@ public:
|
|||
return _moreChatsLoaded;
|
||||
}
|
||||
|
||||
base::Observable<void> &pendingHistoryResize() {
|
||||
return _pendingHistoryResize;
|
||||
}
|
||||
struct ItemVisibilityQuery {
|
||||
not_null<HistoryItem*> item;
|
||||
not_null<bool*> isVisible;
|
||||
|
@ -440,7 +437,6 @@ private:
|
|||
base::Variable<bool> _contactsLoaded = { false };
|
||||
base::Variable<bool> _allChatsLoaded = { false };
|
||||
base::Observable<void> _moreChatsLoaded;
|
||||
base::Observable<void> _pendingHistoryResize;
|
||||
base::Observable<ItemVisibilityQuery> _queryItemVisibility;
|
||||
rpl::event_stream<IdChange> _itemIdChanges;
|
||||
rpl::event_stream<not_null<const ViewElement*>> _viewLayoutChanges;
|
||||
|
|
|
@ -340,12 +340,7 @@ void historyMuteUpdated(History *history) {
|
|||
if (MainWidget *m = App::main()) m->notify_historyMuteUpdated(history);
|
||||
}
|
||||
|
||||
void handlePendingHistoryUpdate() {
|
||||
if (!AuthSession::Exists()) {
|
||||
return;
|
||||
}
|
||||
Auth().data().pendingHistoryResize().notify(true);
|
||||
|
||||
//void handlePendingHistoryUpdate() {
|
||||
//for (const auto item : base::take(Global::RefPendingRepaintItems())) {
|
||||
// Auth().data().requestItemRepaint(item);
|
||||
|
||||
|
@ -370,7 +365,7 @@ void handlePendingHistoryUpdate() {
|
|||
// }
|
||||
//}
|
||||
//}
|
||||
}
|
||||
//}
|
||||
|
||||
void unreadCounterUpdated() {
|
||||
Global::RefHandleUnreadCounterUpdate().call();
|
||||
|
@ -515,7 +510,6 @@ namespace Global {
|
|||
namespace internal {
|
||||
|
||||
struct Data {
|
||||
SingleQueuedInvokation HandleHistoryUpdate = { [] { Messenger::Instance().call_handleHistoryUpdate(); } };
|
||||
SingleQueuedInvokation HandleUnreadCounterUpdate = { [] { Messenger::Instance().call_handleUnreadCounterUpdate(); } };
|
||||
SingleQueuedInvokation HandleDelayedPeerUpdates = { [] { Messenger::Instance().call_handleDelayedPeerUpdates(); } };
|
||||
SingleQueuedInvokation HandleObservables = { [] { Messenger::Instance().call_handleObservables(); } };
|
||||
|
@ -636,7 +630,6 @@ void finish() {
|
|||
GlobalData = nullptr;
|
||||
}
|
||||
|
||||
DefineRefVar(Global, SingleQueuedInvokation, HandleHistoryUpdate);
|
||||
DefineRefVar(Global, SingleQueuedInvokation, HandleUnreadCounterUpdate);
|
||||
DefineRefVar(Global, SingleQueuedInvokation, HandleDelayedPeerUpdates);
|
||||
DefineRefVar(Global, SingleQueuedInvokation, HandleObservables);
|
||||
|
|
|
@ -224,12 +224,8 @@ bool switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot =
|
|||
void migrateUpdated(PeerData *peer);
|
||||
|
||||
void historyMuteUpdated(History *history);
|
||||
|
||||
// handle pending resize() / paint() on history items
|
||||
void handlePendingHistoryUpdate();
|
||||
void unreadCounterUpdated();
|
||||
|
||||
|
||||
enum class ScreenCorner {
|
||||
TopLeft = 0,
|
||||
TopRight = 1,
|
||||
|
@ -298,7 +294,6 @@ bool started();
|
|||
void start();
|
||||
void finish();
|
||||
|
||||
DeclareRefVar(SingleQueuedInvokation, HandleHistoryUpdate);
|
||||
DeclareRefVar(SingleQueuedInvokation, HandleUnreadCounterUpdate);
|
||||
DeclareRefVar(SingleQueuedInvokation, HandleDelayedPeerUpdates);
|
||||
DeclareRefVar(SingleQueuedInvokation, HandleObservables);
|
||||
|
|
|
@ -215,9 +215,30 @@ InnerWidget::InnerWidget(
|
|||
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
|
||||
Auth().data().viewRepaintRequest(
|
||||
) | rpl::start_with_next([this](auto view) {
|
||||
repaintItem(view); // #TODO check my view
|
||||
if (view->delegate() == this) {
|
||||
repaintItem(view);
|
||||
}
|
||||
}, lifetime());
|
||||
Auth().data().viewResizeRequest(
|
||||
) | rpl::start_with_next([this](auto view) {
|
||||
if (view->delegate() == this) {
|
||||
updateSize();
|
||||
}
|
||||
}, lifetime());
|
||||
Auth().data().itemViewRefreshRequest(
|
||||
) | rpl::start_with_next([this](auto item) {
|
||||
if (const auto view = viewForItem(item)) {
|
||||
refreshItem(view);
|
||||
}
|
||||
}, lifetime());
|
||||
Auth().data().itemPlayInlineRequest(
|
||||
) | rpl::start_with_next([this](auto item) {
|
||||
if (const auto view = viewForItem(item)) {
|
||||
if (const auto media = view->media()) {
|
||||
media->playInline(true);
|
||||
}
|
||||
}
|
||||
}, lifetime());
|
||||
subscribe(Auth().data().pendingHistoryResize(), [this] { handlePendingHistoryResize(); });
|
||||
subscribe(Auth().data().queryItemVisibility(), [this](const Data::Session::ItemVisibilityQuery &query) {
|
||||
if (_history != query.item->history() || !query.item->isLogEntry() || !isVisible()) {
|
||||
return;
|
||||
|
@ -439,18 +460,18 @@ QPoint InnerWidget::tooltipPos() const {
|
|||
return _mousePosition;
|
||||
}
|
||||
|
||||
HistoryView::Context InnerWidget::elementContext() {
|
||||
return HistoryView::Context::AdminLog;
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Element> InnerWidget::elementCreate(
|
||||
not_null<HistoryMessage*> message) {
|
||||
return std::make_unique<HistoryView::Message>(
|
||||
message,
|
||||
HistoryView::Context::AdminLog);
|
||||
return std::make_unique<HistoryView::Message>(this, message);
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Element> InnerWidget::elementCreate(
|
||||
not_null<HistoryService*> message) {
|
||||
return std::make_unique<HistoryView::Service>(
|
||||
message,
|
||||
HistoryView::Context::AdminLog);
|
||||
return std::make_unique<HistoryView::Service>(this, message);
|
||||
}
|
||||
|
||||
void InnerWidget::saveState(not_null<SectionMemento*> memento) {
|
||||
|
@ -599,7 +620,9 @@ void InnerWidget::updateMinMaxIds() {
|
|||
|
||||
void InnerWidget::itemsAdded(Direction direction, int addedCount) {
|
||||
Expects(addedCount >= 0);
|
||||
auto checkFrom = (direction == Direction::Up) ? (_items.size() - addedCount) : 1; // Should be ": 0", but zero is skipped anyway.
|
||||
auto checkFrom = (direction == Direction::Up)
|
||||
? (_items.size() - addedCount)
|
||||
: 1; // Should be ": 0", but zero is skipped anyway.
|
||||
auto checkTo = (direction == Direction::Up) ? (_items.size() + 1) : (addedCount + 1);
|
||||
for (auto i = checkFrom; i != checkTo; ++i) {
|
||||
if (i > 0) {
|
||||
|
@ -628,11 +651,17 @@ void InnerWidget::updateSize() {
|
|||
int InnerWidget::resizeGetHeight(int newWidth) {
|
||||
update();
|
||||
|
||||
const auto resizeAllItems = (_itemsWidth != newWidth);
|
||||
auto newHeight = 0;
|
||||
for (auto &item : base::reversed(_items)) {
|
||||
item->setY(newHeight);
|
||||
newHeight += item->resizeGetHeight(newWidth);
|
||||
if (item->pendingResize() || resizeAllItems) {
|
||||
newHeight += item->resizeGetHeight(newWidth);
|
||||
} else {
|
||||
newHeight += item->height();
|
||||
}
|
||||
}
|
||||
_itemsWidth = newWidth;
|
||||
_itemsHeight = newHeight;
|
||||
_itemsTop = (_minHeight > _itemsHeight + st::historyPaddingBottom) ? (_minHeight - _itemsHeight - st::historyPaddingBottom) : 0;
|
||||
return _itemsTop + _itemsHeight + st::historyPaddingBottom;
|
||||
|
@ -1575,6 +1604,10 @@ void InnerWidget::repaintItem(const Element *view) {
|
|||
update(0, itemTop(view), width(), view->height());
|
||||
}
|
||||
|
||||
void InnerWidget::refreshItem(not_null<const Element*> view) {
|
||||
// No need to refresh views in admin log.
|
||||
}
|
||||
|
||||
QPoint InnerWidget::mapPointToItem(QPoint point, const Element *view) const {
|
||||
if (!view) {
|
||||
return QPoint();
|
||||
|
@ -1582,13 +1615,6 @@ QPoint InnerWidget::mapPointToItem(QPoint point, const Element *view) const {
|
|||
return point - QPoint(0, itemTop(view));
|
||||
}
|
||||
|
||||
void InnerWidget::handlePendingHistoryResize() {
|
||||
if (_history->hasPendingResizedItems()) {
|
||||
_history->resizeGetHeight(width());
|
||||
updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
InnerWidget::~InnerWidget() = default;
|
||||
|
||||
} // namespace AdminLog
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
QPoint tooltipPos() const override;
|
||||
|
||||
// HistoryView::ElementDelegate interface.
|
||||
HistoryView::Context elementContext() override;
|
||||
std::unique_ptr<HistoryView::Element> elementCreate(
|
||||
not_null<HistoryMessage*> message) override;
|
||||
std::unique_ptr<HistoryView::Element> elementCreate(
|
||||
|
@ -119,8 +120,8 @@ private:
|
|||
void performDrag();
|
||||
int itemTop(not_null<const Element*> view) const;
|
||||
void repaintItem(const Element *view);
|
||||
void refreshItem(not_null<const Element*> view);
|
||||
QPoint mapPointToItem(QPoint point, const Element *view) const;
|
||||
void handlePendingHistoryResize();
|
||||
|
||||
void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false);
|
||||
void savePhotoToFile(PhotoData *photo);
|
||||
|
@ -191,6 +192,7 @@ private:
|
|||
std::map<uint64, not_null<Element*>> _itemsByIds;
|
||||
std::map<not_null<HistoryItem*>, not_null<Element*>, std::less<>> _itemsByData;
|
||||
int _itemsTop = 0;
|
||||
int _itemsWidth = 0;
|
||||
int _itemsHeight = 0;
|
||||
|
||||
LocalIdManager _idManager;
|
||||
|
|
|
@ -164,18 +164,18 @@ rpl::producer<Data::MessagesSlice> Widget::listSource(
|
|||
limitAfter);
|
||||
}
|
||||
|
||||
HistoryView::Context Widget::elementContext() {
|
||||
return HistoryView::Context::Feed;
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Element> Widget::elementCreate(
|
||||
not_null<HistoryMessage*> message) {
|
||||
return std::make_unique<HistoryView::Message>(
|
||||
message,
|
||||
HistoryView::Context::Feed);
|
||||
return std::make_unique<HistoryView::Message>(this, message);
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Element> Widget::elementCreate(
|
||||
not_null<HistoryService*> message) {
|
||||
return std::make_unique<HistoryView::Service>(
|
||||
message,
|
||||
HistoryView::Context::Feed);
|
||||
return std::make_unique<HistoryView::Service>(this, message);
|
||||
}
|
||||
|
||||
std::unique_ptr<Window::SectionMemento> Widget::createMemento() {
|
||||
|
|
|
@ -67,6 +67,8 @@ public:
|
|||
int limitBefore,
|
||||
int limitAfter) override;
|
||||
|
||||
// HistoryView::ElementDelegate interface.
|
||||
HistoryView::Context elementContext() override;
|
||||
std::unique_ptr<HistoryView::Element> elementCreate(
|
||||
not_null<HistoryMessage*> message) override;
|
||||
std::unique_ptr<HistoryView::Element> elementCreate(
|
||||
|
|
|
@ -90,7 +90,6 @@ bool History::canHaveFromPhotos() const {
|
|||
|
||||
void History::setHasPendingResizedItems() {
|
||||
_flags |= Flag::f_has_pending_resized_items;
|
||||
Global::RefHandleHistoryUpdate().call();
|
||||
}
|
||||
|
||||
void History::setLocalDraft(std::unique_ptr<Data::Draft> &&draft) {
|
||||
|
@ -2021,7 +2020,7 @@ not_null<HistoryItem*> History::addNewInTheMiddle(
|
|||
} else if (blockIndex + 1 < blocks.size() && !blocks[blockIndex + 1]->messages.empty()) {
|
||||
blocks[blockIndex + 1]->messages.front()->previousInBlocksChanged();
|
||||
} else {
|
||||
(*it)->nextInBlocksChanged();
|
||||
(*it)->nextInBlocksRemoved();
|
||||
}
|
||||
|
||||
return item;
|
||||
|
@ -2080,7 +2079,7 @@ HistoryBlock *History::finishBuildingFrontBlock() {
|
|||
// the old first item of a first block was changed
|
||||
first->previousInBlocksChanged();
|
||||
} else {
|
||||
block->messages.back()->nextInBlocksChanged();
|
||||
block->messages.back()->nextInBlocksRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2229,12 +2228,12 @@ MsgId History::msgIdForRead() const {
|
|||
}
|
||||
|
||||
int History::resizeGetHeight(int newWidth) {
|
||||
bool resizeAllItems = (_flags & Flag::f_pending_resize) || (width != newWidth);
|
||||
const auto resizeAllItems = (width != newWidth);
|
||||
|
||||
if (!resizeAllItems && !hasPendingResizedItems()) {
|
||||
return height;
|
||||
}
|
||||
_flags &= ~(Flag::f_pending_resize | Flag::f_has_pending_resized_items);
|
||||
_flags &= ~(Flag::f_has_pending_resized_items);
|
||||
|
||||
width = newWidth;
|
||||
int y = 0;
|
||||
|
@ -2330,7 +2329,7 @@ void History::clear(bool leaveItems) {
|
|||
}
|
||||
clearLastKeyboard();
|
||||
}
|
||||
setPendingResize();
|
||||
Auth().data().notifyHistoryChangeDelayed(this);
|
||||
|
||||
newLoaded = oldLoaded = false;
|
||||
forgetScrollState();
|
||||
|
@ -2436,7 +2435,7 @@ void History::removeBlock(not_null<HistoryBlock*> block) {
|
|||
}
|
||||
blocks[index]->messages.front()->previousInBlocksChanged();
|
||||
} else if (!blocks.empty() && !blocks.back()->messages.empty()) {
|
||||
blocks.back()->messages.back()->nextInBlocksChanged();
|
||||
blocks.back()->messages.back()->nextInBlocksRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2505,7 +2504,7 @@ void HistoryBlock::remove(not_null<Element*> view) {
|
|||
} else if (blockIndex + 1 < _history->blocks.size()) {
|
||||
_history->blocks[blockIndex + 1]->messages.front()->previousInBlocksChanged();
|
||||
} else if (!_history->blocks.empty() && !_history->blocks.back()->messages.empty()) {
|
||||
_history->blocks.back()->messages.back()->nextInBlocksChanged();
|
||||
_history->blocks.back()->messages.back()->nextInBlocksRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2528,7 +2527,7 @@ void HistoryBlock::refreshView(not_null<Element*> view) {
|
|||
} else if (blockIndex + 1 < _history->blocks.size()) {
|
||||
_history->blocks[blockIndex + 1]->messages.front()->previousInBlocksChanged();
|
||||
} else if (!_history->blocks.empty() && !_history->blocks.back()->messages.empty()) {
|
||||
_history->blocks.back()->messages.back()->nextInBlocksChanged();
|
||||
_history->blocks.back()->messages.back()->nextInBlocksRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -241,10 +241,6 @@ public:
|
|||
return _flags & Flag::f_has_pending_resized_items;
|
||||
}
|
||||
void setHasPendingResizedItems();
|
||||
void setPendingResize() {
|
||||
_flags |= Flag::f_pending_resize;
|
||||
setHasPendingResizedItems();
|
||||
}
|
||||
|
||||
void paintDialog(Painter &p, int32 w, bool sel) const;
|
||||
bool mySendActionUpdated(SendAction::Type type, bool doing);
|
||||
|
@ -457,7 +453,6 @@ private:
|
|||
|
||||
enum class Flag {
|
||||
f_has_pending_resized_items = (1 << 0),
|
||||
f_pending_resize = (1 << 1),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) { return true; };
|
||||
|
|
|
@ -2911,20 +2911,20 @@ void HistoryInner::onParentGeometryChanged() {
|
|||
not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() {
|
||||
class Result : public HistoryView::ElementDelegate {
|
||||
public:
|
||||
HistoryView::Context elementContext() override {
|
||||
return HistoryView::Context::History;
|
||||
}
|
||||
std::unique_ptr<HistoryView::Element> elementCreate(
|
||||
not_null<HistoryMessage*> message) override {
|
||||
return std::make_unique<HistoryView::Message>(
|
||||
message,
|
||||
HistoryView::Context::History);
|
||||
return std::make_unique<HistoryView::Message>(this, message);
|
||||
}
|
||||
std::unique_ptr<HistoryView::Element> elementCreate(
|
||||
not_null<HistoryService*> message) override {
|
||||
return std::make_unique<HistoryView::Service>(
|
||||
message,
|
||||
HistoryView::Context::History);
|
||||
return std::make_unique<HistoryView::Service>(this, message);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static Result result;
|
||||
return &result;
|
||||
}
|
||||
|
|
|
@ -2672,7 +2672,6 @@ bool HistoryGif::playInline(bool autoplay) {
|
|||
? Mode::Video
|
||||
: Mode::Gif;
|
||||
setClipReader(Media::Clip::MakeReader(_data, _parent->data()->fullId(), [this](Media::Clip::Notification notification) {
|
||||
// #TODO GIFs
|
||||
_parent->clipCallback(notification);
|
||||
}, mode));
|
||||
if (mode == Mode::Video) {
|
||||
|
|
|
@ -647,7 +647,6 @@ HistoryWidget::HistoryWidget(QWidget *parent, not_null<Window::Controller*> cont
|
|||
}
|
||||
}
|
||||
}));
|
||||
subscribe(Auth().data().pendingHistoryResize(), [this] { handlePendingHistoryUpdate(); });
|
||||
subscribe(Auth().data().queryItemVisibility(), [this](const Data::Session::ItemVisibilityQuery &query) {
|
||||
if (_a_show.animating()
|
||||
|| _history != query.item->history()
|
||||
|
@ -4503,7 +4502,7 @@ void HistoryWidget::onReportSpamClear() {
|
|||
|
||||
void HistoryWidget::handleHistoryChange(not_null<const History*> history) {
|
||||
if (_list && (_history == history || _migrated == history)) {
|
||||
updateHistoryGeometry();
|
||||
handlePendingHistoryUpdate();
|
||||
updateBotKeyboard();
|
||||
if (!_scroll->isHidden()) {
|
||||
const auto unblock = isBlocked();
|
||||
|
@ -4566,12 +4565,8 @@ PeerData *HistoryWidget::ui_getPeerForMouseAction() {
|
|||
|
||||
void HistoryWidget::handlePendingHistoryUpdate() {
|
||||
if (hasPendingResizedItems() || _updateHistoryGeometryRequired) {
|
||||
if (_list) {
|
||||
updateHistoryGeometry();
|
||||
_list->update();
|
||||
} else {
|
||||
_updateHistoryGeometryRequired = false;
|
||||
}
|
||||
updateHistoryGeometry();
|
||||
_list->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4742,7 +4737,9 @@ int HistoryWidget::countAutomaticScrollTop() {
|
|||
}
|
||||
|
||||
void HistoryWidget::updateHistoryGeometry(bool initial, bool loadedDown, const ScrollChange &change) {
|
||||
if (!_history || (initial && _historyInited) || (!initial && !_historyInited)) return;
|
||||
if (!_history || (initial && _historyInited) || (!initial && !_historyInited)) {
|
||||
return;
|
||||
}
|
||||
if (_firstLoadRequest || _a_show.animating()) {
|
||||
return; // scrollTopMax etc are not working after recountHistoryGeometry()
|
||||
}
|
||||
|
@ -6176,36 +6173,6 @@ void HistoryWidget::confirmDeleteSelectedItems() {
|
|||
App::main()->deleteLayer(_list->getSelectedItems());
|
||||
}
|
||||
|
||||
void HistoryWidget::deleteSelectedItems(bool forEveryone) {
|
||||
Ui::hideLayer();
|
||||
if (!_list) return;
|
||||
|
||||
const auto items = _list->getSelectedItems();
|
||||
const auto selected = ranges::view::all(
|
||||
items
|
||||
) | ranges::view::transform([](const FullMsgId &fullId) {
|
||||
return App::histItemById(fullId);
|
||||
}) | ranges::view::filter([](HistoryItem *item) {
|
||||
return item != nullptr;
|
||||
}) | ranges::to_vector;
|
||||
|
||||
if (selected.empty()) return;
|
||||
|
||||
QMap<PeerData*, QVector<MTPint>> idsByPeer;
|
||||
for (const auto item : selected) {
|
||||
idsByPeer[item->history()->peer].push_back(MTP_int(item->id));
|
||||
}
|
||||
|
||||
onClearSelected();
|
||||
for (const auto item : selected) {
|
||||
item->destroy();
|
||||
}
|
||||
|
||||
for (auto i = idsByPeer.cbegin(), e = idsByPeer.cend(); i != e; ++i) {
|
||||
App::main()->deleteMessages(i.key(), i.value(), forEveryone);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onListEscapePressed() {
|
||||
if (_nonEmptySelection && _list) {
|
||||
onClearSelected();
|
||||
|
|
|
@ -329,7 +329,6 @@ public:
|
|||
bool isItemVisible(HistoryItem *item);
|
||||
|
||||
void confirmDeleteSelectedItems();
|
||||
void deleteSelectedItems(bool forEveryone);
|
||||
|
||||
// Float player interface.
|
||||
bool wheelEventFromFloatPlayer(QEvent *e) override;
|
||||
|
|
|
@ -55,13 +55,20 @@ TextSelection ShiftItemSelection(
|
|||
return ShiftItemSelection(selection, byText.length());
|
||||
}
|
||||
|
||||
Element::Element(not_null<HistoryItem*> data, Context context)
|
||||
: _data(data)
|
||||
, _context(context) {
|
||||
Element::Element(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryItem*> data)
|
||||
: _delegate(delegate)
|
||||
, _data(data)
|
||||
, _context(delegate->elementContext()) {
|
||||
Auth().data().registerItemView(this);
|
||||
refreshMedia();
|
||||
}
|
||||
|
||||
not_null<ElementDelegate*> Element::delegate() const {
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
not_null<HistoryItem*> Element::data() const {
|
||||
return _data;
|
||||
}
|
||||
|
@ -146,74 +153,6 @@ int Element::infoWidth() const {
|
|||
bool Element::isHiddenByGroup() const {
|
||||
return _flags & Flag::HiddenByGroup;
|
||||
}
|
||||
//
|
||||
//void Element::makeGroupMember(not_null<Element*> leader) {
|
||||
// Expects(leader != this);
|
||||
//
|
||||
// const auto group = Get<Group>();
|
||||
// Assert(group != nullptr);
|
||||
// if (group->leader == this) {
|
||||
// if (auto single = _media ? _media->takeLastFromGroup() : nullptr) {
|
||||
// _media = std::move(single);
|
||||
// }
|
||||
// _flags |= Flag::HiddenByGroup;
|
||||
// Auth().data().requestViewResize(this);
|
||||
//
|
||||
// group->leader = leader;
|
||||
// base::take(group->others);
|
||||
// } else if (group->leader != leader) {
|
||||
// group->leader = leader;
|
||||
// }
|
||||
//
|
||||
// Ensures(isHiddenByGroup());
|
||||
// Ensures(group->others.empty());
|
||||
//}
|
||||
//
|
||||
//void Element::makeGroupLeader(std::vector<not_null<HistoryItem*>> &&others) {
|
||||
// const auto group = Get<Group>();
|
||||
// Assert(group != nullptr);
|
||||
//
|
||||
// const auto leaderChanged = (group->leader != this);
|
||||
// if (leaderChanged) {
|
||||
// group->leader = this;
|
||||
// _flags &= ~Flag::HiddenByGroup;
|
||||
// Auth().data().requestViewResize(this);
|
||||
// }
|
||||
// group->others = std::move(others);
|
||||
// if (!_media || !_media->applyGroup(group->others)) {
|
||||
// resetGroupMedia(group->others);
|
||||
// data()->invalidateChatsListEntry();
|
||||
// }
|
||||
//
|
||||
// Ensures(!isHiddenByGroup());
|
||||
//}
|
||||
//
|
||||
//bool Element::groupIdValidityChanged() {
|
||||
// if (Has<Group>()) {
|
||||
// if (_media && _media->canBeGrouped()) {
|
||||
// return false;
|
||||
// }
|
||||
// RemoveComponents(Group::Bit());
|
||||
// Auth().data().requestViewResize(this);
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
//}
|
||||
//
|
||||
//void Element::validateGroupId() {
|
||||
// // Just ignore the result.
|
||||
// groupIdValidityChanged();
|
||||
//}
|
||||
//
|
||||
//Group *Element::getFullGroup() {
|
||||
// if (const auto group = Get<Group>()) {
|
||||
// if (group->leader == this) {
|
||||
// return group;
|
||||
// }
|
||||
// return group->leader->Get<Group>();
|
||||
// }
|
||||
// return nullptr;
|
||||
//}
|
||||
|
||||
void Element::refreshMedia() {
|
||||
_flags &= ~Flag::HiddenByGroup;
|
||||
|
@ -241,23 +180,12 @@ void Element::refreshMedia() {
|
|||
}
|
||||
}
|
||||
|
||||
//void Element::resetGroupMedia(
|
||||
// const std::vector<not_null<Element*>> &others) {
|
||||
// if (!others.empty()) {
|
||||
// _media = std::make_unique<HistoryGroupedMedia>(this, others);
|
||||
// } else if (_media) {
|
||||
// _media = _media->takeLastFromGroup();
|
||||
// }
|
||||
// Auth().data().requestViewResize(this);
|
||||
//}
|
||||
|
||||
void Element::previousInBlocksChanged() {
|
||||
recountDisplayDateInBlocks();
|
||||
recountAttachToPreviousInBlocks();
|
||||
}
|
||||
|
||||
// Called only if there is no more next item! Not always when it changes!
|
||||
void Element::nextInBlocksChanged() {
|
||||
void Element::nextInBlocksRemoved() {
|
||||
setAttachToNext(false);
|
||||
}
|
||||
|
||||
|
@ -306,16 +234,9 @@ void Element::clipCallback(Media::Clip::Notification notification) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Element::refreshDataId() {
|
||||
if (const auto media = this->media()) {
|
||||
media->refreshParentId(data());
|
||||
// #TODO refresh sent album items
|
||||
//if (const auto group = Get<Group>()) {
|
||||
// if (group->leader != this) {
|
||||
// group->leader->refreshDataId();
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,10 +244,11 @@ bool Element::computeIsAttachToPrevious(not_null<Element*> previous) {
|
|||
const auto item = data();
|
||||
if (!item->Has<HistoryMessageDate>() && !item->Has<HistoryMessageUnreadBar>()) {
|
||||
const auto prev = previous->data();
|
||||
const auto possible = !item->isPost() && !prev->isPost()
|
||||
&& !item->serviceMsg() && !prev->serviceMsg()
|
||||
const auto possible = !item->serviceMsg() && !prev->serviceMsg()
|
||||
&& !item->isEmpty() && !prev->isEmpty()
|
||||
&& (qAbs(prev->date.secsTo(item->date)) < kAttachMessageToPreviousSecondsDelta);
|
||||
&& (qAbs(prev->date.secsTo(item->date)) < kAttachMessageToPreviousSecondsDelta)
|
||||
&& (_context == Context::Feed
|
||||
|| (!item->isPost() && !prev->isPost()));
|
||||
if (possible) {
|
||||
if (item->history()->peer->isSelf()) {
|
||||
return prev->senderOriginal() == item->senderOriginal()
|
||||
|
@ -390,20 +312,20 @@ void Element::setDisplayDate(bool displayDate) {
|
|||
void Element::setAttachToNext(bool attachToNext) {
|
||||
if (attachToNext && !(_flags & Flag::AttachedToNext)) {
|
||||
_flags |= Flag::AttachedToNext;
|
||||
Auth().data().requestViewResize(this);
|
||||
setPendingResize();
|
||||
} else if (!attachToNext && (_flags & Flag::AttachedToNext)) {
|
||||
_flags &= ~Flag::AttachedToNext;
|
||||
Auth().data().requestViewResize(this);
|
||||
setPendingResize();
|
||||
}
|
||||
}
|
||||
|
||||
void Element::setAttachToPrevious(bool attachToPrevious) {
|
||||
if (attachToPrevious && !(_flags & Flag::AttachedToPrevious)) {
|
||||
_flags |= Flag::AttachedToPrevious;
|
||||
Auth().data().requestViewResize(this);
|
||||
setPendingResize();
|
||||
} else if (!attachToPrevious && (_flags & Flag::AttachedToPrevious)) {
|
||||
_flags &= ~Flag::AttachedToPrevious;
|
||||
Auth().data().requestViewResize(this);
|
||||
setPendingResize();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,16 @@ enum InfoDisplayType : char;
|
|||
|
||||
namespace HistoryView {
|
||||
|
||||
enum class Context : char {
|
||||
History,
|
||||
Feed,
|
||||
AdminLog
|
||||
};
|
||||
|
||||
class Element;
|
||||
class ElementDelegate {
|
||||
public:
|
||||
virtual Context elementContext() = 0;
|
||||
virtual std::unique_ptr<Element> elementCreate(
|
||||
not_null<HistoryMessage*> message) = 0;
|
||||
virtual std::unique_ptr<Element> elementCreate(
|
||||
|
@ -46,25 +53,14 @@ TextSelection ShiftItemSelection(
|
|||
TextSelection selection,
|
||||
const Text &byText);
|
||||
|
||||
class Element;
|
||||
//struct Group : public RuntimeComponent<Group, Element> {
|
||||
// MessageGroupId groupId = MessageGroupId::None;
|
||||
// Element *leader = nullptr;
|
||||
// std::vector<not_null<HistoryItem*>> others;
|
||||
//};
|
||||
|
||||
enum class Context : char {
|
||||
History,
|
||||
Feed,
|
||||
AdminLog
|
||||
};
|
||||
|
||||
class Element
|
||||
: public Object
|
||||
, public RuntimeComposer<Element>
|
||||
, public ClickHandlerHost {
|
||||
public:
|
||||
Element(not_null<HistoryItem*> data, Context context);
|
||||
Element(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryItem*> data);
|
||||
|
||||
enum class Flag : uchar {
|
||||
NeedsResize = 0x01,
|
||||
|
@ -75,6 +71,7 @@ public:
|
|||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||
|
||||
not_null<ElementDelegate*> delegate() const;
|
||||
not_null<HistoryItem*> data() const;
|
||||
HistoryMedia *media() const;
|
||||
Context context() const;
|
||||
|
@ -98,17 +95,12 @@ public:
|
|||
virtual int infoWidth() const;
|
||||
|
||||
bool isHiddenByGroup() const;
|
||||
//void makeGroupMember(not_null<Element*> leader);
|
||||
//void makeGroupLeader(std::vector<not_null<HistoryItem*>> &&others);
|
||||
//bool groupIdValidityChanged();
|
||||
//void validateGroupId();
|
||||
//Group *getFullGroup();
|
||||
|
||||
// For blocks context this should be called only from recountAttachToPreviousInBlocks().
|
||||
void setAttachToPrevious(bool attachToNext);
|
||||
|
||||
// For blocks context this should be called only from recountAttachToPreviousInBlocks()
|
||||
// of the next item or when the next item is removed through nextInBlocksChanged() call.
|
||||
// of the next item or when the next item is removed through nextInBlocksRemoved() call.
|
||||
void setAttachToNext(bool attachToNext);
|
||||
|
||||
// For blocks context this should be called only from recountDisplayDate().
|
||||
|
@ -186,7 +178,7 @@ public:
|
|||
Element *previousInBlocks() const;
|
||||
Element *nextInBlocks() const;
|
||||
void previousInBlocksChanged();
|
||||
void nextInBlocksChanged();
|
||||
void nextInBlocksRemoved();
|
||||
|
||||
void clipCallback(Media::Clip::Notification notification);
|
||||
|
||||
|
@ -214,8 +206,8 @@ private:
|
|||
virtual QSize performCountCurrentSize(int newWidth) = 0;
|
||||
|
||||
void refreshMedia();
|
||||
//void resetGroupMedia(const std::vector<not_null<HistoryItem*>> &others);
|
||||
|
||||
const not_null<ElementDelegate*> _delegate;
|
||||
const not_null<HistoryItem*> _data;
|
||||
std::unique_ptr<HistoryMedia> _media;
|
||||
|
||||
|
|
|
@ -223,9 +223,30 @@ ListWidget::ListWidget(
|
|||
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
|
||||
Auth().data().viewRepaintRequest(
|
||||
) | rpl::start_with_next([this](auto view) {
|
||||
repaintItem(view);
|
||||
if (view->delegate() == _delegate) {
|
||||
repaintItem(view);
|
||||
}
|
||||
}, lifetime());
|
||||
Auth().data().viewResizeRequest(
|
||||
) | rpl::start_with_next([this](auto view) {
|
||||
if (view->delegate() == _delegate) {
|
||||
updateSize();
|
||||
}
|
||||
}, lifetime());
|
||||
Auth().data().itemViewRefreshRequest(
|
||||
) | rpl::start_with_next([this](auto item) {
|
||||
if (const auto view = viewForItem(item)) {
|
||||
refreshItem(view);
|
||||
}
|
||||
}, lifetime());
|
||||
Auth().data().itemPlayInlineRequest(
|
||||
) | rpl::start_with_next([this](auto item) {
|
||||
if (const auto view = viewForItem(item)) {
|
||||
if (const auto media = view->media()) {
|
||||
media->playInline(true);
|
||||
}
|
||||
}
|
||||
}, lifetime());
|
||||
subscribe(Auth().data().pendingHistoryResize(), [this] { handlePendingHistoryResize(); });
|
||||
subscribe(Auth().data().queryItemVisibility(), [this](const Data::Session::ItemVisibilityQuery &query) {
|
||||
if (const auto view = viewForItem(query.item)) {
|
||||
const auto top = itemTop(view);
|
||||
|
@ -262,7 +283,7 @@ void ListWidget::refreshRows() {
|
|||
}
|
||||
updateAroundPositionFromRows();
|
||||
|
||||
RpWidget::resizeToWidth(width());
|
||||
updateItemsGeometry();
|
||||
restoreScrollState();
|
||||
mouseActionUpdate(QCursor::pos());
|
||||
}
|
||||
|
@ -505,27 +526,34 @@ void ListWidget::restoreState(not_null<ListMemento*> memento) {
|
|||
refreshViewer();
|
||||
}
|
||||
|
||||
void ListWidget::itemsAdded(Direction direction, int addedCount) {
|
||||
Expects(addedCount >= 0);
|
||||
|
||||
auto checkFrom = (direction == Direction::Up)
|
||||
? (_items.size() - addedCount)
|
||||
: 1; // Should be ": 0", but zero is skipped anyway.
|
||||
auto checkTo = (direction == Direction::Up)
|
||||
? (_items.size() + 1)
|
||||
: (addedCount + 1);
|
||||
for (auto i = checkFrom; i != checkTo; ++i) {
|
||||
if (i > 0) {
|
||||
const auto view = _items[i - 1].get();
|
||||
if (i < _items.size()) {
|
||||
// #TODO feeds show
|
||||
auto previous = _items[i].get();
|
||||
view->setDisplayDate(view->data()->date.date() != previous->data()->date.date());
|
||||
auto attachToPrevious = view->computeIsAttachToPrevious(previous);
|
||||
view->setAttachToPrevious(attachToPrevious);
|
||||
previous->setAttachToNext(attachToPrevious);
|
||||
void ListWidget::updateItemsGeometry() {
|
||||
const auto count = int(_items.size());
|
||||
const auto first = [&] {
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
const auto view = _items[i].get();
|
||||
if (view->isHiddenByGroup()) {
|
||||
view->setDisplayDate(false);
|
||||
} else {
|
||||
view->setDisplayDate(true);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}();
|
||||
if (first < count) {
|
||||
auto view = _items[first].get();
|
||||
for (auto i = first + 1; i != count; ++i) {
|
||||
const auto next = _items[i].get();
|
||||
if (next->isHiddenByGroup()) {
|
||||
next->setDisplayDate(false);
|
||||
} else {
|
||||
const auto viewDate = view->data()->date;
|
||||
const auto nextDate = next->data()->date;
|
||||
next->setDisplayDate(nextDate.date() != viewDate.date());
|
||||
auto attached = next->computeIsAttachToPrevious(view);
|
||||
next->setAttachToPrevious(attached);
|
||||
view->setAttachToNext(attached);
|
||||
view = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -541,11 +569,17 @@ void ListWidget::updateSize() {
|
|||
int ListWidget::resizeGetHeight(int newWidth) {
|
||||
update();
|
||||
|
||||
const auto resizeAllItems = (_itemsWidth != newWidth);
|
||||
auto newHeight = 0;
|
||||
for (auto &view : _items) {
|
||||
view->setY(newHeight);
|
||||
newHeight += view->resizeGetHeight(newWidth);
|
||||
if (view->pendingResize() || resizeAllItems) {
|
||||
newHeight += view->resizeGetHeight(newWidth);
|
||||
} else {
|
||||
newHeight += view->height();
|
||||
}
|
||||
}
|
||||
_itemsWidth = newWidth;
|
||||
_itemsHeight = newHeight;
|
||||
_itemsTop = (_minHeight > _itemsHeight + st::historyPaddingBottom) ? (_minHeight - _itemsHeight - st::historyPaddingBottom) : 0;
|
||||
return _itemsTop + _itemsHeight + st::historyPaddingBottom;
|
||||
|
@ -1386,6 +1420,10 @@ void ListWidget::repaintItem(const Element *view) {
|
|||
update(0, itemTop(view), width(), view->height());
|
||||
}
|
||||
|
||||
void ListWidget::refreshItem(not_null<const Element*> view) {
|
||||
// #TODO
|
||||
}
|
||||
|
||||
QPoint ListWidget::mapPointToItem(
|
||||
QPoint point,
|
||||
const Element *view) const {
|
||||
|
@ -1395,14 +1433,6 @@ QPoint ListWidget::mapPointToItem(
|
|||
return point - QPoint(0, itemTop(view));
|
||||
}
|
||||
|
||||
void ListWidget::handlePendingHistoryResize() {
|
||||
// #TODO resize
|
||||
//if (_history->hasPendingResizedItems()) {
|
||||
// _history->resizeGetHeight(width());
|
||||
// updateSize();
|
||||
//}
|
||||
}
|
||||
|
||||
ListWidget::~ListWidget() = default;
|
||||
|
||||
} // namespace HistoryView
|
||||
|
|
|
@ -155,8 +155,8 @@ private:
|
|||
void performDrag();
|
||||
int itemTop(not_null<const Element*> view) const;
|
||||
void repaintItem(const Element *view);
|
||||
void refreshItem(not_null<const Element*> view);
|
||||
QPoint mapPointToItem(QPoint point, const Element *view) const;
|
||||
void handlePendingHistoryResize();
|
||||
|
||||
void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false);
|
||||
void savePhotoToFile(PhotoData *photo);
|
||||
|
@ -180,7 +180,7 @@ private:
|
|||
|
||||
void checkMoveToOtherViewer();
|
||||
void updateVisibleTopItem();
|
||||
void itemsAdded(Direction direction, int addedCount);
|
||||
void updateItemsGeometry();
|
||||
void updateSize();
|
||||
|
||||
void toggleScrollDateShown();
|
||||
|
@ -226,6 +226,7 @@ private:
|
|||
std::vector<not_null<Element*>> _items;
|
||||
std::map<not_null<HistoryItem*>, std::unique_ptr<Element>, std::less<>> _views;
|
||||
int _itemsTop = 0;
|
||||
int _itemsWidth = 0;
|
||||
int _itemsHeight = 0;
|
||||
|
||||
int _minHeight = 0;
|
||||
|
|
|
@ -192,8 +192,10 @@ LogEntryOriginal &LogEntryOriginal::operator=(LogEntryOriginal &&other) {
|
|||
|
||||
LogEntryOriginal::~LogEntryOriginal() = default;
|
||||
|
||||
Message::Message(not_null<HistoryMessage*> data, Context context)
|
||||
: Element(data, context) {
|
||||
Message::Message(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryMessage*> data)
|
||||
: Element(delegate, data) {
|
||||
initLogEntryOriginal();
|
||||
}
|
||||
|
||||
|
@ -637,6 +639,9 @@ bool Message::displayFromPhoto() const {
|
|||
}
|
||||
|
||||
bool Message::hasFromPhoto() const {
|
||||
if (isHiddenByGroup()) {
|
||||
return false;
|
||||
}
|
||||
switch (context()) {
|
||||
case Context::AdminLog:
|
||||
case Context::Feed:
|
||||
|
@ -1486,13 +1491,6 @@ TextSelection Message::unskipTextSelection(TextSelection selection) const {
|
|||
|
||||
QRect Message::countGeometry() const {
|
||||
const auto item = message();
|
||||
const auto media = this->media();
|
||||
|
||||
auto maxwidth = qMin(st::msgMaxWidth, maxWidth());
|
||||
if (media && media->width() < maxwidth) {
|
||||
maxwidth = qMax(media->width(), qMin(maxwidth, plainMaxWidth()));
|
||||
}
|
||||
|
||||
const auto outbg = hasOutLayout();
|
||||
auto contentLeft = (outbg && !Adaptive::ChatWide())
|
||||
? st::msgMargin.right()
|
||||
|
@ -1503,15 +1501,25 @@ QRect Message::countGeometry() const {
|
|||
// contentLeft += st::msgPhotoSkip - (hmaxwidth - hwidth);
|
||||
}
|
||||
|
||||
auto contentWidth = width() - st::msgMargin.left() - st::msgMargin.right();
|
||||
const auto media = this->media();
|
||||
const auto mediaWidth = media ? media->width() : width();
|
||||
const auto availableWidth = width() - st::msgMargin.left() - st::msgMargin.right();
|
||||
auto contentWidth = availableWidth;
|
||||
if (item->history()->peer->isSelf() && !outbg) {
|
||||
contentWidth -= st::msgPhotoSkip;
|
||||
}
|
||||
if (contentWidth > maxwidth) {
|
||||
if (outbg && !Adaptive::ChatWide()) {
|
||||
contentLeft += contentWidth - maxwidth;
|
||||
accumulate_min(contentWidth, maxWidth());
|
||||
accumulate_min(contentWidth, st::msgMaxWidth);
|
||||
if (mediaWidth < contentWidth) {
|
||||
const auto textualWidth = plainMaxWidth();
|
||||
if (mediaWidth < textualWidth) {
|
||||
accumulate_min(contentWidth, textualWidth);
|
||||
} else {
|
||||
contentWidth = mediaWidth;
|
||||
}
|
||||
contentWidth = maxwidth;
|
||||
}
|
||||
if (contentWidth < availableWidth && outbg && !Adaptive::ChatWide()) {
|
||||
contentLeft += availableWidth - contentWidth;
|
||||
}
|
||||
|
||||
const auto contentTop = marginTop();
|
||||
|
@ -1523,47 +1531,59 @@ QRect Message::countGeometry() const {
|
|||
}
|
||||
|
||||
int Message::resizeContentGetHeight(int newWidth) {
|
||||
const auto item = message();
|
||||
const auto media = this->media();
|
||||
|
||||
if (newWidth < st::msgMinWidth) {
|
||||
if (isHiddenByGroup()) {
|
||||
return 0;
|
||||
} else if (newWidth < st::msgMinWidth) {
|
||||
return height();
|
||||
}
|
||||
|
||||
auto newHeight = minHeight();
|
||||
|
||||
const auto item = message();
|
||||
const auto media = this->media();
|
||||
const auto mediaDisplayed = media ? media->isDisplayed() : false;
|
||||
const auto bubble = drawBubble();
|
||||
|
||||
// This code duplicates countGeometry() but also resizes media.
|
||||
auto contentWidth = newWidth - (st::msgMargin.left() + st::msgMargin.right());
|
||||
if (item->history()->peer->isSelf() && !hasOutLayout()) {
|
||||
contentWidth -= st::msgPhotoSkip;
|
||||
}
|
||||
if (contentWidth < st::msgPadding.left() + st::msgPadding.right() + 1) {
|
||||
contentWidth = st::msgPadding.left() + st::msgPadding.right() + 1;
|
||||
} else if (contentWidth > st::msgMaxWidth) {
|
||||
contentWidth = st::msgMaxWidth;
|
||||
accumulate_min(contentWidth, maxWidth());
|
||||
accumulate_min(contentWidth, st::msgMaxWidth);
|
||||
if (mediaDisplayed) {
|
||||
media->resizeGetHeight(bubble
|
||||
? std::min(contentWidth, maxWidth())
|
||||
: contentWidth);
|
||||
if (media->width() < contentWidth) {
|
||||
const auto textualWidth = plainMaxWidth();
|
||||
if (media->width() < textualWidth) {
|
||||
accumulate_min(contentWidth, textualWidth);
|
||||
} else {
|
||||
contentWidth = media->width();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (drawBubble()) {
|
||||
|
||||
if (bubble) {
|
||||
auto forwarded = item->Get<HistoryMessageForwarded>();
|
||||
auto reply = item->Get<HistoryMessageReply>();
|
||||
auto via = item->Get<HistoryMessageVia>();
|
||||
auto entry = logEntryOriginal();
|
||||
|
||||
auto mediaDisplayed = false;
|
||||
if (media) {
|
||||
mediaDisplayed = media->isDisplayed();
|
||||
}
|
||||
|
||||
// Entry page is always a bubble bottom.
|
||||
auto mediaOnBottom = (mediaDisplayed && media->isBubbleBottom()) || (entry/* && entry->isBubbleBottom()*/);
|
||||
auto mediaOnTop = (mediaDisplayed && media->isBubbleTop()) || (entry && entry->isBubbleTop());
|
||||
|
||||
if (contentWidth >= maxWidth()) {
|
||||
if (contentWidth == maxWidth()) {
|
||||
if (mediaDisplayed) {
|
||||
media->resizeGetHeight(maxWidth());
|
||||
media->resizeGetHeight(contentWidth);
|
||||
if (entry) {
|
||||
newHeight += entry->resizeGetHeight(countGeometry().width());
|
||||
newHeight += entry->resizeGetHeight(contentWidth);
|
||||
}
|
||||
} else if (entry) {
|
||||
// In case of text-only message it is counted in minHeight already.
|
||||
entry->resizeGetHeight(countGeometry().width());
|
||||
entry->resizeGetHeight(contentWidth);
|
||||
}
|
||||
} else {
|
||||
if (hasVisibleText()) {
|
||||
|
@ -1588,7 +1608,7 @@ int Message::resizeContentGetHeight(int newWidth) {
|
|||
if (mediaDisplayed) {
|
||||
newHeight += media->resizeGetHeight(contentWidth);
|
||||
if (entry) {
|
||||
newHeight += entry->resizeGetHeight(countGeometry().width());
|
||||
newHeight += entry->resizeGetHeight(contentWidth);
|
||||
}
|
||||
} else if (entry) {
|
||||
newHeight += entry->resizeGetHeight(contentWidth);
|
||||
|
@ -1596,20 +1616,20 @@ int Message::resizeContentGetHeight(int newWidth) {
|
|||
}
|
||||
|
||||
if (displayFromName()) {
|
||||
fromNameUpdated(countGeometry().width());
|
||||
fromNameUpdated(contentWidth);
|
||||
newHeight += st::msgNameFont->height;
|
||||
} else if (via && !forwarded) {
|
||||
via->resize(countGeometry().width() - st::msgPadding.left() - st::msgPadding.right());
|
||||
via->resize(contentWidth - st::msgPadding.left() - st::msgPadding.right());
|
||||
newHeight += st::msgNameFont->height;
|
||||
}
|
||||
|
||||
if (displayForwardedFrom()) {
|
||||
auto fwdheight = ((forwarded->text.maxWidth() > (countGeometry().width() - st::msgPadding.left() - st::msgPadding.right())) ? 2 : 1) * st::semiboldFont->height;
|
||||
auto fwdheight = ((forwarded->text.maxWidth() > (contentWidth - st::msgPadding.left() - st::msgPadding.right())) ? 2 : 1) * st::semiboldFont->height;
|
||||
newHeight += fwdheight;
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
reply->resize(countGeometry().width() - st::msgPadding.left() - st::msgPadding.right());
|
||||
reply->resize(contentWidth - st::msgPadding.left() - st::msgPadding.right());
|
||||
newHeight += st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
|
||||
}
|
||||
} else if (media && media->isDisplayed()) {
|
||||
|
@ -1618,10 +1638,9 @@ int Message::resizeContentGetHeight(int newWidth) {
|
|||
newHeight = 0;
|
||||
}
|
||||
if (const auto keyboard = item->inlineReplyKeyboard()) {
|
||||
const auto g = countGeometry();
|
||||
const auto keyboardHeight = st::msgBotKbButton.margin + keyboard->naturalHeight();
|
||||
newHeight += keyboardHeight;
|
||||
keyboard->resize(g.width(), keyboardHeight - st::msgBotKbButton.margin);
|
||||
keyboard->resize(contentWidth, keyboardHeight - st::msgBotKbButton.margin);
|
||||
}
|
||||
|
||||
newHeight += marginTop() + marginBottom();
|
||||
|
|
|
@ -28,7 +28,9 @@ struct LogEntryOriginal
|
|||
|
||||
class Message : public Element {
|
||||
public:
|
||||
Message(not_null<HistoryMessage*> data, Context context);
|
||||
Message(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryMessage*> data);
|
||||
|
||||
void draw(
|
||||
Painter &p,
|
||||
|
|
|
@ -292,8 +292,10 @@ void serviceColorsUpdated() {
|
|||
}
|
||||
}
|
||||
|
||||
Service::Service(not_null<HistoryService*> data, Context context)
|
||||
: Element(data, context) {
|
||||
Service::Service(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryService*> data)
|
||||
: Element(delegate, data) {
|
||||
}
|
||||
|
||||
not_null<HistoryService*> Service::message() const {
|
||||
|
|
|
@ -15,7 +15,9 @@ namespace HistoryView {
|
|||
|
||||
class Service : public Element {
|
||||
public:
|
||||
Service(not_null<HistoryService*> data, Context context);
|
||||
Service(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryService*> data);
|
||||
|
||||
void draw(
|
||||
Painter &p,
|
||||
|
|
|
@ -881,6 +881,7 @@ void MainWidget::cancelUploadLayer(not_null<HistoryItem*> item) {
|
|||
if (wasLast && !history->lastMsg) {
|
||||
checkPeerHistory(history->peer);
|
||||
}
|
||||
Auth().data().sendHistoryChangeNotifications();
|
||||
}
|
||||
Auth().uploader().unpause();
|
||||
}), base::lambda_guarded(this, [] {
|
||||
|
@ -1069,7 +1070,12 @@ void MainWidget::deleteAllFromUser(ChannelData *channel, UserData *from) {
|
|||
}
|
||||
}
|
||||
}
|
||||
MTP::send(MTPchannels_DeleteUserHistory(channel->inputChannel, from->inputUser), rpcDone(&MainWidget::deleteAllFromUserPart, { channel, from }));
|
||||
MTP::send(
|
||||
MTPchannels_DeleteUserHistory(
|
||||
channel->inputChannel,
|
||||
from->inputUser),
|
||||
rpcDone(&MainWidget::deleteAllFromUserPart, { channel, from }));
|
||||
Auth().data().sendHistoryChangeNotifications();
|
||||
}
|
||||
|
||||
void MainWidget::deleteAllFromUserPart(DeleteAllFromUserParams params, const MTPmessages_AffectedHistory &result) {
|
||||
|
@ -1525,8 +1531,9 @@ void MainWidget::searchMessages(const QString &query, PeerData *inPeer) {
|
|||
}
|
||||
}
|
||||
|
||||
void MainWidget::itemEdited(HistoryItem *item) {
|
||||
if (_history->peer() == item->history()->peer || (_history->peer() && _history->peer() == item->history()->peer->migrateTo())) {
|
||||
void MainWidget::itemEdited(not_null<HistoryItem*> item) {
|
||||
if (_history->peer() == item->history()->peer
|
||||
|| (_history->peer() && _history->peer() == item->history()->peer->migrateTo())) {
|
||||
_history->itemEdited(item);
|
||||
}
|
||||
}
|
||||
|
@ -2158,6 +2165,9 @@ void MainWidget::ui_showPeerHistory(
|
|||
}
|
||||
}
|
||||
if (_history->isHidden()) {
|
||||
if (!Adaptive::OneColumn() && way == Way::ClearStack) {
|
||||
return false;
|
||||
}
|
||||
return (_mainSection != nullptr)
|
||||
|| (Adaptive::OneColumn() && !_dialogs->isHidden());
|
||||
}
|
||||
|
@ -2530,7 +2540,9 @@ void MainWidget::showNewSection(
|
|||
|| memento.instant()) {
|
||||
return false;
|
||||
}
|
||||
if (Adaptive::OneColumn()
|
||||
if (!Adaptive::OneColumn() && params.way == SectionShow::Way::ClearStack) {
|
||||
return false;
|
||||
} else if (Adaptive::OneColumn()
|
||||
|| (newThirdSection && _thirdSection)
|
||||
|| (newMainSection && isMainSectionShown())) {
|
||||
return true;
|
||||
|
|
|
@ -252,7 +252,7 @@ public:
|
|||
|
||||
void jumpToDate(not_null<PeerData*> peer, const QDate &date);
|
||||
void searchMessages(const QString &query, PeerData *inPeer);
|
||||
void itemEdited(HistoryItem *item);
|
||||
void itemEdited(not_null<HistoryItem*> item);
|
||||
|
||||
void checkLastUpdate(bool afterSleep);
|
||||
|
||||
|
|
|
@ -611,10 +611,6 @@ void Messenger::handleAppDeactivated() {
|
|||
Ui::Tooltip::Hide();
|
||||
}
|
||||
|
||||
void Messenger::call_handleHistoryUpdate() {
|
||||
Notify::handlePendingHistoryUpdate();
|
||||
}
|
||||
|
||||
void Messenger::call_handleUnreadCounterUpdate() {
|
||||
Global::RefUnreadCounterUpdate().notify(true);
|
||||
}
|
||||
|
|
|
@ -178,7 +178,6 @@ public:
|
|||
void handleAppActivated();
|
||||
void handleAppDeactivated();
|
||||
|
||||
void call_handleHistoryUpdate();
|
||||
void call_handleUnreadCounterUpdate();
|
||||
void call_handleDelayedPeerUpdates();
|
||||
void call_handleObservables();
|
||||
|
|
|
@ -367,6 +367,7 @@ Video::Video(
|
|||
, _duration(formatDurationText(_data->duration()))
|
||||
, _thumbLoaded(false) {
|
||||
setDocumentLinks(_data);
|
||||
_data->thumb->load();
|
||||
}
|
||||
|
||||
void Video::initDimensions() {
|
||||
|
|
Loading…
Add table
Reference in a new issue