Support item repaint in Info media overview.

This commit is contained in:
John Preston 2017-10-05 16:35:52 +01:00
parent fdd89d65ca
commit 65cc4d3fbc
44 changed files with 825 additions and 518 deletions

View File

@ -1661,7 +1661,7 @@ void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) {
if (auto item = App::histItemById(NoChannel, msgId.v)) {
if (item->isMediaUnread()) {
item->markMediaRead();
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
if (item->out() && item->history()->peer->isUser()) {
auto when = App::main()->requestingDifference() ? 0 : unixtime();

View File

@ -1954,8 +1954,10 @@ namespace {
}
}
Auth().notifications().clearFromItem(item);
if (Global::started() && !App::quitting()) {
Global::RefItemRemoved().notify(item, true);
if (Global::started()
&& !App::quitting()
&& AuthSession::Exists()) {
Auth().data().markItemRemoved(item);
}
}

View File

@ -66,9 +66,6 @@ public:
base::Observable<not_null<History*>> &historyCleared() {
return _historyCleared;
}
base::Observable<not_null<const HistoryItem*>> &repaintLogEntry() {
return _repaintLogEntry;
}
base::Observable<void> &pendingHistoryResize() {
return _pendingHistoryResize;
}
@ -79,6 +76,24 @@ public:
base::Observable<ItemVisibilityQuery> &queryItemVisibility() {
return _queryItemVisibility;
}
void markItemLayoutChanged(not_null<const HistoryItem*> item) {
_itemLayoutChanged.fire(std::move(item));
}
rpl::producer<not_null<const HistoryItem*>> itemLayoutChanged() const {
return _itemLayoutChanged.events();
}
void requestItemRepaint(not_null<const HistoryItem*> item) {
_itemRepaintRequest.fire(std::move(item));
}
rpl::producer<not_null<const HistoryItem*>> itemRepaintRequest() const {
return _itemRepaintRequest.events();
}
void markItemRemoved(not_null<const HistoryItem*> item) {
_itemRemoved.fire(std::move(item));
}
rpl::producer<not_null<const HistoryItem*>> itemRemoved() const {
return _itemRemoved.events();
}
void copyFrom(const AuthSessionData &other) {
_variables = other._variables;
@ -187,9 +202,12 @@ private:
base::Observable<void> _stickersUpdated;
base::Observable<void> _savedGifsUpdated;
base::Observable<not_null<History*>> _historyCleared;
base::Observable<not_null<const HistoryItem*>> _repaintLogEntry;
base::Observable<void> _pendingHistoryResize;
base::Observable<ItemVisibilityQuery> _queryItemVisibility;
rpl::event_stream<not_null<const HistoryItem*>> _itemLayoutChanged;
rpl::event_stream<not_null<const HistoryItem*>> _itemRepaintRequest;
rpl::event_stream<not_null<const HistoryItem*>> _itemRemoved;
rpl::event_stream<bool> _thirdSectionInfoEnabledValue;
bool _tabbedReplacedWithInfo = false;
rpl::event_stream<bool> _tabbedReplacedWithInfoValue;

View File

@ -324,6 +324,10 @@ public:
void peerListSearchAddRow(not_null<PeerData*> peer) override;
void peerListSearchRefreshRows() override;
rpl::lifetime &lifetime() {
return _lifetime;
}
virtual ~PeerListController() = default;
protected:
@ -351,6 +355,8 @@ private:
PeerListDelegate *_delegate = nullptr;
std::unique_ptr<PeerListSearchController> _searchController = nullptr;
rpl::lifetime _lifetime;
};
class PeerListContent

View File

@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "calls/calls_instance.h"
#include "history/history_media_types.h"
#include "mainwidget.h"
#include "auth_session.h"
namespace Calls {
namespace {
@ -39,7 +40,7 @@ constexpr auto kPerPageCount = 100;
class BoxController::Row : public PeerListRow {
public:
Row(HistoryItem *item);
Row(not_null<HistoryItem*> item);
enum class Type {
Out,
@ -47,7 +48,7 @@ public:
Missed,
};
bool canAddItem(HistoryItem *item) const {
bool canAddItem(not_null<const HistoryItem*> item) const {
return (ComputeType(item) == _type && item->date.date() == _date);
}
void addItem(HistoryItem *item) {
@ -58,7 +59,7 @@ public:
});
refreshStatus();
}
void itemRemoved(HistoryItem *item) {
void itemRemoved(not_null<const HistoryItem*> item) {
if (hasItems() && item->id >= minItemId() && item->id <= maxItemId()) {
_items.erase(std::remove(_items.begin(), _items.end(), item), _items.end());
refreshStatus();
@ -102,7 +103,7 @@ public:
private:
void refreshStatus();
static Type ComputeType(HistoryItem *item);
static Type ComputeType(not_null<const HistoryItem*> item);
std::vector<HistoryItem*> _items;
QDate _date;
@ -112,7 +113,8 @@ private:
};
BoxController::Row::Row(HistoryItem *item) : PeerListRow(item->history()->peer, item->id)
BoxController::Row::Row(not_null<HistoryItem*> item)
: PeerListRow(item->history()->peer, item->id)
, _items(1, item)
, _date(item->date.date())
, _type(ComputeType(item)) {
@ -164,7 +166,8 @@ void BoxController::Row::refreshStatus() {
setCustomStatus((_items.size() > 1) ? lng_call_box_status_group(lt_count, QString::number(_items.size()), lt_status, text()) : text());
}
BoxController::Row::Type BoxController::Row::ComputeType(HistoryItem *item) {
BoxController::Row::Type BoxController::Row::ComputeType(
not_null<const HistoryItem*> item) {
if (item->out()) {
return Type::Out;
} else if (auto media = item->getMedia()) {
@ -193,18 +196,19 @@ void BoxController::Row::stopLastActionRipple() {
}
void BoxController::prepare() {
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
if (auto row = rowForItem(item)) {
row->itemRemoved(item);
if (!row->hasItems()) {
delegate()->peerListRemoveRow(row);
if (!delegate()->peerListFullRowsCount()) {
refreshAbout();
Auth().data().itemRemoved()
| rpl::start_with_next([this](auto item) {
if (auto row = rowForItem(item)) {
row->itemRemoved(item);
if (!row->hasItems()) {
delegate()->peerListRemoveRow(row);
if (!delegate()->peerListFullRowsCount()) {
refreshAbout();
}
}
delegate()->peerListRefreshRows();
}
delegate()->peerListRefreshRows();
}
});
}, lifetime());
subscribe(Current().newServiceMessage(), [this](const FullMsgId &msgId) {
if (auto item = App::histItemById(msgId)) {
insertRow(item, InsertWay::Prepend);
@ -287,21 +291,25 @@ void BoxController::receivedCalls(const QVector<MTPMessage> &result) {
delegate()->peerListRefreshRows();
}
bool BoxController::insertRow(HistoryItem *item, InsertWay way) {
bool BoxController::insertRow(
not_null<HistoryItem*> item,
InsertWay way) {
if (auto row = rowForItem(item)) {
if (row->canAddItem(item)) {
row->addItem(item);
return false;
}
}
(way == InsertWay::Append) ? delegate()->peerListAppendRow(createRow(item)) : delegate()->peerListPrependRow(createRow(item));
(way == InsertWay::Append)
? delegate()->peerListAppendRow(createRow(item))
: delegate()->peerListPrependRow(createRow(item));
delegate()->peerListSortRows([](PeerListRow &a, PeerListRow &b) {
return static_cast<Row&>(a).maxItemId() > static_cast<Row&>(b).maxItemId();
});
return true;
}
BoxController::Row *BoxController::rowForItem(HistoryItem *item) {
BoxController::Row *BoxController::rowForItem(not_null<const HistoryItem*> item) {
auto v = delegate();
if (auto fullRowsCount = v->peerListFullRowsCount()) {
auto itemId = item->id;
@ -343,7 +351,8 @@ BoxController::Row *BoxController::rowForItem(HistoryItem *item) {
return nullptr;
}
std::unique_ptr<PeerListRow> BoxController::createRow(HistoryItem *item) const {
std::unique_ptr<PeerListRow> BoxController::createRow(
not_null<HistoryItem*> item) const {
auto row = std::make_unique<Row>(item);
return std::move(row);
}

View File

@ -24,7 +24,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Calls {
class BoxController : public PeerListController, private base::Subscriber, private MTP::Sender {
class BoxController
: public PeerListController
, private base::Subscriber
, private MTP::Sender {
public:
void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override;
@ -36,14 +39,15 @@ private:
void refreshAbout();
class Row;
Row *rowForItem(HistoryItem *item);
Row *rowForItem(not_null<const HistoryItem*> item);
enum class InsertWay {
Append,
Prepend,
};
bool insertRow(HistoryItem *item, InsertWay way);
std::unique_ptr<PeerListRow> createRow(HistoryItem *item) const;
bool insertRow(not_null<HistoryItem*> item, InsertWay way);
std::unique_ptr<PeerListRow> createRow(
not_null<HistoryItem*> item) const;
MsgId _offsetId = 0;
mtpRequestId _loadRequestId = 0;

View File

@ -22,23 +22,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "lang/lang_keys.h"
#include "inline_bots/inline_bot_layout_item.h"
//#include "observer_peer.h"
#include "mainwidget.h"
//#include "application.h"
//#include "storage/file_upload.h"
//#include "mainwindow.h"
#include "core/file_utilities.h"
//#include "apiwrap.h"
//#include "boxes/confirm_box.h"
#include "media/media_audio.h"
#include "storage/localstorage.h"
#include "platform/platform_specific.h"
#include "history/history_media_types.h"
//#include "styles/style_history.h"
//#include "window/themes/window_theme.h"
//#include "auth_session.h"
#include "auth_session.h"
#include "messenger.h"
//#include "storage/file_download.h"
QString joinList(const QStringList &list, const QString &sep) {
QString result;
@ -728,7 +719,7 @@ void DocumentData::cancel() {
void DocumentData::notifyLayoutChanged() const {
auto &items = App::documentItems();
for (auto item : items.value(const_cast<DocumentData*>(this))) {
Notify::historyItemLayoutChanged(item);
Auth().data().markItemLayoutChanged(item);
}
if (auto items = InlineBots::Layout::documentItems()) {

View File

@ -20,24 +20,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "data/data_photo.h"
//#include "lang/lang_keys.h"
//#include "inline_bots/inline_bot_layout_item.h"
//#include "observer_peer.h"
#include "mainwidget.h"
//#include "application.h"
//#include "storage/file_upload.h"
//#include "mainwindow.h"
//#include "core/file_utilities.h"
//#include "apiwrap.h"
//#include "boxes/confirm_box.h"
//#include "media/media_audio.h"
//#include "storage/localstorage.h"
#include "history/history_media_types.h"
//#include "styles/style_history.h"
//#include "window/themes/window_theme.h"
//#include "auth_session.h"
#include "auth_session.h"
#include "messenger.h"
//#include "storage/file_download.h"
PhotoData::PhotoData(const PhotoId &id, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full)
: id(id)
@ -90,7 +76,7 @@ void PhotoData::notifyLayoutChanged() const {
auto i = items.constFind(const_cast<PhotoData*>(this));
if (i != items.cend()) {
for_const (auto item, i.value()) {
Notify::historyItemLayoutChanged(item);
Auth().data().markItemLayoutChanged(item);
}
}
}

View File

@ -92,9 +92,16 @@ DialogsInner::DialogsInner(QWidget *parent, not_null<Window::Controller*> contro
_cancelSearchFromUser->hide();
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
itemRemoved(item);
});
Auth().data().itemRemoved()
| rpl::start_with_next(
[this](auto item) { itemRemoved(item); },
lifetime());
Auth().data().itemRepaintRequest()
| rpl::start_with_next([this](auto item) {
if (item->history()->lastMsg == item) {
item->history()->updateChatListEntry();
}
}, lifetime());
subscribe(App::histories().sendActionAnimationUpdated(), [this](const Histories::SendActionAnimationUpdate &update) {
auto updateRect = Dialogs::Layout::RowPainter::sendActionAnimationRect(update.width, update.height, getFullWidth(), update.textUpdated);
updateDialogRow(update.history->peer, MsgId(0), updateRect, UpdateRowSection::Default | UpdateRowSection::Filtered);
@ -1436,7 +1443,7 @@ void DialogsInner::visibleTopBottomUpdated(
}
}
void DialogsInner::itemRemoved(HistoryItem *item) {
void DialogsInner::itemRemoved(not_null<const HistoryItem*> item) {
int wasCount = _searchResults.size();
for (auto i = _searchResults.begin(); i != _searchResults.end();) {
if ((*i)->item() == item) {

View File

@ -176,7 +176,7 @@ private:
}
void handlePeerNameChange(not_null<PeerData*> peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
void itemRemoved(HistoryItem *item);
void itemRemoved(not_null<const HistoryItem*> item);
enum class UpdateRowSection {
Default = (1 << 0),
Filtered = (1 << 1),

View File

@ -250,12 +250,6 @@ bool isLayerShown() {
return false;
}
void repaintHistoryItem(not_null<const HistoryItem*> item) {
if (auto main = App::main()) {
main->ui_repaintHistoryItem(item);
}
}
void autoplayMediaInlineAsync(const FullMsgId &msgId) {
if (auto main = App::main()) {
InvokeQueued(main, [msgId] {
@ -355,10 +349,6 @@ void migrateUpdated(PeerData *peer) {
if (MainWidget *m = App::main()) m->notify_migrateUpdated(peer);
}
void historyItemLayoutChanged(const HistoryItem *item) {
if (MainWidget *m = App::main()) m->notify_historyItemLayoutChanged(item);
}
void historyMuteUpdated(History *history) {
if (MainWidget *m = App::main()) m->notify_historyMuteUpdated(history);
}
@ -370,7 +360,7 @@ void handlePendingHistoryUpdate() {
Auth().data().pendingHistoryResize().notify(true);
for (auto item : base::take(Global::RefPendingRepaintItems())) {
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
// Start the video if it is waiting for that.
if (item->pendingInitDimensions()) {
@ -639,7 +629,6 @@ struct Data {
base::Variable<DBIWorkMode> WorkMode = { dbiwmWindowAndTray };
base::Observable<HistoryItem*> ItemRemoved;
base::Observable<void> UnreadCounterUpdate;
base::Observable<void> PeerChooseCancel;
@ -762,7 +751,6 @@ DefineRefVar(Global, base::Observable<void>, LocalPasscodeChanged);
DefineRefVar(Global, base::Variable<DBIWorkMode>, WorkMode);
DefineRefVar(Global, base::Observable<HistoryItem*>, ItemRemoved);
DefineRefVar(Global, base::Observable<void>, UnreadCounterUpdate);
DefineRefVar(Global, base::Observable<void>, PeerChooseCancel);

View File

@ -122,7 +122,6 @@ void hideLayer(anim::type animated = anim::type::normal);
void hideSettingsAndLayer(anim::type animated = anim::type::normal);
bool isLayerShown();
void repaintHistoryItem(not_null<const HistoryItem*> item);
void autoplayMediaInlineAsync(const FullMsgId &msgId);
void showPeerProfile(const PeerId &peer);
@ -181,7 +180,6 @@ bool switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot =
void migrateUpdated(PeerData *peer);
void historyItemLayoutChanged(const HistoryItem *item);
void historyMuteUpdated(History *history);
// handle pending resize() / paint() on history items
@ -399,7 +397,6 @@ DeclareRefVar(base::Observable<void>, LocalPasscodeChanged);
DeclareRefVar(base::Variable<DBIWorkMode>, WorkMode);
DeclareRefVar(base::Observable<HistoryItem*>, ItemRemoved);
DeclareRefVar(base::Observable<void>, UnreadCounterUpdate);
DeclareRefVar(base::Observable<void>, PeerChooseCancel);

View File

@ -205,7 +205,11 @@ void InnerWidget::enumerateDates(Method method) {
enumerateItems<EnumItemsDirection::BottomToTop>(dateCallback);
}
InnerWidget::InnerWidget(QWidget *parent, not_null<Window::Controller*> controller, not_null<ChannelData*> channel) : TWidget(parent)
InnerWidget::InnerWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
not_null<ChannelData*> channel)
: RpWidget(parent)
, _controller(controller)
, _channel(channel)
, _history(App::history(channel))
@ -213,11 +217,12 @@ InnerWidget::InnerWidget(QWidget *parent, not_null<Window::Controller*> controll
, _emptyText(st::historyAdminLogEmptyWidth - st::historyAdminLogEmptyPadding.left() - st::historyAdminLogEmptyPadding.left()) {
setMouseTracking(true);
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
subscribe(Auth().data().repaintLogEntry(), [this](not_null<const HistoryItem*> historyItem) {
if (_history == historyItem->history()) {
repaintItem(historyItem);
}
});
Auth().data().itemRepaintRequest()
| rpl::start_with_next([this](auto item) {
if (item->isLogEntry() && _history == item->history()) {
repaintItem(item);
}
}, lifetime());
subscribe(Auth().data().pendingHistoryResize(), [this] { handlePendingHistoryResize(); });
subscribe(Auth().data().queryItemVisibility(), [this](const AuthSessionData::ItemVisibilityQuery &query) {
if (_history != query.item->history() || !query.item->isLogEntry() || !isVisible()) {

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "history/history_admin_log_item.h"
#include "history/history_admin_log_section.h"
#include "ui/widgets/tooltip.h"
#include "ui/rp_widget.h"
#include "mtproto/sender.h"
#include "base/timer.h"
@ -38,9 +39,16 @@ namespace AdminLog {
class SectionMemento;
class InnerWidget final : public TWidget, public Ui::AbstractTooltipShower, private MTP::Sender, private base::Subscriber {
class InnerWidget final
: public Ui::RpWidget
, public Ui::AbstractTooltipShower
, private MTP::Sender
, private base::Subscriber {
public:
InnerWidget(QWidget *parent, not_null<Window::Controller*> controller, not_null<ChannelData*> channel);
InnerWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
not_null<ChannelData*> channel);
base::Observable<void> showSearchSignal;
base::Observable<int> scrollToSignal;

View File

@ -84,7 +84,12 @@ int BinarySearchBlocksOrItems(const T &list, int edge) {
// flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html
HistoryInner::HistoryInner(HistoryWidget *historyWidget, not_null<Window::Controller*> controller, Ui::ScrollArea *scroll, History *history) : TWidget(nullptr)
HistoryInner::HistoryInner(
HistoryWidget *historyWidget,
not_null<Window::Controller*> controller,
Ui::ScrollArea *scroll,
History *history)
: RpWidget(nullptr)
, _controller(controller)
, _peer(history->peer)
, _migrated(history->migrateFrom())
@ -105,9 +110,10 @@ HistoryInner::HistoryInner(HistoryWidget *historyWidget, not_null<Window::Contro
notifyIsBotChanged();
setMouseTracking(true);
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
itemRemoved(item);
});
Auth().data().itemRemoved()
| rpl::start_with_next(
[this](auto item) { itemRemoved(item); },
lifetime());
subscribe(_controller->gifPauseLevelChanged(), [this] {
if (!_controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any)) {
update();
@ -389,7 +395,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
adjustCurrent(clip.top());
auto selEnd = _selected.cend();
auto hasSel = !_selected.isEmpty();
auto hasSel = !_selected.empty();
auto drawToY = clip.y() + clip.height();
@ -420,9 +426,9 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
sel = FullSelection;
}
} else if (hasSel) {
auto i = _selected.constFind(item);
auto i = _selected.find(item);
if (i != selEnd) {
sel = i.value();
sel = i->second;
}
}
item->draw(p, clip.translated(0, -y), sel, ms);
@ -471,9 +477,9 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
sel = FullSelection;
}
} else if (hasSel) {
auto i = _selected.constFind(item);
auto i = _selected.find(item);
if (i != selEnd) {
sel = i.value();
sel = i->second;
}
}
item->draw(p, historyRect.translated(0, -y), sel, ms);
@ -570,15 +576,18 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
}
}
bool HistoryInner::event(QEvent *e) {
if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) {
bool HistoryInner::eventHook(QEvent *e) {
if (e->type() == QEvent::TouchBegin
|| e->type() == QEvent::TouchUpdate
|| e->type() == QEvent::TouchEnd
|| e->type() == QEvent::TouchCancel) {
QTouchEvent *ev = static_cast<QTouchEvent*>(e);
if (ev->device()->type() == QTouchDevice::TouchScreen) {
touchEvent(ev);
return true;
}
}
return TWidget::event(e);
return RpWidget::eventHook(e);
}
void HistoryInner::onTouchScrollTimer() {
@ -811,9 +820,9 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
if (ClickHandler::getPressed()) {
_mouseAction = MouseAction::PrepareDrag;
} else if (!_selected.isEmpty()) {
if (_selected.cbegin().value() == FullSelection) {
if (_selected.constFind(_mouseActionItem) != _selected.cend() && App::hoveredItem()) {
} else if (!_selected.empty()) {
if (_selected.cbegin()->second == FullSelection) {
if (_selected.find(_mouseActionItem) != _selected.cend() && App::hoveredItem()) {
_mouseAction = MouseAction::PrepareDrag; // start items drag
} else if (!_pressWasInactive) {
_mouseAction = MouseAction::PrepareSelect; // start items select
@ -828,12 +837,12 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
dragState = _mouseActionItem->getState(_dragStartPosition, request);
if (dragState.cursor == HistoryInTextCursorState) {
TextSelection selStatus = { dragState.symbol, dragState.symbol };
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
if (!_selected.isEmpty()) {
repaintItem(_selected.cbegin().key());
if (selStatus != FullSelection && (_selected.empty() || _selected.cbegin()->second != FullSelection)) {
if (!_selected.empty()) {
repaintItem(_selected.cbegin()->first);
_selected.clear();
}
_selected.insert(_mouseActionItem, selStatus);
_selected.emplace(_mouseActionItem, selStatus);
_mouseTextSymbol = dragState.symbol;
_mouseAction = MouseAction::Selecting;
_mouseSelectType = TextSelectType::Paragraphs;
@ -851,13 +860,12 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
_mouseTextSymbol = dragState.symbol;
bool uponSelected = (dragState.cursor == HistoryInTextCursorState);
if (uponSelected) {
if (_selected.isEmpty() ||
_selected.cbegin().value() == FullSelection ||
_selected.cbegin().key() != _mouseActionItem
) {
if (_selected.empty()
|| _selected.cbegin()->second == FullSelection
|| _selected.cbegin()->first != _mouseActionItem) {
uponSelected = false;
} else {
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
uint16 selFrom = _selected.cbegin()->second.from, selTo = _selected.cbegin()->second.to;
if (_mouseTextSymbol < selFrom || _mouseTextSymbol >= selTo) {
uponSelected = false;
}
@ -871,12 +879,12 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
} else {
if (dragState.afterSymbol) ++_mouseTextSymbol;
TextSelection selStatus = { _mouseTextSymbol, _mouseTextSymbol };
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
if (!_selected.isEmpty()) {
repaintItem(_selected.cbegin().key());
if (selStatus != FullSelection && (_selected.empty() || _selected.cbegin()->second != FullSelection)) {
if (!_selected.empty()) {
repaintItem(_selected.cbegin()->first);
_selected.clear();
}
_selected.insert(_mouseActionItem, selStatus);
_selected.emplace(_mouseActionItem, selStatus);
_mouseAction = MouseAction::Selecting;
repaintItem(_mouseActionItem);
} else {
@ -911,21 +919,20 @@ void HistoryInner::performDrag() {
bool uponSelected = false;
if (_mouseActionItem) {
if (!_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
uponSelected = _selected.contains(_mouseActionItem);
if (!_selected.empty() && _selected.cbegin()->second == FullSelection) {
uponSelected = (_selected.find(_mouseActionItem) != _selected.cend());
} else {
HistoryStateRequest request;
request.flags |= Text::StateRequest::Flag::LookupSymbol;
auto dragState = _mouseActionItem->getState(_dragStartPosition, request);
uponSelected = (dragState.cursor == HistoryInTextCursorState);
if (uponSelected) {
if (_selected.isEmpty() ||
_selected.cbegin().value() == FullSelection ||
_selected.cbegin().key() != _mouseActionItem
) {
if (_selected.empty()
|| _selected.cbegin()->second == FullSelection
|| _selected.cbegin()->first != _mouseActionItem) {
uponSelected = false;
} else {
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
uint16 selFrom = _selected.cbegin()->second.from, selTo = _selected.cbegin()->second.to;
if (dragState.symbol < selFrom || dragState.symbol >= selTo) {
uponSelected = false;
}
@ -997,7 +1004,7 @@ void HistoryInner::performDrag() {
}
}
void HistoryInner::itemRemoved(HistoryItem *item) {
void HistoryInner::itemRemoved(not_null<const HistoryItem*> item) {
if (_history != item->history() && _migrated != item->history()) {
return;
}
@ -1032,7 +1039,7 @@ void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton bu
} else if (auto pressed = App::pressedLinkItem()) {
// if we are in selecting items mode perhaps we want to
// toggle selection instead of activating the pressed link
if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection && button != Qt::RightButton) {
if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && !_selected.empty() && _selected.cbegin()->second == FullSelection && button != Qt::RightButton) {
if (auto media = pressed->getMedia()) {
if (media->toggleSelectionByHandlerClick(activated)) {
activated.clear();
@ -1052,27 +1059,27 @@ void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton bu
App::activateClickHandler(activated, button);
return;
}
if (_mouseAction == MouseAction::PrepareSelect && !_pressWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
if (_mouseAction == MouseAction::PrepareSelect && !_pressWasInactive && !_selected.empty() && _selected.cbegin()->second == FullSelection) {
SelectedItems::iterator i = _selected.find(_mouseActionItem);
if (i == _selected.cend() && !_mouseActionItem->serviceMsg() && _mouseActionItem->id > 0) {
if (_selected.size() < MaxSelectedItems) {
if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
if (!_selected.empty() && _selected.cbegin()->second != FullSelection) {
_selected.clear();
}
_selected.insert(_mouseActionItem, FullSelection);
_selected.emplace(_mouseActionItem, FullSelection);
}
} else {
_selected.erase(i);
}
repaintItem(_mouseActionItem);
} else if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && button != Qt::RightButton) {
SelectedItems::iterator i = _selected.find(_mouseActionItem);
if (i != _selected.cend() && i.value() == FullSelection) {
auto i = _selected.find(_mouseActionItem);
if (i != _selected.cend() && i->second == FullSelection) {
_selected.erase(i);
repaintItem(_mouseActionItem);
} else if (i == _selected.cend() && !_mouseActionItem->serviceMsg() && _mouseActionItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
} else if (i == _selected.cend() && !_mouseActionItem->serviceMsg() && _mouseActionItem->id > 0 && !_selected.empty() && _selected.cbegin()->second == FullSelection) {
if (_selected.size() < MaxSelectedItems) {
_selected.insert(_mouseActionItem, FullSelection);
_selected.emplace(_mouseActionItem, FullSelection);
repaintItem(_mouseActionItem);
}
} else {
@ -1083,8 +1090,8 @@ void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton bu
if (_dragSelFrom && _dragSelTo) {
applyDragSelection();
_dragSelFrom = _dragSelTo = 0;
} else if (!_selected.isEmpty() && !_pressWasInactive) {
auto sel = _selected.cbegin().value();
} else if (!_selected.empty() && !_pressWasInactive) {
auto sel = _selected.cbegin()->second;
if (sel != FullSelection && sel.from == sel.to) {
_selected.clear();
App::wnd()->setInnerFocus();
@ -1098,8 +1105,8 @@ void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton bu
_widget->updateTopBarSelection();
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
setToClipboard(_selected.cbegin().key()->selectedText(_selected.cbegin().value()), QClipboard::Selection);
if (!_selected.empty() && _selected.cbegin()->second != FullSelection) {
setToClipboard(_selected.cbegin()->first->selectedText(_selected.cbegin()->second), QClipboard::Selection);
}
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
}
@ -1115,7 +1122,7 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) {
if (!_history) return;
mouseActionStart(e->globalPos(), e->button());
if (((_mouseAction == MouseAction::Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) || (_mouseAction == MouseAction::None && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection))) && _mouseSelectType == TextSelectType::Letters && _mouseActionItem) {
if (((_mouseAction == MouseAction::Selecting && !_selected.empty() && _selected.cbegin()->second != FullSelection) || (_mouseAction == MouseAction::None && (_selected.empty() || _selected.cbegin()->second != FullSelection))) && _mouseSelectType == TextSelectType::Letters && _mouseActionItem) {
HistoryStateRequest request;
request.flags |= Text::StateRequest::Flag::LookupSymbol;
auto dragState = _mouseActionItem->getState(_dragStartPosition, request);
@ -1125,11 +1132,11 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) {
if (_mouseAction == MouseAction::None) {
_mouseAction = MouseAction::Selecting;
TextSelection selStatus = { dragState.symbol, dragState.symbol };
if (!_selected.isEmpty()) {
repaintItem(_selected.cbegin().key());
if (!_selected.empty()) {
repaintItem(_selected.cbegin()->first);
_selected.clear();
}
_selected.insert(_mouseActionItem, selStatus);
_selected.emplace(_mouseActionItem, selStatus);
}
mouseMoveEvent(e);
@ -1158,17 +1165,17 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
// -2 - has full selected items, but not over, -1 - has selection, but no over, 0 - no selection, 1 - over text, 2 - over full selected items
auto isUponSelected = 0;
auto hasSelected = 0;;
if (!_selected.isEmpty()) {
if (!_selected.empty()) {
isUponSelected = -1;
if (_selected.cbegin().value() == FullSelection) {
if (_selected.cbegin()->second == FullSelection) {
hasSelected = 2;
if (App::hoveredItem() && _selected.constFind(App::hoveredItem()) != _selected.cend()) {
if (App::hoveredItem() && _selected.find(App::hoveredItem()) != _selected.cend()) {
isUponSelected = 2;
} else {
isUponSelected = -2;
}
} else {
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
uint16 selFrom = _selected.cbegin()->second.from, selTo = _selected.cbegin()->second.to;
hasSelected = (selTo > selFrom) ? 1 : 0;
if (App::mousedItem() && App::mousedItem() == App::hoveredItem()) {
auto mousePos = mapPointToItem(mapFromGlobal(_mousePosition), App::mousedItem());
@ -1520,21 +1527,21 @@ TextWithEntities HistoryInner::getSelectedText() const {
applyDragSelection(&sel);
}
if (sel.isEmpty()) {
if (sel.empty()) {
return TextWithEntities();
}
if (sel.cbegin().value() != FullSelection) {
return sel.cbegin().key()->selectedText(sel.cbegin().value());
if (sel.cbegin()->second != FullSelection) {
return sel.cbegin()->first->selectedText(sel.cbegin()->second);
}
int fullSize = 0;
QString timeFormat(qsl(", [dd.MM.yy hh:mm]\n"));
QMap<int, TextWithEntities> texts;
for (auto i = sel.cbegin(), e = sel.cend(); i != e; ++i) {
HistoryItem *item = i.key();
for (auto &selected : sel) {
auto item = selected.first;
if (item->detached()) continue;
QString time = item->date.toString(timeFormat);
auto time = item->date.toString(timeFormat);
TextWithEntities part, unwrapped = item->selectedText(FullSelection);
int size = item->author()->name.size() + time.size() + unwrapped.text.size();
part.text.reserve(size);
@ -1563,7 +1570,7 @@ TextWithEntities HistoryInner::getSelectedText() const {
void HistoryInner::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Escape) {
_widget->onListEscapePressed();
} else if (e == QKeySequence::Copy && !_selected.isEmpty()) {
} else if (e == QKeySequence::Copy && !_selected.empty()) {
copySelectedText();
#ifdef Q_OS_MAC
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
@ -1850,7 +1857,7 @@ HistoryInner::~HistoryInner() {
}
bool HistoryInner::focusNextPrevChild(bool next) {
if (_selected.isEmpty()) {
if (_selected.empty()) {
return TWidget::focusNextPrevChild(next);
} else {
clearSelectedItems();
@ -1932,7 +1939,7 @@ HistoryItem *HistoryInner::nextItem(HistoryItem *item) {
}
bool HistoryInner::canCopySelected() const {
return !_selected.isEmpty();
return !_selected.empty();
}
bool HistoryInner::canDeleteSelected() const {
@ -1942,13 +1949,13 @@ bool HistoryInner::canDeleteSelected() const {
Window::TopBarWidget::SelectedState HistoryInner::getSelectionState() const {
auto result = Window::TopBarWidget::SelectedState {};
for (auto i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) {
if (i.value() == FullSelection) {
for (auto &selected : _selected) {
if (selected.second == FullSelection) {
++result.count;
if (i.key()->canDelete()) {
if (selected.first->canDelete()) {
++result.canDeleteCount;
}
if (i.key()->canForward()) {
if (selected.first->canForward()) {
++result.canForwardCount;
}
} else {
@ -1959,7 +1966,7 @@ Window::TopBarWidget::SelectedState HistoryInner::getSelectionState() const {
}
void HistoryInner::clearSelectedItems(bool onlyTextSelection) {
if (!_selected.isEmpty() && (!onlyTextSelection || _selected.cbegin().value() != FullSelection)) {
if (!_selected.empty() && (!onlyTextSelection || _selected.cbegin()->second != FullSelection)) {
_selected.clear();
_widget->updateTopBarSelection();
_widget->update();
@ -1968,12 +1975,12 @@ void HistoryInner::clearSelectedItems(bool onlyTextSelection) {
SelectedItemSet HistoryInner::getSelectedItems() const {
auto result = SelectedItemSet();
if (_selected.isEmpty() || _selected.cbegin().value() != FullSelection) {
if (_selected.empty() || _selected.cbegin()->second != FullSelection) {
return result;
}
for (auto i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) {
auto item = i.key();
for (auto &selected : _selected) {
auto item = selected.first;
if (item && item->toHistoryMessage() && item->id > 0) {
if (item->history() == _migrated) {
result.insert(item->id - ServerMaxMsgId, item);
@ -1986,12 +1993,12 @@ SelectedItemSet HistoryInner::getSelectedItems() const {
}
void HistoryInner::selectItem(HistoryItem *item) {
if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
if (!_selected.empty() && _selected.cbegin()->second != FullSelection) {
_selected.clear();
} else if (_selected.size() == MaxSelectedItems && _selected.constFind(item) == _selected.cend()) {
} else if (_selected.size() == MaxSelectedItems && _selected.find(item) == _selected.cend()) {
return;
}
_selected.insert(item, FullSelection);
_selected.emplace(item, FullSelection);
_widget->updateTopBarSelection();
_widget->update();
}
@ -2037,7 +2044,7 @@ void HistoryInner::onUpdateSelected() {
HistoryTextState dragState;
ClickHandlerHost *lnkhost = nullptr;
bool selectingText = (item == _mouseActionItem && item == App::hoveredItem() && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection);
bool selectingText = (item == _mouseActionItem && item == App::hoveredItem() && !_selected.empty() && _selected.cbegin()->second != FullSelection);
if (point.y() < _historyPaddingTop) {
if (_botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) {
dragState = _botAbout->info->text.getState(point - _botAbout->rect.topLeft() - QPoint(st::msgPadding.left(), st::msgPadding.top() + st::botDescSkip + st::msgNameFont->height), _botAbout->width);
@ -2146,7 +2153,7 @@ void HistoryInner::onUpdateSelected() {
_mouseCursorState = dragState.cursor;
if (dragState.link) {
cur = style::cur_pointer;
} else if (_mouseCursorState == HistoryInTextCursorState && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
} else if (_mouseCursorState == HistoryInTextCursorState && (_selected.empty() || _selected.cbegin()->second != FullSelection)) {
cur = style::cur_text;
} else if (_mouseCursorState == HistoryInDateCursorState) {
// cur = style::cur_cross;
@ -2203,8 +2210,8 @@ void HistoryInner::onUpdateSelected() {
dragFirstAffected = (dragFirstAffected == dragSelTo) ? 0 : (selectingDown ? nextItem(dragFirstAffected) : prevItem(dragFirstAffected));
}
if (dragFirstAffected) {
auto i = _selected.constFind(dragFirstAffected);
dragSelecting = (i == _selected.cend() || i.value() != FullSelection);
auto i = _selected.find(dragFirstAffected);
dragSelecting = (i == _selected.cend() || i->second != FullSelection);
}
updateDragSelection(dragSelFrom, dragSelTo, dragSelecting);
}
@ -2213,7 +2220,7 @@ void HistoryInner::onUpdateSelected() {
if (ClickHandler::getPressed()) {
cur = style::cur_pointer;
} else if (_mouseAction == MouseAction::Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
} else if (_mouseAction == MouseAction::Selecting && !_selected.empty() && _selected.cbegin()->second != FullSelection) {
if (!_dragSelFrom || !_dragSelTo) {
cur = style::cur_text;
}
@ -2353,16 +2360,16 @@ void HistoryInner::applyDragSelection() {
void HistoryInner::addSelectionRange(SelectedItems *toItems, int32 fromblock, int32 fromitem, int32 toblock, int32 toitem, History *h) const {
if (fromblock >= 0 && fromitem >= 0 && toblock >= 0 && toitem >= 0) {
for (; fromblock <= toblock; ++fromblock) {
HistoryBlock *block = h->blocks[fromblock];
auto block = h->blocks[fromblock];
for (int32 cnt = (fromblock < toblock) ? block->items.size() : (toitem + 1); fromitem < cnt; ++fromitem) {
HistoryItem *item = block->items[fromitem];
SelectedItems::iterator i = toItems->find(item);
auto item = block->items[fromitem];
auto i = toItems->find(item);
if (item->id > 0 && !item->serviceMsg()) {
if (i == toItems->cend()) {
if (toItems->size() >= MaxSelectedItems) break;
toItems->insert(item, FullSelection);
} else if (i.value() != FullSelection) {
*i = FullSelection;
toItems->emplace(item, FullSelection);
} else if (i->second != FullSelection) {
i->second = FullSelection;
}
} else {
if (i != toItems->cend()) {
@ -2383,7 +2390,7 @@ void HistoryInner::applyDragSelection(SelectedItems *toItems) const {
}
seltoy += _dragSelTo->height();
if (!toItems->isEmpty() && toItems->cbegin().value() != FullSelection) {
if (!toItems->empty() && toItems->cbegin()->second != FullSelection) {
toItems->clear();
}
if (_dragSelecting) {
@ -2407,8 +2414,8 @@ void HistoryInner::applyDragSelection(SelectedItems *toItems) const {
}
addSelectionRange(toItems, fromblock, fromitem, toblock, toitem, _history);
} else {
for (SelectedItems::iterator i = toItems->begin(); i != toItems->cend();) {
int32 iy = itemTop(i.key());
for (auto i = toItems->begin(); i != toItems->cend();) {
auto iy = itemTop(i->first);
if (iy < 0) {
if (iy < -1) i = toItems->erase(i);
continue;

View File

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/rp_widget.h"
#include "ui/widgets/tooltip.h"
#include "ui/widgets/scroll_area.h"
#include "window/top_bar_widget.h"
@ -33,11 +34,18 @@ class PopupMenu;
} // namespace Ui
class HistoryWidget;
class HistoryInner : public TWidget, public Ui::AbstractTooltipShower, private base::Subscriber {
class HistoryInner
: public Ui::RpWidget
, public Ui::AbstractTooltipShower
, private base::Subscriber {
Q_OBJECT
public:
HistoryInner(HistoryWidget *historyWidget, not_null<Window::Controller*> controller, Ui::ScrollArea *scroll, History *history);
HistoryInner(
HistoryWidget *historyWidget,
not_null<Window::Controller*> controller,
Ui::ScrollArea *scroll,
History *history);
void messagesReceived(PeerData *peer, const QVector<MTPMessage> &messages);
void messagesReceivedDown(PeerData *peer, const QVector<MTPMessage> &messages);
@ -91,7 +99,7 @@ public:
protected:
bool focusNextPrevChild(bool next) override;
bool event(QEvent *e) override; // calls touchEvent when necessary
bool eventHook(QEvent *e) override; // calls touchEvent when necessary
void touchEvent(QTouchEvent *e);
void paintEvent(QPaintEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
@ -141,7 +149,7 @@ private:
void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false);
void itemRemoved(HistoryItem *item);
void itemRemoved(not_null<const HistoryItem*> item);
void savePhotoToFile(PhotoData *photo);
void saveDocumentToFile(DocumentData *document);
void copyContextImage(PhotoData *photo);
@ -206,7 +214,7 @@ private:
bool _firstLoading = false;
style::cursor _cursor = style::cur_default;
using SelectedItems = QMap<HistoryItem*, TextSelection>;
using SelectedItems = std::map<HistoryItem*, TextSelection, std::less<>>;
SelectedItems _selected;
void applyDragSelection();
void applyDragSelection(SelectedItems *toItems) const;

View File

@ -685,7 +685,7 @@ void HistoryItem::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool activ
}
}
App::hoveredLinkItem(active ? this : nullptr);
Ui::repaintHistoryItem(this);
Auth().data().requestItemRepaint(this);
}
void HistoryItem::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
@ -695,7 +695,7 @@ void HistoryItem::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pres
}
}
App::pressedLinkItem(pressed ? this : nullptr);
Ui::repaintHistoryItem(this);
Auth().data().requestItemRepaint(this);
}
void HistoryItem::addLogEntryOriginal(WebPageId localId, const QString &label, const TextWithEntities &content) {
@ -1103,14 +1103,14 @@ void HistoryItem::clipCallback(Media::Clip::Notification notification) {
}
if (!stopped) {
setPendingInitDimensions();
Notify::historyItemLayoutChanged(this);
Auth().data().markItemLayoutChanged(this);
Global::RefPendingRepaintItems().insert(this);
}
} break;
case NotificationRepaint: {
if (!reader->currentDisplayed()) {
Ui::repaintHistoryItem(this);
Auth().data().requestItemRepaint(this);
}
} break;
}

View File

@ -176,11 +176,11 @@ void HistoryFileMedia::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool
}
void HistoryFileMedia::thumbAnimationCallback() {
Ui::repaintHistoryItem(_parent);
Auth().data().requestItemRepaint(_parent);
}
void HistoryFileMedia::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
Ui::repaintHistoryItem(_parent);
Auth().data().requestItemRepaint(_parent);
}
void HistoryFileMedia::setLinks(ClickHandlerPtr &&openl, ClickHandlerPtr &&savel, ClickHandlerPtr &&cancell) {
@ -206,7 +206,7 @@ void HistoryFileMedia::setStatusSize(int32 newSize, int32 fullSize, int32 durati
void HistoryFileMedia::step_radial(TimeMs ms, bool timer) {
if (timer) {
Ui::repaintHistoryItem(_parent);
Auth().data().requestItemRepaint(_parent);
} else {
_animation->radial.update(dataProgress(), dataFinished(), ms);
if (!_animation->radial.animating()) {
@ -1553,7 +1553,7 @@ void HistoryDocument::updatePressed(QPoint point) {
nameright = st::msgFilePadding.left();
}
voice->setSeekingCurrent(snap((point.x() - nameleft) / float64(_width - nameleft - nameright), 0., 1.));
Ui::repaintHistoryItem(_parent);
Auth().data().requestItemRepaint(_parent);
}
}
}
@ -1748,7 +1748,7 @@ void HistoryDocument::step_voiceProgress(float64 ms, bool timer) {
} else {
voice->_playback->a_progress.update(qMin(dt, 1.), anim::linear);
}
if (timer) Ui::repaintHistoryItem(_parent);
if (timer) Auth().data().requestItemRepaint(_parent);
}
}
}
@ -2613,7 +2613,7 @@ bool HistoryGif::playInline(bool autoplay) {
if (mode == Mode::Video) {
_roundPlayback = std::make_unique<Media::Clip::Playback>();
_roundPlayback->setValueChangedCallback([this](float64 value) {
Ui::repaintHistoryItem(_parent);
Auth().data().requestItemRepaint(_parent);
});
if (App::main()) {
App::main()->mediaMarkRead(_data);
@ -2638,7 +2638,7 @@ void HistoryGif::stopInline() {
clearClipReader();
_parent->setPendingInitDimensions();
Notify::historyItemLayoutChanged(_parent);
Auth().data().markItemLayoutChanged(_parent);
}
void HistoryGif::setClipReader(Media::Clip::ReaderPointer gif) {

View File

@ -556,7 +556,7 @@ const style::TextStyle &HistoryMessage::KeyboardStyle::textStyle() const {
}
void HistoryMessage::KeyboardStyle::repaint(not_null<const HistoryItem*> item) const {
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
int HistoryMessage::KeyboardStyle::buttonRadius() const {
@ -1581,7 +1581,7 @@ void HistoryMessage::setViewsCount(int32 count) {
views->_viewsText = (views->_views >= 0) ? formatViewsCount(views->_views) : QString();
views->_viewsWidth = views->_viewsText.isEmpty() ? 0 : st::msgDateFont->width(views->_viewsText);
if (was == views->_viewsWidth) {
Ui::repaintHistoryItem(this);
Auth().data().requestItemRepaint(this);
} else {
if (_text.hasSkipBlock()) {
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
@ -1596,7 +1596,7 @@ void HistoryMessage::setId(MsgId newId) {
bool wasPositive = (id > 0), positive = (newId > 0);
HistoryItem::setId(newId);
if (wasPositive == positive) {
Ui::repaintHistoryItem(this);
Auth().data().requestItemRepaint(this);
} else {
if (_text.hasSkipBlock()) {
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());

View File

@ -605,8 +605,7 @@ SharedMediaMergedSlice SharedMediaMergedSliceBuilder::snapshot() const {
return SharedMediaMergedSlice(
_key,
_part,
_migrated
);
_migrated);
}
rpl::producer<SharedMediaMergedSlice> SharedMediaMergedViewer(
@ -615,7 +614,7 @@ rpl::producer<SharedMediaMergedSlice> SharedMediaMergedViewer(
int limitAfter) {
Expects(IsServerMsgId(key.universalId)
|| (key.universalId == 0)
|| (IsServerMsgId(-key.universalId) && key.migratedPeerId != 0));
|| (IsServerMsgId(ServerMaxMsgId + key.universalId) && key.migratedPeerId != 0));
Expects((key.universalId != 0) || (limitBefore == 0 && limitAfter == 0));
return [=](auto consumer) {

View File

@ -131,7 +131,9 @@ public:
return {
key.migratedPeerId,
key.type,
(key.universalId <= 0) ? (-key.universalId) : (ServerMaxMsgId - 1)
(key.universalId < 0)
? (ServerMaxMsgId + key.universalId)
: (key.universalId > 0) ? (ServerMaxMsgId - 1) : 0
};
}
@ -157,9 +159,9 @@ private:
return ComputeId(slice.key().peerId, slice[index]);
};
static FullMsgId ComputeId(const Key &key) {
return (key.universalId > 0)
return (key.universalId >= 0)
? ComputeId(key.peerId, key.universalId)
: ComputeId(key.migratedPeerId, -key.universalId);
: ComputeId(key.migratedPeerId, ServerMaxMsgId + key.universalId);
}
static base::optional<int> Add(
const base::optional<int> &a,
@ -181,7 +183,7 @@ private:
&& (!_migrated || _part.skippedBefore() != 0);
}
bool isolatedInMigrated() const {
return IsServerMsgId(-_key.universalId)
return IsServerMsgId(ServerMaxMsgId + _key.universalId)
&& (_migrated->skippedAfter() != 0);
}
@ -298,9 +300,9 @@ private:
}
static Value ComputeId(const Key &key) {
if (auto messageId = base::get_if<MessageId>(&key.universalId)) {
return (*messageId > 0)
return (*messageId >= 0)
? ComputeId(key.peerId, *messageId)
: ComputeId(key.migratedPeerId, -*messageId);
: ComputeId(key.migratedPeerId, ServerMaxMsgId + *messageId);
}
return *base::get_if<not_null<PhotoData*>>(&key.universalId);
}

View File

@ -171,35 +171,35 @@ void ReportSpamPanel::setReported(bool reported, PeerData *onPeer) {
update();
}
HistoryHider::HistoryHider(MainWidget *parent, const SelectedItemSet &items) : TWidget(parent)
HistoryHider::HistoryHider(MainWidget *parent, const SelectedItemSet &items) : RpWidget(parent)
, _forwardItems(items)
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
init();
}
HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : TWidget(parent)
HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : RpWidget(parent)
, _sharedContact(sharedContact)
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
init();
}
HistoryHider::HistoryHider(MainWidget *parent) : TWidget(parent)
HistoryHider::HistoryHider(MainWidget *parent) : RpWidget(parent)
, _sendPath(true)
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
init();
}
HistoryHider::HistoryHider(MainWidget *parent, const QString &botAndQuery) : TWidget(parent)
HistoryHider::HistoryHider(MainWidget *parent, const QString &botAndQuery) : RpWidget(parent)
, _botAndQuery(botAndQuery)
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
init();
}
HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString &text) : TWidget(parent)
HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString &text) : RpWidget(parent)
, _shareUrl(url)
, _shareText(text)
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
@ -210,17 +210,18 @@ HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString
void HistoryHider::init() {
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
if (!_forwardItems.empty()) {
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
for (auto i = _forwardItems.begin(); i != _forwardItems.end(); ++i) {
if (i->get() == item) {
i = _forwardItems.erase(i);
break;
Auth().data().itemRemoved()
| rpl::start_with_next([this](auto item) {
for (auto i = _forwardItems.begin(); i != _forwardItems.end(); ++i) {
if (i->get() == item) {
i = _forwardItems.erase(i);
break;
}
}
}
if (_forwardItems.empty()) {
startHide();
}
});
if (_forwardItems.empty()) {
startHide();
}
}, lifetime());
}
connect(_send, SIGNAL(clicked()), this, SLOT(forward()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(startHide()));
@ -665,9 +666,14 @@ HistoryWidget::HistoryWidget(QWidget *parent, not_null<Window::Controller*> cont
connect(&_updateEditTimeLeftDisplay, SIGNAL(timeout()), this, SLOT(updateField()));
subscribe(Adaptive::Changed(), [this] { update(); });
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
itemRemoved(item);
});
Auth().data().itemRemoved()
| rpl::start_with_next(
[this](auto item) { itemRemoved(item); },
lifetime());
Auth().data().itemRepaintRequest()
| rpl::start_with_next(
[this](auto item) { repaintHistoryItem(item); },
lifetime());
subscribe(Auth().data().contactsLoaded(), [this](bool) {
if (_peer) {
updateReportSpamStatus();
@ -740,6 +746,16 @@ HistoryWidget::HistoryWidget(QWidget *parent, not_null<Window::Controller*> cont
}
}
});
Auth().data().itemLayoutChanged()
| rpl::start_with_next([this](auto item) {
if (_peer && _list) {
if ((item == App::mousedItem())
|| (item == App::hoveredItem())
|| (item == App::hoveredLinkItem())) {
_list->onUpdateSelected();
}
}
}, lifetime());
orderWidgets();
}
@ -913,7 +929,7 @@ void HistoryWidget::updateHighlightedMessage() {
return stopMessageHighlight();
}
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
TimeMs HistoryWidget::highlightStartTime(not_null<const HistoryItem*> item) const {
@ -3272,7 +3288,7 @@ void HistoryWidget::app_sendBotCallback(const HistoryMessageReplyMarkup::Button
sendData = button->data;
}
button->requestId = MTP::send(MTPmessages_GetBotCallbackAnswer(MTP_flags(flags), _peer->input, MTP_int(msg->id), MTP_bytes(sendData)), rpcDone(&HistoryWidget::botCallbackDone, info), rpcFail(&HistoryWidget::botCallbackFail, info));
Ui::repaintHistoryItem(msg);
Auth().data().requestItemRepaint(msg);
if (_replyToId == msg->id) {
cancelReply();
@ -3290,7 +3306,7 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC
if (info.row < markup->rows.size() && info.col < markup->rows.at(info.row).size()) {
if (markup->rows.at(info.row).at(info.col).requestId == req) {
markup->rows.at(info.row).at(info.col).requestId = 0;
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
}
}
@ -3325,7 +3341,7 @@ bool HistoryWidget::botCallbackFail(BotCallbackInfo info, const RPCError &error,
if (info.row < markup->rows.size() && info.col < markup->rows.at(info.row).size()) {
if (markup->rows.at(info.row).at(info.col).requestId == req) {
markup->rows.at(info.row).at(info.col).requestId = 0;
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
}
}
@ -4449,7 +4465,7 @@ void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
if (!item->isPost()) {
updateSendAction(item->history(), SendAction::Type::UploadPhoto, 0);
}
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
}
@ -4460,17 +4476,16 @@ void HistoryWidget::onDocumentProgress(const FullMsgId &newId) {
if (!item->isPost()) {
updateSendAction(item->history(), (document && document->voice()) ? SendAction::Type::UploadVoice : SendAction::Type::UploadFile, document ? document->uploadOffset : 0);
}
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
}
void HistoryWidget::onPhotoFailed(const FullMsgId &newId) {
HistoryItem *item = App::histItemById(newId);
if (item) {
if (auto item = App::histItemById(newId)) {
if (!item->isPost()) {
updateSendAction(item->history(), SendAction::Type::UploadPhoto, -1);
}
// Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
}
@ -4481,7 +4496,7 @@ void HistoryWidget::onDocumentFailed(const FullMsgId &newId) {
if (!item->isPost()) {
updateSendAction(item->history(), (document && document->voice()) ? SendAction::Type::UploadVoice : SendAction::Type::UploadFile, -1);
}
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
}
@ -4585,13 +4600,16 @@ void HistoryWidget::grabFinish() {
_topShadow->show();
}
void HistoryWidget::ui_repaintHistoryItem(not_null<const HistoryItem*> item) {
if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) {
void HistoryWidget::repaintHistoryItem(
not_null<const HistoryItem*> item) {
auto itemHistory = item->history();
if (itemHistory == _history || itemHistory == _migrated) {
auto ms = getms();
if (_lastScrolled + kSkipRepaintWhileScrollMs <= ms) {
_list->repaintItem(item);
} else {
_updateHistoryItems.start(_lastScrolled + kSkipRepaintWhileScrollMs - ms);
_updateHistoryItems.start(
_lastScrolled + kSkipRepaintWhileScrollMs - ms);
}
}
}
@ -4611,12 +4629,6 @@ PeerData *HistoryWidget::ui_getPeerForMouseAction() {
return _peer;
}
void HistoryWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
if (_peer && _list && (item == App::mousedItem() || item == App::hoveredItem() || item == App::hoveredLinkItem())) {
_list->onUpdateSelected();
}
}
void HistoryWidget::handlePendingHistoryUpdate() {
if (hasPendingResizedItems() || _updateHistoryGeometryRequired) {
if (_list) {
@ -4689,7 +4701,7 @@ void HistoryWidget::updateControlsGeometry() {
st::lineWidth);
}
void HistoryWidget::itemRemoved(HistoryItem *item) {
void HistoryWidget::itemRemoved(not_null<const HistoryItem*> item) {
if (item == _replyEditMsg) {
if (_editMsgId) {
cancelEdit();
@ -4707,6 +4719,17 @@ void HistoryWidget::itemRemoved(HistoryItem *item) {
onKbToggle();
_kbReplyTo = 0;
}
for (auto i = _toForward.begin(); i != _toForward.end(); ++i) {
if (i->get() == item) {
i = _toForward.erase(i);
updateForwardingTexts();
if (_toForward.empty()) {
updateControlsVisibility();
updateControlsGeometry();
}
break;
}
}
}
void HistoryWidget::itemEdited(HistoryItem *item) {
@ -6148,7 +6171,6 @@ void HistoryWidget::updateForwarding() {
} else {
_toForward.clear();
}
updateForwardingItemRemovedSubscription();
updateControlsVisibility();
updateControlsGeometry();
}
@ -6199,24 +6221,6 @@ void HistoryWidget::checkForwardingInfo() {
}
}
void HistoryWidget::updateForwardingItemRemovedSubscription() {
if (_toForward.isEmpty()) {
unsubscribe(_forwardingItemRemovedSubscription);
_forwardingItemRemovedSubscription = 0;
} else if (!_forwardingItemRemovedSubscription) {
_forwardingItemRemovedSubscription = subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
for (auto i = _toForward.begin(); i != _toForward.end(); ++i) {
if (i->get() == item) {
i = _toForward.erase(i);
updateForwardingItemRemovedSubscription();
updateForwardingTexts();
break;
}
}
});
}
}
void HistoryWidget::updateReplyToName() {
if (_editMsgId) return;
if (!_replyEditMsg && (_replyToId || !_kbReplyTo)) return;

View File

@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "window/section_widget.h"
#include "core/single_timer.h"
#include "ui/widgets/input_fields.h"
#include "ui/rp_widget.h"
#include "base/flags.h"
namespace InlineBots {
@ -97,7 +98,7 @@ private:
};
class HistoryHider : public TWidget, private base::Subscriber {
class HistoryHider : public Ui::RpWidget, private base::Subscriber {
Q_OBJECT
public:
@ -276,7 +277,6 @@ public:
void cancelEdit();
void updateForwarding();
void updateForwardingTexts();
void updateForwardingItemRemovedSubscription();
void clearReplyReturns();
void pushReplyReturn(HistoryItem *item);
@ -350,10 +350,8 @@ public:
void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, not_null<const HistoryItem*> msg, int row, int col);
void ui_repaintHistoryItem(not_null<const HistoryItem*> item);
PeerData *ui_getPeerForMouseAction();
void notify_historyItemLayoutChanged(const HistoryItem *item);
void notify_botCommandsChanged(UserData *user);
void notify_inlineBotRequesting(bool requesting);
void notify_replyMarkupUpdated(const HistoryItem *item);
@ -480,6 +478,7 @@ private:
using TabbedPanel = ChatHelpers::TabbedPanel;
using TabbedSelector = ChatHelpers::TabbedSelector;
void repaintHistoryItem(not_null<const HistoryItem*> item);
void handlePendingHistoryUpdate();
void fullPeerUpdated(PeerData *peer);
void topBarClick();
@ -519,7 +518,7 @@ private:
// If an empty filepath is found we upload (possible) "image" with (possible) "content".
void uploadFilesAfterConfirmation(const QStringList &files, const QByteArray &content, const QImage &image, std::unique_ptr<FileLoadTask::MediaInformation> information, SendMediaType type, QString caption);
void itemRemoved(HistoryItem *item);
void itemRemoved(not_null<const HistoryItem*> item);
// Updates position of controls around the message field,
// like send button, emoji button and others.
@ -560,7 +559,6 @@ private:
SelectedItemSet _toForward;
Text _toForwardFrom, _toForwardText;
int _toForwardNameVersion = 0;
int _forwardingItemRemovedSubscription = 0;
MsgId _editMsgId = 0;

View File

@ -218,10 +218,10 @@ void WrapWidget::showBackFromStack() {
if (!_historyStack.empty()) {
auto last = std::move(_historyStack.back());
_historyStack.pop_back();
_anotherTabMemento = std::move(last.anotherTab);
showNewContent(
last.section.get(),
params);
_anotherTabMemento = std::move(last.anotherTab);
} else {
controller()->showBackFromStack(params);
}
@ -237,6 +237,7 @@ not_null<Ui::RpWidget*> WrapWidget::topWidget() const {
void WrapWidget::showContent(object_ptr<ContentWidget> content) {
_content = std::move(content);
_content->show();
_anotherTabMemento = nullptr;
finishShowContent();
}

View File

@ -187,8 +187,7 @@ Type InnerWidget::type() const {
void InnerWidget::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
setChildVisibleTopBottom(_list, visibleTop, visibleBottom);
}
bool InnerWidget::showInternal(not_null<Memento*> memento) {

View File

@ -81,9 +81,6 @@ private:
object_ptr<Ui::PlainShadow> _otherTabsShadow = { nullptr };
object_ptr<ListWidget> _list = { nullptr };
int _visibleTop = 0;
int _visibleBottom = 0;
};
} // namespace Media

View File

@ -23,7 +23,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "overview/overview_layout.h"
#include "history/history_media_types.h"
#include "window/themes/window_theme.h"
#include "storage/file_download.h"
#include "lang/lang_keys.h"
#include "auth_session.h"
#include "styles/style_overview.h"
#include "styles/style_info.h"
@ -36,6 +38,21 @@ namespace {
constexpr auto kIdsLimit = 256;
using ItemBase = Layout::ItemBase;
using UniversalMsgId = int32;
UniversalMsgId GetUniversalId(FullMsgId itemId) {
return (itemId.channel != 0)
? itemId.msg
: (itemId.msg - ServerMaxMsgId);
}
UniversalMsgId GetUniversalId(not_null<const HistoryItem*> item) {
return GetUniversalId(item->fullId());
}
UniversalMsgId GetUniversalId(not_null<const ItemBase*> layout) {
return GetUniversalId(layout->getItem()->fullId());
}
} // namespace
@ -55,11 +72,30 @@ public:
return _items.empty();
}
UniversalMsgId minId() const {
Expects(!empty());
return _items.back().first;
}
UniversalMsgId maxId() const {
Expects(!empty());
return _items.front().first;
}
void setTop(int top) {
_top = top;
}
int top() const {
return _top;
}
void resizeToWidth(int newWidth);
int height() const {
return _height;
}
bool removeItem(UniversalMsgId universalId);
base::optional<QRect> findItemRect(
UniversalMsgId universalId) const;
void paint(
Painter &p,
QRect clip,
@ -67,20 +103,33 @@ public:
TimeMs ms) const;
private:
using Items = base::flat_map<
UniversalMsgId,
not_null<ItemBase*>,
std::greater<>>;
int headerHeight() const;
void appendItem(not_null<ItemBase*> item);
void setHeader(not_null<ItemBase*> item);
bool belongsHere(not_null<ItemBase*> item) const;
int countRowHeight(not_null<ItemBase*> item) const;
Items::iterator findItemAfterTop(int top);
Items::const_iterator findItemAfterTop(int top) const;
Items::const_iterator findItemAfterBottom(
Items::const_iterator from,
int bottom) const;
QRect findItemRect(not_null<ItemBase*> item) const;
int recountHeight() const;
void refreshHeight();
Type _type = Type::Photo;
Text _header;
std::vector<not_null<ItemBase*>> _items;
Items _items;
int _itemsLeft = 0;
int _itemsTop = 0;
int _itemWidth = 0;
int _itemsInRow = 1;
int _rowsCount = 0;
mutable int _rowsCount = 0;
int _top = 0;
int _height = 0;
};
@ -120,7 +169,7 @@ bool ListWidget::Section::belongsHere(
not_null<ItemBase*> item) const {
Expects(!_items.empty());
auto date = item->getItem()->date.date();
auto myDate = _items.back()->getItem()->date.date();
auto myDate = _items.back().second->getItem()->date.date();
switch (_type) {
case Type::Photo:
@ -142,25 +191,70 @@ bool ListWidget::Section::belongsHere(
Unexpected("Type in ListWidget::Section::belongsHere()");
}
int ListWidget::Section::countRowHeight(
not_null<ItemBase*> item) const {
switch (_type) {
case Type::Photo:
case Type::Video:
case Type::RoundFile:
return _itemWidth + st::infoMediaSkip;
case Type::VoiceFile:
case Type::File:
case Type::Link:
case Type::MusicFile:
return item->height();
}
Unexpected("Type in ListWidget::Section::countRowHeight()");
void ListWidget::Section::appendItem(not_null<ItemBase*> item) {
_items.emplace(GetUniversalId(item), item);
}
void ListWidget::Section::appendItem(not_null<ItemBase*> item) {
_items.push_back(item);
bool ListWidget::Section::removeItem(UniversalMsgId universalId) {
if (auto it = _items.find(universalId); it != _items.end()) {
it = _items.erase(it);
refreshHeight();
return true;
}
return false;
}
base::optional<QRect> ListWidget::Section::findItemRect(
UniversalMsgId universalId) const {
if (auto it = _items.find(universalId); it != _items.end()) {
return findItemRect(it->second);
}
return base::none;
}
QRect ListWidget::Section::findItemRect(
not_null<ItemBase*> item) const {
auto position = item->position();
auto top = position / _itemsInRow;
auto indexInRow = position % _itemsInRow;
auto left = _itemsLeft
+ indexInRow * (_itemWidth + st::infoMediaSkip);
return QRect(left, top, _itemWidth, item->height());
}
auto ListWidget::Section::findItemAfterTop(
int top) -> Items::iterator {
return base::lower_bound(
_items,
top,
[this](const auto &item, int top) {
auto itemTop = item.second->position() / _itemsInRow;
return (itemTop + item.second->height()) <= top;
});
}
auto ListWidget::Section::findItemAfterTop(
int top) const -> Items::const_iterator {
return base::lower_bound(
_items,
top,
[this](const auto &item, int top) {
auto itemTop = item.second->position() / _itemsInRow;
return (itemTop + item.second->height()) <= top;
});
}
auto ListWidget::Section::findItemAfterBottom(
Items::const_iterator from,
int bottom) const -> Items::const_iterator {
return std::lower_bound(
from,
_items.end(),
bottom,
[this](const auto &item, int bottom) {
auto itemTop = item.second->position() / _itemsInRow;
return itemTop < bottom;
});
}
void ListWidget::Section::paint(
@ -169,9 +263,8 @@ void ListWidget::Section::paint(
int outerWidth,
TimeMs ms) const {
auto baseIndex = 0;
auto top = _itemsTop;
auto header = headerHeight();
if (header) {
if (QRect(0, 0, outerWidth, header).intersects(clip)) {
p.setPen(st::infoMediaHeaderFg);
_header.drawLeftElided(
p,
@ -179,14 +272,14 @@ void ListWidget::Section::paint(
st::infoMediaHeaderPosition.y(),
outerWidth - 2 * st::infoMediaHeaderPosition.x(),
outerWidth);
top += header;
}
auto fromitem = floorclamp(
auto top = header + _itemsTop;
auto fromcol = floorclamp(
clip.x() - _itemsLeft,
_itemWidth,
0,
_itemsInRow);
auto tillitem = ceilclamp(
auto tillcol = ceilclamp(
clip.x() + clip.width() - _itemsLeft,
_itemWidth,
0,
@ -194,35 +287,23 @@ void ListWidget::Section::paint(
Layout::PaintContext context(ms, false);
context.isAfterDate = (header > 0);
// #TODO ranges, binary search for visible slice.
for (auto row = 0; row != _rowsCount; ++row) {
auto rowHeight = countRowHeight(_items[baseIndex]);
auto increment = gsl::finally([&] {
top += rowHeight;
baseIndex += _itemsInRow;
context.isAfterDate = false;
});
if (top >= clip.y() + clip.height()) {
break;
} else if (top + rowHeight <= clip.y()) {
continue;
}
for (auto col = fromitem; col != tillitem; ++col) {
auto index = baseIndex + col;
if (index >= int(_items.size())) {
break;
}
auto item = _items[index];
auto left = _itemsLeft
+ col * (_itemWidth + st::infoMediaSkip);
p.translate(left, top);
auto fromIt = findItemAfterTop(clip.y());
auto tillIt = findItemAfterBottom(
fromIt,
clip.y() + clip.height());
for (auto it = fromIt; it != tillIt; ++it) {
auto item = it->second;
auto rect = findItemRect(item);
context.isAfterDate = (header > 0)
&& (rect.y() <= header + _itemsTop);
if (rect.intersects(clip)) {
p.translate(rect.topLeft());
item->paint(
p,
clip.translated(-left, -top),
clip.translated(-rect.topLeft()),
TextSelection(),
&context);
p.translate(-left, -top);
p.translate(-rect.topLeft());
}
}
}
@ -237,7 +318,6 @@ void ListWidget::Section::resizeToWidth(int newWidth) {
return;
}
_height = headerHeight();
switch (_type) {
case Type::Photo:
case Type::Video:
@ -248,42 +328,70 @@ void ListWidget::Section::resizeToWidth(int newWidth) {
/ (st::infoMediaMinGridSize + st::infoMediaSkip);
_itemWidth = ((newWidth - _itemsLeft) / _itemsInRow)
- st::infoMediaSkip;
auto itemHeight = _itemWidth + st::infoMediaSkip;
_rowsCount = (int(_items.size()) + _itemsInRow - 1)
/ _itemsInRow;
_height += _itemsTop + _rowsCount * itemHeight;
for (auto &item : _items) {
item.second->resizeGetHeight(_itemWidth);
}
} break;
case Type::VoiceFile:
case Type::File:
case Type::MusicFile: {
_itemsLeft = 0;
_itemsTop = 0;
_itemsInRow = 1;
_itemWidth = newWidth;
auto itemHeight = _items.empty() ? 0 : _items.front()->height();
_rowsCount = _items.size();
_height += _rowsCount * itemHeight;
} break;
case Type::MusicFile:
case Type::Link:
_itemsLeft = 0;
_itemsTop = 0;
_itemsInRow = 1;
_itemWidth = newWidth;
auto top = 0;
for (auto item : _items) {
top += item->resizeGetHeight(_itemWidth);
for (auto &item : _items) {
item.second->resizeGetHeight(_itemWidth);
}
_height += top;
break;
}
if (_type != Type::Link) {
for (auto item : _items) {
item->resizeGetHeight(_itemWidth);
refreshHeight();
}
int ListWidget::Section::recountHeight() const {
auto result = headerHeight();
switch (_type) {
case Type::Photo:
case Type::Video:
case Type::RoundFile: {
auto itemHeight = _itemWidth + st::infoMediaSkip;
auto index = 0;
result += _itemsTop;
for (auto &item : _items) {
item.second->setPosition(_itemsInRow * result + index);
if (++index == _itemsInRow) {
result += itemHeight;
index = 0;
}
}
if (_items.size() % _itemsInRow) {
_rowsCount = int(_items.size()) / _itemsInRow + 1;
result += itemHeight;
} else {
_rowsCount = int(_items.size()) / _itemsInRow;
}
} break;
case Type::VoiceFile:
case Type::File:
case Type::MusicFile:
case Type::Link:
for (auto &item : _items) {
item.second->setPosition(result);
result += item.second->height();
}
_rowsCount = _items.size();
break;
}
return result;
}
void ListWidget::Section::refreshHeight() {
_height = recountHeight();
}
ListWidget::ListWidget(
@ -296,13 +404,72 @@ ListWidget::ListWidget(
, _peer(peer)
, _type(type)
, _slice(sliceKey()) {
start();
refreshViewer();
}
void ListWidget::start() {
ObservableViewer(*Window::Theme::Background())
| rpl::start_with_next([this](const auto &update) {
if (update.paletteChanged()) {
invalidatePaletteCache();
}
}, lifetime());
ObservableViewer(Auth().downloader().taskFinished())
| rpl::start_with_next([this] { update(); }, lifetime());
Auth().data().itemLayoutChanged()
| rpl::start_with_next([this](auto item) {
if ((item == App::mousedItem())
|| (item == App::hoveredItem())
|| (item == App::hoveredLinkItem())) {
updateSelected();
}
}, lifetime());
Auth().data().itemRemoved()
| rpl::start_with_next([this](auto item) {
itemRemoved(item);
}, lifetime());
Auth().data().itemRepaintRequest()
| rpl::start_with_next([this](auto item) {
repaintItem(item);
}, lifetime());
}
void ListWidget::itemRemoved(not_null<const HistoryItem*> item) {
if (myItem(item)) {
auto universalId = GetUniversalId(item);
auto sectionIt = findSectionByItem(universalId);
if (sectionIt != _sections.end()) {
if (sectionIt->removeItem(universalId)) {
auto top = sectionIt->top();
if (sectionIt->empty()) {
_sections.erase(sectionIt);
}
refreshHeight();
}
}
}
}
void ListWidget::repaintItem(not_null<const HistoryItem*> item) {
if (myItem(item)) {
repaintItem(GetUniversalId(item));
}
}
void ListWidget::repaintItem(UniversalMsgId universalId) {
auto sectionIt = findSectionByItem(universalId);
if (sectionIt != _sections.end()) {
if (auto rect = sectionIt->findItemRect(universalId)) {
auto top = padding().top() + sectionIt->top();
rtlupdate(rect->translated(0, top));
}
}
}
bool ListWidget::myItem(not_null<const HistoryItem*> item) const {
auto peer = item->history()->peer;
return (_peer == peer || _peer == peer->migrateTo());
}
void ListWidget::invalidatePaletteCache() {
@ -314,9 +481,7 @@ void ListWidget::invalidatePaletteCache() {
SharedMediaMergedSlice::Key ListWidget::sliceKey() const {
auto universalId = _universalAroundId;
using Key = SharedMediaMergedSlice::Key;
if (auto migrateTo = _peer->migrateTo()) {
return Key(migrateTo->id, _peer->id, _type, universalId);
} else if (auto migrateFrom = _peer->migrateFrom()) {
if (auto migrateFrom = _peer->migrateFrom()) {
return Key(_peer->id, migrateFrom->id, _type, universalId);
}
return Key(_peer->id, 0, _type, universalId);
@ -338,11 +503,14 @@ int ListWidget::countIdsLimit() const {
}
ItemBase *ListWidget::getLayout(const FullMsgId &itemId) {
auto it = _layouts.find(itemId);
auto universalId = GetUniversalId(itemId);
auto it = _layouts.find(universalId);
if (it == _layouts.end()) {
if (auto layout = createLayout(itemId, _type)) {
layout->initDimensions();
it = _layouts.emplace(itemId, std::move(layout)).first;
it = _layouts.emplace(
universalId,
std::move(layout)).first;
} else {
return nullptr;
}
@ -372,34 +540,37 @@ std::unique_ptr<ItemBase> ListWidget::createLayout(
}
return nullptr;
};
auto &fileSt = st::overviewFileLayout;
using namespace Layout;
switch (type) {
case Type::Photo:
if (auto photo = getPhoto()) {
return std::make_unique<Layout::Photo>(photo, item);
return std::make_unique<Photo>(item, photo);
}
return nullptr;
case Type::Video:
if (auto file = getFile()) {
return std::make_unique<Layout::Video>(file, item);
return std::make_unique<Video>(item, file);
}
return nullptr;
case Type::File:
if (auto file = getFile()) {
return std::make_unique<Layout::Document>(file, item, st::overviewFileLayout);
return std::make_unique<Document>(item, file, fileSt);
}
return nullptr;
case Type::MusicFile:
if (auto file = getFile()) {
return std::make_unique<Layout::Document>(file, item, st::overviewFileLayout);
return std::make_unique<Document>(item, file, fileSt);
}
return nullptr;
case Type::VoiceFile:
if (auto file = getFile()) {
return std::make_unique<Layout::Voice>(file, item, st::overviewFileLayout);
return std::make_unique<Voice>(item, file, fileSt);
}
return nullptr;
case Type::Link:
return std::make_unique<Layout::Link>(item->getMedia(), item);
return std::make_unique<Link>(item, item->getMedia());
case Type::RoundFile:
return nullptr;
}
@ -438,37 +609,60 @@ void ListWidget::markLayoutsStale() {
}
int ListWidget::resizeGetHeight(int newWidth) {
for (auto &section : _sections) {
section.resizeToWidth(newWidth);
if (newWidth > 0) {
for (auto &section : _sections) {
section.resizeToWidth(newWidth);
}
}
return recountHeight();
}
void ListWidget::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
if (width() <= 0) {
return;
}
}
QMargins ListWidget::padding() const {
return st::infoMediaMargin;
}
void ListWidget::paintEvent(QPaintEvent *e) {
Painter p(this);
auto outerWidth = width();
auto clip = e->rect();
auto ms = getms();
auto top = st::infoMediaMargin.top();
p.translate(0, top);
clip = clip.translated(0, -top);
for (auto &section : _sections) {
section.paint(p, clip, outerWidth, ms);
auto height = section.height();
p.translate(0, height);
clip = clip.translated(0, -height);
auto fromSectionIt = findSectionAfterTop(clip.y());
auto tillSectionIt = findSectionAfterBottom(
fromSectionIt,
clip.y() + clip.height());
for (auto it = fromSectionIt; it != tillSectionIt; ++it) {
auto top = it->top();
p.translate(0, top);
it->paint(p, clip.translated(0, -top), outerWidth, ms);
p.translate(0, -top);
}
}
void ListWidget::refreshHeight() {
resize(width(), recountHeight());
}
int ListWidget::recountHeight() {
auto result = 0;
auto cachedPadding = padding();
auto result = cachedPadding.top();
for (auto &section : _sections) {
section.setTop(result);
result += section.height();
}
return st::infoMediaMargin.top()
+ result
+ st::infoMediaMargin.bottom();
return result
+ cachedPadding.bottom();
}
void ListWidget::updateSelected() {
}
void ListWidget::clearStaleLayouts() {
@ -481,6 +675,47 @@ void ListWidget::clearStaleLayouts() {
}
}
auto ListWidget::findSectionByItem(
UniversalMsgId universalId) -> std::vector<Section>::iterator {
return base::lower_bound(
_sections,
universalId,
[](const Section &section, int universalId) {
return section.minId() > universalId;
});
}
auto ListWidget::findSectionAfterTop(
int top) -> std::vector<Section>::iterator {
return base::lower_bound(
_sections,
top,
[](const Section &section, int top) {
return (section.top() + section.height()) <= top;
});
}
auto ListWidget::findSectionAfterTop(
int top) const -> std::vector<Section>::const_iterator {
return base::lower_bound(
_sections,
top,
[](const Section &section, int top) {
return (section.top() + section.height()) <= top;
});
}
auto ListWidget::findSectionAfterBottom(
std::vector<Section>::const_iterator from,
int bottom) const -> std::vector<Section>::const_iterator {
return std::lower_bound(
from,
_sections.end(),
bottom,
[](const Section &section, int bottom) {
return section.top() < bottom;
});
}
ListWidget::~ListWidget() = default;
} // namespace Media

View File

@ -60,12 +60,34 @@ public:
protected:
int resizeGetHeight(int newWidth) override;
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintEvent(QPaintEvent *e) override;
private:
using ItemBase = Overview::Layout::ItemBase;
using UniversalMsgId = int32;
struct CachedItem {
CachedItem(std::unique_ptr<ItemBase> item);
~CachedItem();
std::unique_ptr<ItemBase> item;
bool stale = false;
};
class Section;
void start();
int recountHeight();
void refreshHeight();
QMargins padding() const;
void updateSelected();
bool myItem(not_null<const HistoryItem*> item) const;
void repaintItem(not_null<const HistoryItem*> item);
void repaintItem(UniversalMsgId msgId);
void itemRemoved(not_null<const HistoryItem*> item);
void refreshViewer();
void invalidatePaletteCache();
@ -79,24 +101,23 @@ private:
void markLayoutsStale();
void clearStaleLayouts();
std::vector<Section>::iterator findSectionByItem(
UniversalMsgId universalId);
std::vector<Section>::iterator findSectionAfterTop(int top);
std::vector<Section>::const_iterator findSectionAfterTop(
int top) const;
std::vector<Section>::const_iterator findSectionAfterBottom(
std::vector<Section>::const_iterator from,
int bottom) const;
not_null<Window::Controller*> _controller;
not_null<PeerData*> _peer;
Type _type = Type::Photo;
MsgId _universalAroundId = ServerMaxMsgId - 1;
UniversalMsgId _universalAroundId = ServerMaxMsgId - 1;
SharedMediaMergedSlice _slice;
struct CachedItem {
CachedItem(std::unique_ptr<ItemBase> item);
~CachedItem();
std::unique_ptr<ItemBase> item;
bool stale = false;
};
std::map<FullMsgId, CachedItem> _layouts;
class Section;
std::map<UniversalMsgId, CachedItem> _layouts;
std::vector<Section> _sections;
rpl::lifetime _viewerLifetime;

View File

@ -935,31 +935,6 @@ void MainWidget::notify_migrateUpdated(PeerData *peer) {
_history->notify_migrateUpdated(peer);
}
void MainWidget::ui_repaintHistoryItem(not_null<const HistoryItem*> item) {
if (item->isLogEntry()) {
Auth().data().repaintLogEntry().notify(item, true);
} else {
_history->ui_repaintHistoryItem(item);
if (item->history()->lastMsg == item) {
item->history()->updateChatListEntry();
}
_playerPlaylist->ui_repaintHistoryItem(item);
_playerPanel->ui_repaintHistoryItem(item);
}
if (_overview) _overview->ui_repaintHistoryItem(item);
if (auto last = currentFloatPlayer()) {
last->widget->ui_repaintHistoryItem(item);
}
}
void MainWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
_history->notify_historyItemLayoutChanged(item);
if (_overview) _overview->notify_historyItemLayoutChanged(item);
if (auto last = currentFloatPlayer()) {
last->widget->ui_repaintHistoryItem(item);
}
}
void MainWidget::notify_historyMuteUpdated(History *history) {
_dialogs->notify_historyMuteUpdated(history);
}
@ -1873,7 +1848,7 @@ void MainWidget::handleAudioUpdate(const AudioMsgId &audioId) {
}
if (auto item = App::histItemById(audioId.contextId())) {
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
item->audioTrackUpdated();
}
if (auto items = InlineBots::Layout::documentItems()) {
@ -2046,7 +2021,7 @@ void MainWidget::documentLoadProgress(DocumentData *document) {
auto i = items.constFind(document);
if (i != items.cend()) {
for_const (auto item, i.value()) {
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
}
Auth().documentUpdated.notify(document, true);
@ -5301,7 +5276,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
msgRow->history()->unregSendAction(App::self());
}
App::historyRegItem(msgRow);
Ui::repaintHistoryItem(msgRow);
Auth().data().requestItemRepaint(msgRow);
}
}
App::historyUnregRandom(d.vrandom_id.v);
@ -5329,7 +5304,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
if (auto item = App::histItemById(channel, msgId.v)) {
if (item->isMediaUnread()) {
item->markMediaRead();
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
} else {
// Perhaps it was an unread mention!

View File

@ -340,7 +340,6 @@ public:
void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col);
void ui_repaintHistoryItem(not_null<const HistoryItem*> item);
void ui_showPeerHistory(
PeerId peer,
const SectionShow &params,
@ -355,7 +354,6 @@ public:
void notify_userIsBotChanged(UserData *bot);
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
void notify_migrateUpdated(PeerData *peer);
void notify_historyItemLayoutChanged(const HistoryItem *item);
void notify_historyMuteUpdated(History *history);
bool cmd_search();

View File

@ -21,17 +21,23 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "media/player/media_player_float.h"
#include "data/data_document.h"
#include "styles/style_media_player.h"
#include "history/history_media.h"
#include "media/media_clip_reader.h"
#include "media/view/media_clip_playback.h"
#include "media/media_audio.h"
#include "auth_session.h"
#include "styles/style_media_player.h"
#include "styles/style_history.h"
namespace Media {
namespace Player {
Float::Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible)> toggleCallback, base::lambda<void(bool closed)> draggedCallback) : TWidget(parent)
Float::Float(
QWidget *parent,
HistoryItem *item,
base::lambda<void(bool visible)> toggleCallback,
base::lambda<void(bool closed)> draggedCallback)
: RpWidget(parent)
, _item(item)
, _toggleCallback(std::move(toggleCallback))
, _draggedCallback(std::move(draggedCallback)) {
@ -48,11 +54,25 @@ Float::Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible)
prepareShadow();
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
if (_item == item) {
detach();
}
});
// #TODO rpl::merge
Auth().data().itemLayoutChanged()
| rpl::start_with_next([this](auto item) {
if (_item == item) {
repaintItem();
}
}, lifetime());
Auth().data().itemRepaintRequest()
| rpl::start_with_next([this](auto item) {
if (_item == item) {
repaintItem();
}
}, lifetime());
Auth().data().itemRemoved()
| rpl::start_with_next([this](auto item) {
if (_item == item) {
detach();
}
}, lifetime());
setCursor(style::cur_pointer);
}

View File

@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/rp_widget.h"
namespace Media {
namespace Clip {
class Playback;
@ -27,7 +29,7 @@ class Playback;
namespace Player {
class Float : public TWidget, private base::Subscriber {
class Float : public Ui::RpWidget, private base::Subscriber {
public:
Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible)> toggleCallback, base::lambda<void(bool closed)> draggedCallback);
@ -59,11 +61,6 @@ public:
finishDrag(false);
}
}
void ui_repaintHistoryItem(not_null<const HistoryItem*> item) {
if (item == _item) {
repaintItem();
}
}
protected:
void paintEvent(QPaintEvent *e) override;

View File

@ -24,17 +24,25 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "overview/overview_layout.h"
#include "styles/style_media_player.h"
#include "history/history_media.h"
#include "auth_session.h"
namespace Media {
namespace Player {
ListWidget::ListWidget(QWidget *parent) : TWidget(parent) {
ListWidget::ListWidget(QWidget *parent) : RpWidget(parent) {
setMouseTracking(true);
playlistUpdated();
subscribe(instance()->playlistChangedNotifier(), [this](AudioMsgId::Type type) { playlistUpdated(); });
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
itemRemoved(item);
});
subscribe(
instance()->playlistChangedNotifier(),
[this](AudioMsgId::Type type) { playlistUpdated(); });
Auth().data().itemRemoved()
| rpl::start_with_next(
[this](auto item) { itemRemoved(item); },
lifetime());
Auth().data().itemRepaintRequest()
| rpl::start_with_next(
[this](auto item) { repaintItem(item); },
lifetime());
}
ListWidget::~ListWidget() {
@ -118,10 +126,6 @@ void ListWidget::mouseMoveEvent(QMouseEvent *e) {
}
}
void ListWidget::ui_repaintHistoryItem(not_null<const HistoryItem*> item) {
repaintItem(item);
}
void ListWidget::repaintItem(const HistoryItem *item) {
if (!item) return;
@ -139,7 +143,7 @@ void ListWidget::repaintItem(const HistoryItem *item) {
}
}
void ListWidget::itemRemoved(HistoryItem *item) {
void ListWidget::itemRemoved(not_null<const HistoryItem *> item) {
auto layoutIt = _layouts.find(item->fullId());
if (layoutIt != _layouts.cend()) {
auto layout = layoutIt.value();
@ -204,7 +208,7 @@ void ListWidget::playlistUpdated() {
if (auto item = App::histItemById(msgId)) {
if (auto media = item->getMedia()) {
if (media->type() == MediaTypeMusicFile) {
layoutIt = _layouts.insert(msgId, new Overview::Layout::Document(media->getDocument(), item, st::mediaPlayerFileLayout));
layoutIt = _layouts.insert(msgId, new Overview::Layout::Document(item, media->getDocument(), st::mediaPlayerFileLayout));
layoutIt.value()->initDimensions();
}
}

View File

@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/rp_widget.h"
namespace Overview {
namespace Layout {
class Document;
@ -29,12 +31,10 @@ class Document;
namespace Media {
namespace Player {
class ListWidget : public TWidget, private base::Subscriber {
class ListWidget : public Ui::RpWidget, private base::Subscriber {
public:
ListWidget(QWidget *parent);
void ui_repaintHistoryItem(not_null<const HistoryItem*> item);
QRect getCurrentTrackGeometry() const;
~ListWidget();
@ -48,7 +48,7 @@ protected:
int resizeGetHeight(int newWidth) override;
private:
void itemRemoved(HistoryItem *item);
void itemRemoved(not_null<const HistoryItem*> item);
int marginTop() const;
void repaintItem(const HistoryItem *item);
void playlistUpdated();

View File

@ -96,12 +96,6 @@ void Panel::updateControlsGeometry() {
}
}
void Panel::ui_repaintHistoryItem(not_null<const HistoryItem*> item) {
if (auto list = static_cast<ListWidget*>(_scroll->widget())) {
list->ui_repaintHistoryItem(item);
}
}
int Panel::bestPositionFor(int left) const {
left -= contentLeft();
left -= st::mediaPlayerFileLayout.songPadding.left();

View File

@ -52,8 +52,6 @@ public:
void setPinCallback(ButtonCallback &&callback);
void setCloseCallback(ButtonCallback &&callback);
void ui_repaintHistoryItem(not_null<const HistoryItem*> item);
int bestPositionFor(int left) const;
protected:

View File

@ -1023,7 +1023,7 @@ base::optional<MediaView::SharedMediaKey> MediaView::sharedMediaKey() const {
_history->peer->id,
_migrated ? _migrated->peer->id : 0,
type,
(_msgid.channel == _history->channelId()) ? _msgid.msg : -_msgid.msg };
(_msgid.channel == _history->channelId()) ? _msgid.msg : (_msgid.msg - ServerMaxMsgId) };
};
return
sharedMediaType()

View File

@ -67,30 +67,40 @@ TextWithEntities ComposeNameWithEntities(DocumentData *document) {
} // namespace
void ItemBase::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
App::hoveredLinkItem(active ? _parent : nullptr);
Ui::repaintHistoryItem(_parent);
App::hoveredLinkItem(active ? _parent.get() : nullptr);
Auth().data().requestItemRepaint(_parent);
}
void ItemBase::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
App::pressedLinkItem(pressed ? _parent : nullptr);
Ui::repaintHistoryItem(_parent);
App::pressedLinkItem(pressed ? _parent.get() : nullptr);
Auth().data().requestItemRepaint(_parent);
}
void RadialProgressItem::setDocumentLinks(DocumentData *document) {
ClickHandlerPtr save;
if (document->voice()) {
save.reset(new DocumentOpenClickHandler(document));
} else {
save.reset(new DocumentSaveClickHandler(document));
}
setLinks(MakeShared<DocumentOpenClickHandler>(document), std::move(save), MakeShared<DocumentCancelClickHandler>(document));
void RadialProgressItem::setDocumentLinks(
not_null<DocumentData*> document) {
auto createSaveHandler = [](
not_null<DocumentData*> document
) -> ClickHandlerPtr {
if (document->voice()) {
return MakeShared<DocumentOpenClickHandler>(document);
}
return MakeShared<DocumentSaveClickHandler>(document);
};
setLinks(
MakeShared<DocumentOpenClickHandler>(document),
createSaveHandler(document),
MakeShared<DocumentCancelClickHandler>(document));
}
void RadialProgressItem::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
ItemBase::clickHandlerActiveChanged(action, active);
if (action == _openl || action == _savel || action == _cancell) {
if (iconAnimated()) {
_a_iconOver.start([this] { Ui::repaintHistoryItem(_parent); }, active ? 0. : 1., active ? 1. : 0., st::msgFileOverDuration);
_a_iconOver.start(
[this] { Auth().data().requestItemRepaint(_parent); },
active ? 0. : 1.,
active ? 1. : 0.,
st::msgFileOverDuration);
}
}
}
@ -103,7 +113,7 @@ void RadialProgressItem::setLinks(ClickHandlerPtr &&openl, ClickHandlerPtr &&sav
void RadialProgressItem::step_radial(TimeMs ms, bool timer) {
if (timer) {
Ui::repaintHistoryItem(_parent);
Auth().data().requestItemRepaint(_parent);
} else {
_radial->update(dataProgress(), dataFinished(), ms);
if (!_radial->animating()) {
@ -221,9 +231,12 @@ void PhotoVideoCheckbox::startAnimation() {
_pression.start(_updateCallback, showPressed ? 0. : 1., showPressed ? 1. : 0., st::overviewCheck.duration);
}
Photo::Photo(PhotoData *photo, HistoryItem *parent) : ItemBase(parent)
Photo::Photo(
not_null<HistoryItem*> parent,
not_null<PhotoData*> photo)
: ItemBase(parent)
, _data(photo)
, _link(new PhotoOpenClickHandler(photo)) {
, _link(MakeShared<PhotoOpenClickHandler>(photo)) {
}
void Photo::initDimensions() {
@ -289,7 +302,7 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
void Photo::ensureCheckboxCreated() {
if (!_check) _check = std::make_unique<PhotoVideoCheckbox>([this] {
Ui::repaintHistoryItem(_parent);
Auth().data().requestItemRepaint(_parent);
});
}
@ -319,7 +332,10 @@ void Photo::invalidateCache() {
}
}
Video::Video(DocumentData *video, HistoryItem *parent) : RadialProgressItem(parent)
Video::Video(
not_null<HistoryItem*> parent,
not_null<DocumentData*> video)
: RadialProgressItem(parent)
, _data(video)
, _duration(formatDurationText(_data->duration()))
, _thumbLoaded(false) {
@ -449,7 +465,7 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
void Video::ensureCheckboxCreated() {
if (!_check) _check = std::make_unique<PhotoVideoCheckbox>([this] {
Ui::repaintHistoryItem(_parent);
Auth().data().requestItemRepaint(_parent);
});
}
@ -521,9 +537,13 @@ void Video::updateStatusText() {
}
}
Voice::Voice(DocumentData *voice, HistoryItem *parent, const style::OverviewFileLayout &st) : RadialProgressItem(parent)
Voice::Voice(
not_null<HistoryItem*> parent,
not_null<DocumentData*> voice,
const style::OverviewFileLayout &st)
: RadialProgressItem(parent)
, _data(voice)
, _namel(new DocumentOpenClickHandler(_data))
, _namel(MakeShared<DocumentOpenClickHandler>(_data))
, _st(st) {
AddComponents(Info::Bit());
@ -722,10 +742,14 @@ bool Voice::updateStatusText() {
return showPause;
}
Document::Document(DocumentData *document, HistoryItem *parent, const style::OverviewFileLayout &st) : RadialProgressItem(parent)
Document::Document(
not_null<HistoryItem*> parent,
not_null<DocumentData*> document,
const style::OverviewFileLayout &st)
: RadialProgressItem(parent)
, _data(document)
, _msgl(goToMessageClickHandler(parent))
, _namel(new DocumentOpenClickHandler(_data))
, _namel(MakeShared<DocumentOpenClickHandler>(_data))
, _st(st)
, _date(langDateTime(date(_data->date)))
, _datew(st::normalFont->width(_date))
@ -1037,7 +1061,10 @@ bool Document::updateStatusText() {
return showPause;
}
Link::Link(HistoryMedia *media, HistoryItem *parent) : ItemBase(parent) {
Link::Link(
not_null<HistoryItem*> parent,
HistoryMedia *media)
: ItemBase(parent) {
AddComponents(Info::Bit());
auto textWithEntities = _parent->originalText();

View File

@ -66,7 +66,14 @@ public:
class ItemBase : public AbstractItem {
public:
ItemBase(HistoryItem *parent) : _parent(parent) {
ItemBase(not_null<HistoryItem*> parent) : _parent(parent) {
}
void setPosition(int position) {
_position = position;
}
int position() const {
return _position;
}
ItemBase *toMediaItem() final override {
@ -83,13 +90,14 @@ public:
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
protected:
HistoryItem *_parent;
not_null<HistoryItem*> _parent = nullptr;
int _position = 0;
};
class RadialProgressItem : public ItemBase {
public:
RadialProgressItem(HistoryItem *parent) : ItemBase(parent) {
RadialProgressItem(not_null<HistoryItem*> parent) : ItemBase(parent) {
}
RadialProgressItem(const RadialProgressItem &other) = delete;
@ -99,8 +107,11 @@ public:
protected:
ClickHandlerPtr _openl, _savel, _cancell;
void setLinks(ClickHandlerPtr &&openl, ClickHandlerPtr &&savel, ClickHandlerPtr &&cancell);
void setDocumentLinks(DocumentData *document);
void setLinks(
ClickHandlerPtr &&openl,
ClickHandlerPtr &&savel,
ClickHandlerPtr &&cancell);
void setDocumentLinks(not_null<DocumentData*> document);
void step_radial(TimeMs ms, bool timer);
@ -171,7 +182,9 @@ class PhotoVideoCheckbox;
class Photo : public ItemBase {
public:
Photo(PhotoData *photo, HistoryItem *parent);
Photo(
not_null<HistoryItem*> parent,
not_null<PhotoData*> photo);
void initDimensions() override;
int32 resizeGetHeight(int32 width) override;
@ -188,7 +201,7 @@ private:
std::unique_ptr<PhotoVideoCheckbox> _check;
PhotoData *_data;
not_null<PhotoData*> _data;
ClickHandlerPtr _link;
QPixmap _pix;
@ -198,7 +211,9 @@ private:
class Video : public RadialProgressItem {
public:
Video(DocumentData *video, HistoryItem *parent);
Video(
not_null<HistoryItem*> parent,
not_null<DocumentData*> video);
void initDimensions() override;
int32 resizeGetHeight(int32 width) override;
@ -221,7 +236,7 @@ private:
std::unique_ptr<PhotoVideoCheckbox> _check;
DocumentData *_data;
not_null<DocumentData*> _data;
StatusText _status;
QString _duration;
@ -234,7 +249,10 @@ private:
class Voice : public RadialProgressItem {
public:
Voice(DocumentData *voice, HistoryItem *parent, const style::OverviewFileLayout &st);
Voice(
not_null<HistoryItem*> parent,
not_null<DocumentData*> voice,
const style::OverviewFileLayout &st);
void initDimensions() override;
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
@ -247,7 +265,7 @@ protected:
bool iconAnimated() const override;
private:
DocumentData *_data;
not_null<DocumentData*> _data;
StatusText _status;
ClickHandlerPtr _namel;
@ -263,7 +281,10 @@ private:
class Document : public RadialProgressItem {
public:
Document(DocumentData *document, HistoryItem *parent, const style::OverviewFileLayout &st);
Document(
not_null<HistoryItem*> parent,
not_null<DocumentData*> document,
const style::OverviewFileLayout &st);
void initDimensions() override;
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
@ -280,7 +301,7 @@ protected:
bool iconAnimated() const override;
private:
DocumentData *_data;
not_null<DocumentData*> _data;
StatusText _status;
ClickHandlerPtr _msgl, _namel;
@ -301,7 +322,9 @@ private:
class Link : public ItemBase {
public:
Link(HistoryMedia *media, HistoryItem *parent);
Link(
not_null<HistoryItem*> parent,
HistoryMedia *media);
void initDimensions() override;
int32 resizeGetHeight(int32 width) override;

View File

@ -67,9 +67,6 @@ OverviewInner::OverviewInner(OverviewWidget *overview, Ui::ScrollArea *scroll, P
, _itemsToBeLoaded(LinksOverviewPerPage * 2)
, _width(st::columnMinimalWidthMain) {
subscribe(Auth().downloader().taskFinished(), [this] { update(); });
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
itemRemoved(item);
});
resize(_width, st::windowMinHeight);
@ -1891,34 +1888,34 @@ Overview::Layout::ItemBase *OverviewInner::layoutPrepare(HistoryItem *item) {
if (_type == OverviewPhotos) {
if (media && media->type() == MediaTypePhoto) {
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
i = _layoutItems.insert(item, new Overview::Layout::Photo(static_cast<HistoryPhoto*>(media)->photo(), item));
i = _layoutItems.insert(item, new Overview::Layout::Photo(item, static_cast<HistoryPhoto*>(media)->photo()));
i.value()->initDimensions();
}
}
} else if (_type == OverviewVideos) {
if (media && media->type() == MediaTypeVideo) {
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
i = _layoutItems.insert(item, new Overview::Layout::Video(media->getDocument(), item));
i = _layoutItems.insert(item, new Overview::Layout::Video(item, media->getDocument()));
i.value()->initDimensions();
}
}
} else if (_type == OverviewVoiceFiles) {
if (media && (media->type() == MediaTypeVoiceFile)) {
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
i = _layoutItems.insert(item, new Overview::Layout::Voice(media->getDocument(), item, st::overviewFileLayout));
i = _layoutItems.insert(item, new Overview::Layout::Voice(item, media->getDocument(), st::overviewFileLayout));
i.value()->initDimensions();
}
}
} else if (_type == OverviewFiles || _type == OverviewMusicFiles) {
if (media && (media->type() == MediaTypeFile || media->type() == MediaTypeMusicFile || media->type() == MediaTypeGif)) {
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
i = _layoutItems.insert(item, new Overview::Layout::Document(media->getDocument(), item, st::overviewFileLayout));
i = _layoutItems.insert(item, new Overview::Layout::Document(item, media->getDocument(), st::overviewFileLayout));
i.value()->initDimensions();
}
}
} else if (_type == OverviewLinks) {
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
i = _layoutItems.insert(item, new Overview::Layout::Link(media, item));
i = _layoutItems.insert(item, new Overview::Layout::Link(item, media));
i.value()->initDimensions();
}
}
@ -2293,18 +2290,6 @@ void OverviewWidget::grabFinish() {
_topShadow->show();
}
void OverviewWidget::ui_repaintHistoryItem(not_null<const HistoryItem*> item) {
if (peer() == item->history()->peer || migratePeer() == item->history()->peer) {
_inner->repaintItem(item);
}
}
void OverviewWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
if (peer() == item->history()->peer || migratePeer() == item->history()->peer) {
_inner->onUpdateSelected();
}
}
SelectedItemSet OverviewWidget::getSelectedItems() const {
return _inner->getSelectedItems();
}

View File

@ -352,10 +352,6 @@ public:
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
void ui_repaintHistoryItem(not_null<const HistoryItem*> item);
void notify_historyItemLayoutChanged(const HistoryItem *item);
~OverviewWidget();
protected:

View File

@ -3162,7 +3162,7 @@ public:
auto i = items.constFind(_doc);
if (i != items.cend()) {
for_const (auto item, i.value()) {
Ui::repaintHistoryItem(item);
Auth().data().requestItemRepaint(item);
}
}
}

View File

@ -33,7 +33,6 @@ public:
void remove(SharedMediaRemoveOne &&query);
void remove(SharedMediaRemoveAll &&query);
rpl::producer<SharedMediaResult> query(SharedMediaQuery &&query) const;
rpl::producer<SharedMediaSliceUpdate> sharedMediaSliceUpdated() const;
rpl::producer<SharedMediaRemoveOne> sharedMediaOneRemoved() const;
rpl::producer<SharedMediaRemoveAll> sharedMediaAllRemoved() const;
@ -43,7 +42,6 @@ public:
void remove(UserPhotosRemoveOne &&query);
void remove(UserPhotosRemoveAfter &&query);
rpl::producer<UserPhotosResult> query(UserPhotosQuery &&query) const;
rpl::producer<UserPhotosSliceUpdate> userPhotosSliceUpdated() const;
private:

View File

@ -122,11 +122,11 @@ private:
QRect _bar;
};
class SplittedWidget : public TWidget {
class SplittedWidget : public Ui::RpWidget {
Q_OBJECT
public:
SplittedWidget(QWidget *parent) : TWidget(parent) {
SplittedWidget(QWidget *parent) : RpWidget(parent) {
setAttribute(Qt::WA_OpaquePaintEvent);
}
void setHeight(int32 newHeight) {