Improve items resize in history and feed.

This commit is contained in:
John Preston 2018-01-19 20:10:58 +03:00
parent e6baf8ef5b
commit b91ebad8be
31 changed files with 311 additions and 333 deletions

View File

@ -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));

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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 {

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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() {

View File

@ -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(

View File

@ -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();
}
}

View File

@ -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; };

View File

@ -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;
}

View File

@ -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) {

View File

@ -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();

View File

@ -329,7 +329,6 @@ public:
bool isItemVisible(HistoryItem *item);
void confirmDeleteSelectedItems();
void deleteSelectedItems(bool forEveryone);
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e) override;

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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,

View File

@ -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 {

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -611,10 +611,6 @@ void Messenger::handleAppDeactivated() {
Ui::Tooltip::Hide();
}
void Messenger::call_handleHistoryUpdate() {
Notify::handlePendingHistoryUpdate();
}
void Messenger::call_handleUnreadCounterUpdate() {
Global::RefUnreadCounterUpdate().notify(true);
}

View File

@ -178,7 +178,6 @@ public:
void handleAppActivated();
void handleAppDeactivated();
void call_handleHistoryUpdate();
void call_handleUnreadCounterUpdate();
void call_handleDelayedPeerUpdates();
void call_handleObservables();

View File

@ -367,6 +367,7 @@ Video::Video(
, _duration(formatDurationText(_data->duration()))
, _thumbLoaded(false) {
setDocumentLinks(_data);
_data->thumb->load();
}
void Video::initDimensions() {