mirror of https://github.com/procxx/kepka.git
Support item repaint in Info media overview.
This commit is contained in:
parent
fdd89d65ca
commit
65cc4d3fbc
|
@ -1661,7 +1661,7 @@ void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) {
|
||||||
if (auto item = App::histItemById(NoChannel, msgId.v)) {
|
if (auto item = App::histItemById(NoChannel, msgId.v)) {
|
||||||
if (item->isMediaUnread()) {
|
if (item->isMediaUnread()) {
|
||||||
item->markMediaRead();
|
item->markMediaRead();
|
||||||
Ui::repaintHistoryItem(item);
|
Auth().data().requestItemRepaint(item);
|
||||||
|
|
||||||
if (item->out() && item->history()->peer->isUser()) {
|
if (item->out() && item->history()->peer->isUser()) {
|
||||||
auto when = App::main()->requestingDifference() ? 0 : unixtime();
|
auto when = App::main()->requestingDifference() ? 0 : unixtime();
|
||||||
|
|
|
@ -1954,8 +1954,10 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Auth().notifications().clearFromItem(item);
|
Auth().notifications().clearFromItem(item);
|
||||||
if (Global::started() && !App::quitting()) {
|
if (Global::started()
|
||||||
Global::RefItemRemoved().notify(item, true);
|
&& !App::quitting()
|
||||||
|
&& AuthSession::Exists()) {
|
||||||
|
Auth().data().markItemRemoved(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,9 +66,6 @@ public:
|
||||||
base::Observable<not_null<History*>> &historyCleared() {
|
base::Observable<not_null<History*>> &historyCleared() {
|
||||||
return _historyCleared;
|
return _historyCleared;
|
||||||
}
|
}
|
||||||
base::Observable<not_null<const HistoryItem*>> &repaintLogEntry() {
|
|
||||||
return _repaintLogEntry;
|
|
||||||
}
|
|
||||||
base::Observable<void> &pendingHistoryResize() {
|
base::Observable<void> &pendingHistoryResize() {
|
||||||
return _pendingHistoryResize;
|
return _pendingHistoryResize;
|
||||||
}
|
}
|
||||||
|
@ -79,6 +76,24 @@ public:
|
||||||
base::Observable<ItemVisibilityQuery> &queryItemVisibility() {
|
base::Observable<ItemVisibilityQuery> &queryItemVisibility() {
|
||||||
return _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) {
|
void copyFrom(const AuthSessionData &other) {
|
||||||
_variables = other._variables;
|
_variables = other._variables;
|
||||||
|
@ -187,9 +202,12 @@ private:
|
||||||
base::Observable<void> _stickersUpdated;
|
base::Observable<void> _stickersUpdated;
|
||||||
base::Observable<void> _savedGifsUpdated;
|
base::Observable<void> _savedGifsUpdated;
|
||||||
base::Observable<not_null<History*>> _historyCleared;
|
base::Observable<not_null<History*>> _historyCleared;
|
||||||
base::Observable<not_null<const HistoryItem*>> _repaintLogEntry;
|
|
||||||
base::Observable<void> _pendingHistoryResize;
|
base::Observable<void> _pendingHistoryResize;
|
||||||
base::Observable<ItemVisibilityQuery> _queryItemVisibility;
|
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;
|
rpl::event_stream<bool> _thirdSectionInfoEnabledValue;
|
||||||
bool _tabbedReplacedWithInfo = false;
|
bool _tabbedReplacedWithInfo = false;
|
||||||
rpl::event_stream<bool> _tabbedReplacedWithInfoValue;
|
rpl::event_stream<bool> _tabbedReplacedWithInfoValue;
|
||||||
|
|
|
@ -324,6 +324,10 @@ public:
|
||||||
void peerListSearchAddRow(not_null<PeerData*> peer) override;
|
void peerListSearchAddRow(not_null<PeerData*> peer) override;
|
||||||
void peerListSearchRefreshRows() override;
|
void peerListSearchRefreshRows() override;
|
||||||
|
|
||||||
|
rpl::lifetime &lifetime() {
|
||||||
|
return _lifetime;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~PeerListController() = default;
|
virtual ~PeerListController() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -351,6 +355,8 @@ private:
|
||||||
PeerListDelegate *_delegate = nullptr;
|
PeerListDelegate *_delegate = nullptr;
|
||||||
std::unique_ptr<PeerListSearchController> _searchController = nullptr;
|
std::unique_ptr<PeerListSearchController> _searchController = nullptr;
|
||||||
|
|
||||||
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PeerListContent
|
class PeerListContent
|
||||||
|
|
|
@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "calls/calls_instance.h"
|
#include "calls/calls_instance.h"
|
||||||
#include "history/history_media_types.h"
|
#include "history/history_media_types.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace Calls {
|
namespace Calls {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -39,7 +40,7 @@ constexpr auto kPerPageCount = 100;
|
||||||
|
|
||||||
class BoxController::Row : public PeerListRow {
|
class BoxController::Row : public PeerListRow {
|
||||||
public:
|
public:
|
||||||
Row(HistoryItem *item);
|
Row(not_null<HistoryItem*> item);
|
||||||
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Out,
|
Out,
|
||||||
|
@ -47,7 +48,7 @@ public:
|
||||||
Missed,
|
Missed,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool canAddItem(HistoryItem *item) const {
|
bool canAddItem(not_null<const HistoryItem*> item) const {
|
||||||
return (ComputeType(item) == _type && item->date.date() == _date);
|
return (ComputeType(item) == _type && item->date.date() == _date);
|
||||||
}
|
}
|
||||||
void addItem(HistoryItem *item) {
|
void addItem(HistoryItem *item) {
|
||||||
|
@ -58,7 +59,7 @@ public:
|
||||||
});
|
});
|
||||||
refreshStatus();
|
refreshStatus();
|
||||||
}
|
}
|
||||||
void itemRemoved(HistoryItem *item) {
|
void itemRemoved(not_null<const HistoryItem*> item) {
|
||||||
if (hasItems() && item->id >= minItemId() && item->id <= maxItemId()) {
|
if (hasItems() && item->id >= minItemId() && item->id <= maxItemId()) {
|
||||||
_items.erase(std::remove(_items.begin(), _items.end(), item), _items.end());
|
_items.erase(std::remove(_items.begin(), _items.end(), item), _items.end());
|
||||||
refreshStatus();
|
refreshStatus();
|
||||||
|
@ -102,7 +103,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refreshStatus();
|
void refreshStatus();
|
||||||
static Type ComputeType(HistoryItem *item);
|
static Type ComputeType(not_null<const HistoryItem*> item);
|
||||||
|
|
||||||
std::vector<HistoryItem*> _items;
|
std::vector<HistoryItem*> _items;
|
||||||
QDate _date;
|
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)
|
, _items(1, item)
|
||||||
, _date(item->date.date())
|
, _date(item->date.date())
|
||||||
, _type(ComputeType(item)) {
|
, _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());
|
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()) {
|
if (item->out()) {
|
||||||
return Type::Out;
|
return Type::Out;
|
||||||
} else if (auto media = item->getMedia()) {
|
} else if (auto media = item->getMedia()) {
|
||||||
|
@ -193,18 +196,19 @@ void BoxController::Row::stopLastActionRipple() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoxController::prepare() {
|
void BoxController::prepare() {
|
||||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
Auth().data().itemRemoved()
|
||||||
if (auto row = rowForItem(item)) {
|
| rpl::start_with_next([this](auto item) {
|
||||||
row->itemRemoved(item);
|
if (auto row = rowForItem(item)) {
|
||||||
if (!row->hasItems()) {
|
row->itemRemoved(item);
|
||||||
delegate()->peerListRemoveRow(row);
|
if (!row->hasItems()) {
|
||||||
if (!delegate()->peerListFullRowsCount()) {
|
delegate()->peerListRemoveRow(row);
|
||||||
refreshAbout();
|
if (!delegate()->peerListFullRowsCount()) {
|
||||||
|
refreshAbout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
}
|
}
|
||||||
delegate()->peerListRefreshRows();
|
}, lifetime());
|
||||||
}
|
|
||||||
});
|
|
||||||
subscribe(Current().newServiceMessage(), [this](const FullMsgId &msgId) {
|
subscribe(Current().newServiceMessage(), [this](const FullMsgId &msgId) {
|
||||||
if (auto item = App::histItemById(msgId)) {
|
if (auto item = App::histItemById(msgId)) {
|
||||||
insertRow(item, InsertWay::Prepend);
|
insertRow(item, InsertWay::Prepend);
|
||||||
|
@ -287,21 +291,25 @@ void BoxController::receivedCalls(const QVector<MTPMessage> &result) {
|
||||||
delegate()->peerListRefreshRows();
|
delegate()->peerListRefreshRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BoxController::insertRow(HistoryItem *item, InsertWay way) {
|
bool BoxController::insertRow(
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
InsertWay way) {
|
||||||
if (auto row = rowForItem(item)) {
|
if (auto row = rowForItem(item)) {
|
||||||
if (row->canAddItem(item)) {
|
if (row->canAddItem(item)) {
|
||||||
row->addItem(item);
|
row->addItem(item);
|
||||||
return false;
|
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) {
|
delegate()->peerListSortRows([](PeerListRow &a, PeerListRow &b) {
|
||||||
return static_cast<Row&>(a).maxItemId() > static_cast<Row&>(b).maxItemId();
|
return static_cast<Row&>(a).maxItemId() > static_cast<Row&>(b).maxItemId();
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoxController::Row *BoxController::rowForItem(HistoryItem *item) {
|
BoxController::Row *BoxController::rowForItem(not_null<const HistoryItem*> item) {
|
||||||
auto v = delegate();
|
auto v = delegate();
|
||||||
if (auto fullRowsCount = v->peerListFullRowsCount()) {
|
if (auto fullRowsCount = v->peerListFullRowsCount()) {
|
||||||
auto itemId = item->id;
|
auto itemId = item->id;
|
||||||
|
@ -343,7 +351,8 @@ BoxController::Row *BoxController::rowForItem(HistoryItem *item) {
|
||||||
return nullptr;
|
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);
|
auto row = std::make_unique<Row>(item);
|
||||||
return std::move(row);
|
return std::move(row);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
namespace Calls {
|
namespace Calls {
|
||||||
|
|
||||||
class BoxController : public PeerListController, private base::Subscriber, private MTP::Sender {
|
class BoxController
|
||||||
|
: public PeerListController
|
||||||
|
, private base::Subscriber
|
||||||
|
, private MTP::Sender {
|
||||||
public:
|
public:
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
void rowClicked(not_null<PeerListRow*> row) override;
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
|
@ -36,14 +39,15 @@ private:
|
||||||
void refreshAbout();
|
void refreshAbout();
|
||||||
|
|
||||||
class Row;
|
class Row;
|
||||||
Row *rowForItem(HistoryItem *item);
|
Row *rowForItem(not_null<const HistoryItem*> item);
|
||||||
|
|
||||||
enum class InsertWay {
|
enum class InsertWay {
|
||||||
Append,
|
Append,
|
||||||
Prepend,
|
Prepend,
|
||||||
};
|
};
|
||||||
bool insertRow(HistoryItem *item, InsertWay way);
|
bool insertRow(not_null<HistoryItem*> item, InsertWay way);
|
||||||
std::unique_ptr<PeerListRow> createRow(HistoryItem *item) const;
|
std::unique_ptr<PeerListRow> createRow(
|
||||||
|
not_null<HistoryItem*> item) const;
|
||||||
|
|
||||||
MsgId _offsetId = 0;
|
MsgId _offsetId = 0;
|
||||||
mtpRequestId _loadRequestId = 0;
|
mtpRequestId _loadRequestId = 0;
|
||||||
|
|
|
@ -22,23 +22,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "inline_bots/inline_bot_layout_item.h"
|
#include "inline_bots/inline_bot_layout_item.h"
|
||||||
//#include "observer_peer.h"
|
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
//#include "application.h"
|
|
||||||
//#include "storage/file_upload.h"
|
|
||||||
//#include "mainwindow.h"
|
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
//#include "apiwrap.h"
|
|
||||||
//#include "boxes/confirm_box.h"
|
|
||||||
#include "media/media_audio.h"
|
#include "media/media_audio.h"
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
#include "platform/platform_specific.h"
|
#include "platform/platform_specific.h"
|
||||||
#include "history/history_media_types.h"
|
#include "history/history_media_types.h"
|
||||||
//#include "styles/style_history.h"
|
#include "auth_session.h"
|
||||||
//#include "window/themes/window_theme.h"
|
|
||||||
//#include "auth_session.h"
|
|
||||||
#include "messenger.h"
|
#include "messenger.h"
|
||||||
//#include "storage/file_download.h"
|
|
||||||
|
|
||||||
QString joinList(const QStringList &list, const QString &sep) {
|
QString joinList(const QStringList &list, const QString &sep) {
|
||||||
QString result;
|
QString result;
|
||||||
|
@ -728,7 +719,7 @@ void DocumentData::cancel() {
|
||||||
void DocumentData::notifyLayoutChanged() const {
|
void DocumentData::notifyLayoutChanged() const {
|
||||||
auto &items = App::documentItems();
|
auto &items = App::documentItems();
|
||||||
for (auto item : items.value(const_cast<DocumentData*>(this))) {
|
for (auto item : items.value(const_cast<DocumentData*>(this))) {
|
||||||
Notify::historyItemLayoutChanged(item);
|
Auth().data().markItemLayoutChanged(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto items = InlineBots::Layout::documentItems()) {
|
if (auto items = InlineBots::Layout::documentItems()) {
|
||||||
|
|
|
@ -20,24 +20,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#include "data/data_photo.h"
|
#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 "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 "history/history_media_types.h"
|
||||||
//#include "styles/style_history.h"
|
#include "auth_session.h"
|
||||||
//#include "window/themes/window_theme.h"
|
|
||||||
//#include "auth_session.h"
|
|
||||||
#include "messenger.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)
|
PhotoData::PhotoData(const PhotoId &id, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full)
|
||||||
: id(id)
|
: id(id)
|
||||||
|
@ -90,7 +76,7 @@ void PhotoData::notifyLayoutChanged() const {
|
||||||
auto i = items.constFind(const_cast<PhotoData*>(this));
|
auto i = items.constFind(const_cast<PhotoData*>(this));
|
||||||
if (i != items.cend()) {
|
if (i != items.cend()) {
|
||||||
for_const (auto item, i.value()) {
|
for_const (auto item, i.value()) {
|
||||||
Notify::historyItemLayoutChanged(item);
|
Auth().data().markItemLayoutChanged(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,9 +92,16 @@ DialogsInner::DialogsInner(QWidget *parent, not_null<Window::Controller*> contro
|
||||||
_cancelSearchFromUser->hide();
|
_cancelSearchFromUser->hide();
|
||||||
|
|
||||||
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
|
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
|
||||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
Auth().data().itemRemoved()
|
||||||
itemRemoved(item);
|
| 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) {
|
subscribe(App::histories().sendActionAnimationUpdated(), [this](const Histories::SendActionAnimationUpdate &update) {
|
||||||
auto updateRect = Dialogs::Layout::RowPainter::sendActionAnimationRect(update.width, update.height, getFullWidth(), update.textUpdated);
|
auto updateRect = Dialogs::Layout::RowPainter::sendActionAnimationRect(update.width, update.height, getFullWidth(), update.textUpdated);
|
||||||
updateDialogRow(update.history->peer, MsgId(0), updateRect, UpdateRowSection::Default | UpdateRowSection::Filtered);
|
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();
|
int wasCount = _searchResults.size();
|
||||||
for (auto i = _searchResults.begin(); i != _searchResults.end();) {
|
for (auto i = _searchResults.begin(); i != _searchResults.end();) {
|
||||||
if ((*i)->item() == item) {
|
if ((*i)->item() == item) {
|
||||||
|
|
|
@ -176,7 +176,7 @@ private:
|
||||||
}
|
}
|
||||||
void handlePeerNameChange(not_null<PeerData*> peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
|
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 {
|
enum class UpdateRowSection {
|
||||||
Default = (1 << 0),
|
Default = (1 << 0),
|
||||||
Filtered = (1 << 1),
|
Filtered = (1 << 1),
|
||||||
|
|
|
@ -250,12 +250,6 @@ bool isLayerShown() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void repaintHistoryItem(not_null<const HistoryItem*> item) {
|
|
||||||
if (auto main = App::main()) {
|
|
||||||
main->ui_repaintHistoryItem(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void autoplayMediaInlineAsync(const FullMsgId &msgId) {
|
void autoplayMediaInlineAsync(const FullMsgId &msgId) {
|
||||||
if (auto main = App::main()) {
|
if (auto main = App::main()) {
|
||||||
InvokeQueued(main, [msgId] {
|
InvokeQueued(main, [msgId] {
|
||||||
|
@ -355,10 +349,6 @@ void migrateUpdated(PeerData *peer) {
|
||||||
if (MainWidget *m = App::main()) m->notify_migrateUpdated(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) {
|
void historyMuteUpdated(History *history) {
|
||||||
if (MainWidget *m = App::main()) m->notify_historyMuteUpdated(history);
|
if (MainWidget *m = App::main()) m->notify_historyMuteUpdated(history);
|
||||||
}
|
}
|
||||||
|
@ -370,7 +360,7 @@ void handlePendingHistoryUpdate() {
|
||||||
Auth().data().pendingHistoryResize().notify(true);
|
Auth().data().pendingHistoryResize().notify(true);
|
||||||
|
|
||||||
for (auto item : base::take(Global::RefPendingRepaintItems())) {
|
for (auto item : base::take(Global::RefPendingRepaintItems())) {
|
||||||
Ui::repaintHistoryItem(item);
|
Auth().data().requestItemRepaint(item);
|
||||||
|
|
||||||
// Start the video if it is waiting for that.
|
// Start the video if it is waiting for that.
|
||||||
if (item->pendingInitDimensions()) {
|
if (item->pendingInitDimensions()) {
|
||||||
|
@ -639,7 +629,6 @@ struct Data {
|
||||||
|
|
||||||
base::Variable<DBIWorkMode> WorkMode = { dbiwmWindowAndTray };
|
base::Variable<DBIWorkMode> WorkMode = { dbiwmWindowAndTray };
|
||||||
|
|
||||||
base::Observable<HistoryItem*> ItemRemoved;
|
|
||||||
base::Observable<void> UnreadCounterUpdate;
|
base::Observable<void> UnreadCounterUpdate;
|
||||||
base::Observable<void> PeerChooseCancel;
|
base::Observable<void> PeerChooseCancel;
|
||||||
|
|
||||||
|
@ -762,7 +751,6 @@ DefineRefVar(Global, base::Observable<void>, LocalPasscodeChanged);
|
||||||
|
|
||||||
DefineRefVar(Global, base::Variable<DBIWorkMode>, WorkMode);
|
DefineRefVar(Global, base::Variable<DBIWorkMode>, WorkMode);
|
||||||
|
|
||||||
DefineRefVar(Global, base::Observable<HistoryItem*>, ItemRemoved);
|
|
||||||
DefineRefVar(Global, base::Observable<void>, UnreadCounterUpdate);
|
DefineRefVar(Global, base::Observable<void>, UnreadCounterUpdate);
|
||||||
DefineRefVar(Global, base::Observable<void>, PeerChooseCancel);
|
DefineRefVar(Global, base::Observable<void>, PeerChooseCancel);
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,6 @@ void hideLayer(anim::type animated = anim::type::normal);
|
||||||
void hideSettingsAndLayer(anim::type animated = anim::type::normal);
|
void hideSettingsAndLayer(anim::type animated = anim::type::normal);
|
||||||
bool isLayerShown();
|
bool isLayerShown();
|
||||||
|
|
||||||
void repaintHistoryItem(not_null<const HistoryItem*> item);
|
|
||||||
void autoplayMediaInlineAsync(const FullMsgId &msgId);
|
void autoplayMediaInlineAsync(const FullMsgId &msgId);
|
||||||
|
|
||||||
void showPeerProfile(const PeerId &peer);
|
void showPeerProfile(const PeerId &peer);
|
||||||
|
@ -181,7 +180,6 @@ bool switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot =
|
||||||
|
|
||||||
void migrateUpdated(PeerData *peer);
|
void migrateUpdated(PeerData *peer);
|
||||||
|
|
||||||
void historyItemLayoutChanged(const HistoryItem *item);
|
|
||||||
void historyMuteUpdated(History *history);
|
void historyMuteUpdated(History *history);
|
||||||
|
|
||||||
// handle pending resize() / paint() on history items
|
// handle pending resize() / paint() on history items
|
||||||
|
@ -399,7 +397,6 @@ DeclareRefVar(base::Observable<void>, LocalPasscodeChanged);
|
||||||
|
|
||||||
DeclareRefVar(base::Variable<DBIWorkMode>, WorkMode);
|
DeclareRefVar(base::Variable<DBIWorkMode>, WorkMode);
|
||||||
|
|
||||||
DeclareRefVar(base::Observable<HistoryItem*>, ItemRemoved);
|
|
||||||
DeclareRefVar(base::Observable<void>, UnreadCounterUpdate);
|
DeclareRefVar(base::Observable<void>, UnreadCounterUpdate);
|
||||||
DeclareRefVar(base::Observable<void>, PeerChooseCancel);
|
DeclareRefVar(base::Observable<void>, PeerChooseCancel);
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,11 @@ void InnerWidget::enumerateDates(Method method) {
|
||||||
enumerateItems<EnumItemsDirection::BottomToTop>(dateCallback);
|
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)
|
, _controller(controller)
|
||||||
, _channel(channel)
|
, _channel(channel)
|
||||||
, _history(App::history(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()) {
|
, _emptyText(st::historyAdminLogEmptyWidth - st::historyAdminLogEmptyPadding.left() - st::historyAdminLogEmptyPadding.left()) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
|
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
|
||||||
subscribe(Auth().data().repaintLogEntry(), [this](not_null<const HistoryItem*> historyItem) {
|
Auth().data().itemRepaintRequest()
|
||||||
if (_history == historyItem->history()) {
|
| rpl::start_with_next([this](auto item) {
|
||||||
repaintItem(historyItem);
|
if (item->isLogEntry() && _history == item->history()) {
|
||||||
}
|
repaintItem(item);
|
||||||
});
|
}
|
||||||
|
}, lifetime());
|
||||||
subscribe(Auth().data().pendingHistoryResize(), [this] { handlePendingHistoryResize(); });
|
subscribe(Auth().data().pendingHistoryResize(), [this] { handlePendingHistoryResize(); });
|
||||||
subscribe(Auth().data().queryItemVisibility(), [this](const AuthSessionData::ItemVisibilityQuery &query) {
|
subscribe(Auth().data().queryItemVisibility(), [this](const AuthSessionData::ItemVisibilityQuery &query) {
|
||||||
if (_history != query.item->history() || !query.item->isLogEntry() || !isVisible()) {
|
if (_history != query.item->history() || !query.item->isLogEntry() || !isVisible()) {
|
||||||
|
|
|
@ -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_item.h"
|
||||||
#include "history/history_admin_log_section.h"
|
#include "history/history_admin_log_section.h"
|
||||||
#include "ui/widgets/tooltip.h"
|
#include "ui/widgets/tooltip.h"
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
|
|
||||||
|
@ -38,9 +39,16 @@ namespace AdminLog {
|
||||||
|
|
||||||
class SectionMemento;
|
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:
|
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<void> showSearchSignal;
|
||||||
base::Observable<int> scrollToSignal;
|
base::Observable<int> scrollToSignal;
|
||||||
|
|
|
@ -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
|
// 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)
|
, _controller(controller)
|
||||||
, _peer(history->peer)
|
, _peer(history->peer)
|
||||||
, _migrated(history->migrateFrom())
|
, _migrated(history->migrateFrom())
|
||||||
|
@ -105,9 +110,10 @@ HistoryInner::HistoryInner(HistoryWidget *historyWidget, not_null<Window::Contro
|
||||||
notifyIsBotChanged();
|
notifyIsBotChanged();
|
||||||
|
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
Auth().data().itemRemoved()
|
||||||
itemRemoved(item);
|
| rpl::start_with_next(
|
||||||
});
|
[this](auto item) { itemRemoved(item); },
|
||||||
|
lifetime());
|
||||||
subscribe(_controller->gifPauseLevelChanged(), [this] {
|
subscribe(_controller->gifPauseLevelChanged(), [this] {
|
||||||
if (!_controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any)) {
|
if (!_controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any)) {
|
||||||
update();
|
update();
|
||||||
|
@ -389,7 +395,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||||
adjustCurrent(clip.top());
|
adjustCurrent(clip.top());
|
||||||
|
|
||||||
auto selEnd = _selected.cend();
|
auto selEnd = _selected.cend();
|
||||||
auto hasSel = !_selected.isEmpty();
|
auto hasSel = !_selected.empty();
|
||||||
|
|
||||||
auto drawToY = clip.y() + clip.height();
|
auto drawToY = clip.y() + clip.height();
|
||||||
|
|
||||||
|
@ -420,9 +426,9 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||||
sel = FullSelection;
|
sel = FullSelection;
|
||||||
}
|
}
|
||||||
} else if (hasSel) {
|
} else if (hasSel) {
|
||||||
auto i = _selected.constFind(item);
|
auto i = _selected.find(item);
|
||||||
if (i != selEnd) {
|
if (i != selEnd) {
|
||||||
sel = i.value();
|
sel = i->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item->draw(p, clip.translated(0, -y), sel, ms);
|
item->draw(p, clip.translated(0, -y), sel, ms);
|
||||||
|
@ -471,9 +477,9 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||||
sel = FullSelection;
|
sel = FullSelection;
|
||||||
}
|
}
|
||||||
} else if (hasSel) {
|
} else if (hasSel) {
|
||||||
auto i = _selected.constFind(item);
|
auto i = _selected.find(item);
|
||||||
if (i != selEnd) {
|
if (i != selEnd) {
|
||||||
sel = i.value();
|
sel = i->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item->draw(p, historyRect.translated(0, -y), sel, ms);
|
item->draw(p, historyRect.translated(0, -y), sel, ms);
|
||||||
|
@ -570,15 +576,18 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryInner::event(QEvent *e) {
|
bool HistoryInner::eventHook(QEvent *e) {
|
||||||
if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) {
|
if (e->type() == QEvent::TouchBegin
|
||||||
|
|| e->type() == QEvent::TouchUpdate
|
||||||
|
|| e->type() == QEvent::TouchEnd
|
||||||
|
|| e->type() == QEvent::TouchCancel) {
|
||||||
QTouchEvent *ev = static_cast<QTouchEvent*>(e);
|
QTouchEvent *ev = static_cast<QTouchEvent*>(e);
|
||||||
if (ev->device()->type() == QTouchDevice::TouchScreen) {
|
if (ev->device()->type() == QTouchDevice::TouchScreen) {
|
||||||
touchEvent(ev);
|
touchEvent(ev);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TWidget::event(e);
|
return RpWidget::eventHook(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::onTouchScrollTimer() {
|
void HistoryInner::onTouchScrollTimer() {
|
||||||
|
@ -811,9 +820,9 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
|
||||||
|
|
||||||
if (ClickHandler::getPressed()) {
|
if (ClickHandler::getPressed()) {
|
||||||
_mouseAction = MouseAction::PrepareDrag;
|
_mouseAction = MouseAction::PrepareDrag;
|
||||||
} else if (!_selected.isEmpty()) {
|
} else if (!_selected.empty()) {
|
||||||
if (_selected.cbegin().value() == FullSelection) {
|
if (_selected.cbegin()->second == FullSelection) {
|
||||||
if (_selected.constFind(_mouseActionItem) != _selected.cend() && App::hoveredItem()) {
|
if (_selected.find(_mouseActionItem) != _selected.cend() && App::hoveredItem()) {
|
||||||
_mouseAction = MouseAction::PrepareDrag; // start items drag
|
_mouseAction = MouseAction::PrepareDrag; // start items drag
|
||||||
} else if (!_pressWasInactive) {
|
} else if (!_pressWasInactive) {
|
||||||
_mouseAction = MouseAction::PrepareSelect; // start items select
|
_mouseAction = MouseAction::PrepareSelect; // start items select
|
||||||
|
@ -828,12 +837,12 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
|
||||||
dragState = _mouseActionItem->getState(_dragStartPosition, request);
|
dragState = _mouseActionItem->getState(_dragStartPosition, request);
|
||||||
if (dragState.cursor == HistoryInTextCursorState) {
|
if (dragState.cursor == HistoryInTextCursorState) {
|
||||||
TextSelection selStatus = { dragState.symbol, dragState.symbol };
|
TextSelection selStatus = { dragState.symbol, dragState.symbol };
|
||||||
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
if (selStatus != FullSelection && (_selected.empty() || _selected.cbegin()->second != FullSelection)) {
|
||||||
if (!_selected.isEmpty()) {
|
if (!_selected.empty()) {
|
||||||
repaintItem(_selected.cbegin().key());
|
repaintItem(_selected.cbegin()->first);
|
||||||
_selected.clear();
|
_selected.clear();
|
||||||
}
|
}
|
||||||
_selected.insert(_mouseActionItem, selStatus);
|
_selected.emplace(_mouseActionItem, selStatus);
|
||||||
_mouseTextSymbol = dragState.symbol;
|
_mouseTextSymbol = dragState.symbol;
|
||||||
_mouseAction = MouseAction::Selecting;
|
_mouseAction = MouseAction::Selecting;
|
||||||
_mouseSelectType = TextSelectType::Paragraphs;
|
_mouseSelectType = TextSelectType::Paragraphs;
|
||||||
|
@ -851,13 +860,12 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
|
||||||
_mouseTextSymbol = dragState.symbol;
|
_mouseTextSymbol = dragState.symbol;
|
||||||
bool uponSelected = (dragState.cursor == HistoryInTextCursorState);
|
bool uponSelected = (dragState.cursor == HistoryInTextCursorState);
|
||||||
if (uponSelected) {
|
if (uponSelected) {
|
||||||
if (_selected.isEmpty() ||
|
if (_selected.empty()
|
||||||
_selected.cbegin().value() == FullSelection ||
|
|| _selected.cbegin()->second == FullSelection
|
||||||
_selected.cbegin().key() != _mouseActionItem
|
|| _selected.cbegin()->first != _mouseActionItem) {
|
||||||
) {
|
|
||||||
uponSelected = false;
|
uponSelected = false;
|
||||||
} else {
|
} 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) {
|
if (_mouseTextSymbol < selFrom || _mouseTextSymbol >= selTo) {
|
||||||
uponSelected = false;
|
uponSelected = false;
|
||||||
}
|
}
|
||||||
|
@ -871,12 +879,12 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
|
||||||
} else {
|
} else {
|
||||||
if (dragState.afterSymbol) ++_mouseTextSymbol;
|
if (dragState.afterSymbol) ++_mouseTextSymbol;
|
||||||
TextSelection selStatus = { _mouseTextSymbol, _mouseTextSymbol };
|
TextSelection selStatus = { _mouseTextSymbol, _mouseTextSymbol };
|
||||||
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
if (selStatus != FullSelection && (_selected.empty() || _selected.cbegin()->second != FullSelection)) {
|
||||||
if (!_selected.isEmpty()) {
|
if (!_selected.empty()) {
|
||||||
repaintItem(_selected.cbegin().key());
|
repaintItem(_selected.cbegin()->first);
|
||||||
_selected.clear();
|
_selected.clear();
|
||||||
}
|
}
|
||||||
_selected.insert(_mouseActionItem, selStatus);
|
_selected.emplace(_mouseActionItem, selStatus);
|
||||||
_mouseAction = MouseAction::Selecting;
|
_mouseAction = MouseAction::Selecting;
|
||||||
repaintItem(_mouseActionItem);
|
repaintItem(_mouseActionItem);
|
||||||
} else {
|
} else {
|
||||||
|
@ -911,21 +919,20 @@ void HistoryInner::performDrag() {
|
||||||
|
|
||||||
bool uponSelected = false;
|
bool uponSelected = false;
|
||||||
if (_mouseActionItem) {
|
if (_mouseActionItem) {
|
||||||
if (!_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
|
if (!_selected.empty() && _selected.cbegin()->second == FullSelection) {
|
||||||
uponSelected = _selected.contains(_mouseActionItem);
|
uponSelected = (_selected.find(_mouseActionItem) != _selected.cend());
|
||||||
} else {
|
} else {
|
||||||
HistoryStateRequest request;
|
HistoryStateRequest request;
|
||||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||||
auto dragState = _mouseActionItem->getState(_dragStartPosition, request);
|
auto dragState = _mouseActionItem->getState(_dragStartPosition, request);
|
||||||
uponSelected = (dragState.cursor == HistoryInTextCursorState);
|
uponSelected = (dragState.cursor == HistoryInTextCursorState);
|
||||||
if (uponSelected) {
|
if (uponSelected) {
|
||||||
if (_selected.isEmpty() ||
|
if (_selected.empty()
|
||||||
_selected.cbegin().value() == FullSelection ||
|
|| _selected.cbegin()->second == FullSelection
|
||||||
_selected.cbegin().key() != _mouseActionItem
|
|| _selected.cbegin()->first != _mouseActionItem) {
|
||||||
) {
|
|
||||||
uponSelected = false;
|
uponSelected = false;
|
||||||
} else {
|
} 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) {
|
if (dragState.symbol < selFrom || dragState.symbol >= selTo) {
|
||||||
uponSelected = false;
|
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()) {
|
if (_history != item->history() && _migrated != item->history()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1032,7 +1039,7 @@ void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton bu
|
||||||
} else if (auto pressed = App::pressedLinkItem()) {
|
} else if (auto pressed = App::pressedLinkItem()) {
|
||||||
// if we are in selecting items mode perhaps we want to
|
// if we are in selecting items mode perhaps we want to
|
||||||
// toggle selection instead of activating the pressed link
|
// 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 (auto media = pressed->getMedia()) {
|
||||||
if (media->toggleSelectionByHandlerClick(activated)) {
|
if (media->toggleSelectionByHandlerClick(activated)) {
|
||||||
activated.clear();
|
activated.clear();
|
||||||
|
@ -1052,27 +1059,27 @@ void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton bu
|
||||||
App::activateClickHandler(activated, button);
|
App::activateClickHandler(activated, button);
|
||||||
return;
|
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);
|
SelectedItems::iterator i = _selected.find(_mouseActionItem);
|
||||||
if (i == _selected.cend() && !_mouseActionItem->serviceMsg() && _mouseActionItem->id > 0) {
|
if (i == _selected.cend() && !_mouseActionItem->serviceMsg() && _mouseActionItem->id > 0) {
|
||||||
if (_selected.size() < MaxSelectedItems) {
|
if (_selected.size() < MaxSelectedItems) {
|
||||||
if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
|
if (!_selected.empty() && _selected.cbegin()->second != FullSelection) {
|
||||||
_selected.clear();
|
_selected.clear();
|
||||||
}
|
}
|
||||||
_selected.insert(_mouseActionItem, FullSelection);
|
_selected.emplace(_mouseActionItem, FullSelection);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_selected.erase(i);
|
_selected.erase(i);
|
||||||
}
|
}
|
||||||
repaintItem(_mouseActionItem);
|
repaintItem(_mouseActionItem);
|
||||||
} else if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && button != Qt::RightButton) {
|
} else if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && button != Qt::RightButton) {
|
||||||
SelectedItems::iterator i = _selected.find(_mouseActionItem);
|
auto i = _selected.find(_mouseActionItem);
|
||||||
if (i != _selected.cend() && i.value() == FullSelection) {
|
if (i != _selected.cend() && i->second == FullSelection) {
|
||||||
_selected.erase(i);
|
_selected.erase(i);
|
||||||
repaintItem(_mouseActionItem);
|
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) {
|
if (_selected.size() < MaxSelectedItems) {
|
||||||
_selected.insert(_mouseActionItem, FullSelection);
|
_selected.emplace(_mouseActionItem, FullSelection);
|
||||||
repaintItem(_mouseActionItem);
|
repaintItem(_mouseActionItem);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1083,8 +1090,8 @@ void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton bu
|
||||||
if (_dragSelFrom && _dragSelTo) {
|
if (_dragSelFrom && _dragSelTo) {
|
||||||
applyDragSelection();
|
applyDragSelection();
|
||||||
_dragSelFrom = _dragSelTo = 0;
|
_dragSelFrom = _dragSelTo = 0;
|
||||||
} else if (!_selected.isEmpty() && !_pressWasInactive) {
|
} else if (!_selected.empty() && !_pressWasInactive) {
|
||||||
auto sel = _selected.cbegin().value();
|
auto sel = _selected.cbegin()->second;
|
||||||
if (sel != FullSelection && sel.from == sel.to) {
|
if (sel != FullSelection && sel.from == sel.to) {
|
||||||
_selected.clear();
|
_selected.clear();
|
||||||
App::wnd()->setInnerFocus();
|
App::wnd()->setInnerFocus();
|
||||||
|
@ -1098,8 +1105,8 @@ void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton bu
|
||||||
_widget->updateTopBarSelection();
|
_widget->updateTopBarSelection();
|
||||||
|
|
||||||
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||||
if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
|
if (!_selected.empty() && _selected.cbegin()->second != FullSelection) {
|
||||||
setToClipboard(_selected.cbegin().key()->selectedText(_selected.cbegin().value()), QClipboard::Selection);
|
setToClipboard(_selected.cbegin()->first->selectedText(_selected.cbegin()->second), QClipboard::Selection);
|
||||||
}
|
}
|
||||||
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
|
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
|
||||||
}
|
}
|
||||||
|
@ -1115,7 +1122,7 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) {
|
||||||
if (!_history) return;
|
if (!_history) return;
|
||||||
|
|
||||||
mouseActionStart(e->globalPos(), e->button());
|
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;
|
HistoryStateRequest request;
|
||||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||||
auto dragState = _mouseActionItem->getState(_dragStartPosition, request);
|
auto dragState = _mouseActionItem->getState(_dragStartPosition, request);
|
||||||
|
@ -1125,11 +1132,11 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) {
|
||||||
if (_mouseAction == MouseAction::None) {
|
if (_mouseAction == MouseAction::None) {
|
||||||
_mouseAction = MouseAction::Selecting;
|
_mouseAction = MouseAction::Selecting;
|
||||||
TextSelection selStatus = { dragState.symbol, dragState.symbol };
|
TextSelection selStatus = { dragState.symbol, dragState.symbol };
|
||||||
if (!_selected.isEmpty()) {
|
if (!_selected.empty()) {
|
||||||
repaintItem(_selected.cbegin().key());
|
repaintItem(_selected.cbegin()->first);
|
||||||
_selected.clear();
|
_selected.clear();
|
||||||
}
|
}
|
||||||
_selected.insert(_mouseActionItem, selStatus);
|
_selected.emplace(_mouseActionItem, selStatus);
|
||||||
}
|
}
|
||||||
mouseMoveEvent(e);
|
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
|
// -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 isUponSelected = 0;
|
||||||
auto hasSelected = 0;;
|
auto hasSelected = 0;;
|
||||||
if (!_selected.isEmpty()) {
|
if (!_selected.empty()) {
|
||||||
isUponSelected = -1;
|
isUponSelected = -1;
|
||||||
if (_selected.cbegin().value() == FullSelection) {
|
if (_selected.cbegin()->second == FullSelection) {
|
||||||
hasSelected = 2;
|
hasSelected = 2;
|
||||||
if (App::hoveredItem() && _selected.constFind(App::hoveredItem()) != _selected.cend()) {
|
if (App::hoveredItem() && _selected.find(App::hoveredItem()) != _selected.cend()) {
|
||||||
isUponSelected = 2;
|
isUponSelected = 2;
|
||||||
} else {
|
} else {
|
||||||
isUponSelected = -2;
|
isUponSelected = -2;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
hasSelected = (selTo > selFrom) ? 1 : 0;
|
||||||
if (App::mousedItem() && App::mousedItem() == App::hoveredItem()) {
|
if (App::mousedItem() && App::mousedItem() == App::hoveredItem()) {
|
||||||
auto mousePos = mapPointToItem(mapFromGlobal(_mousePosition), App::mousedItem());
|
auto mousePos = mapPointToItem(mapFromGlobal(_mousePosition), App::mousedItem());
|
||||||
|
@ -1520,21 +1527,21 @@ TextWithEntities HistoryInner::getSelectedText() const {
|
||||||
applyDragSelection(&sel);
|
applyDragSelection(&sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sel.isEmpty()) {
|
if (sel.empty()) {
|
||||||
return TextWithEntities();
|
return TextWithEntities();
|
||||||
}
|
}
|
||||||
if (sel.cbegin().value() != FullSelection) {
|
if (sel.cbegin()->second != FullSelection) {
|
||||||
return sel.cbegin().key()->selectedText(sel.cbegin().value());
|
return sel.cbegin()->first->selectedText(sel.cbegin()->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fullSize = 0;
|
int fullSize = 0;
|
||||||
QString timeFormat(qsl(", [dd.MM.yy hh:mm]\n"));
|
QString timeFormat(qsl(", [dd.MM.yy hh:mm]\n"));
|
||||||
QMap<int, TextWithEntities> texts;
|
QMap<int, TextWithEntities> texts;
|
||||||
for (auto i = sel.cbegin(), e = sel.cend(); i != e; ++i) {
|
for (auto &selected : sel) {
|
||||||
HistoryItem *item = i.key();
|
auto item = selected.first;
|
||||||
if (item->detached()) continue;
|
if (item->detached()) continue;
|
||||||
|
|
||||||
QString time = item->date.toString(timeFormat);
|
auto time = item->date.toString(timeFormat);
|
||||||
TextWithEntities part, unwrapped = item->selectedText(FullSelection);
|
TextWithEntities part, unwrapped = item->selectedText(FullSelection);
|
||||||
int size = item->author()->name.size() + time.size() + unwrapped.text.size();
|
int size = item->author()->name.size() + time.size() + unwrapped.text.size();
|
||||||
part.text.reserve(size);
|
part.text.reserve(size);
|
||||||
|
@ -1563,7 +1570,7 @@ TextWithEntities HistoryInner::getSelectedText() const {
|
||||||
void HistoryInner::keyPressEvent(QKeyEvent *e) {
|
void HistoryInner::keyPressEvent(QKeyEvent *e) {
|
||||||
if (e->key() == Qt::Key_Escape) {
|
if (e->key() == Qt::Key_Escape) {
|
||||||
_widget->onListEscapePressed();
|
_widget->onListEscapePressed();
|
||||||
} else if (e == QKeySequence::Copy && !_selected.isEmpty()) {
|
} else if (e == QKeySequence::Copy && !_selected.empty()) {
|
||||||
copySelectedText();
|
copySelectedText();
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
|
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
|
||||||
|
@ -1850,7 +1857,7 @@ HistoryInner::~HistoryInner() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryInner::focusNextPrevChild(bool next) {
|
bool HistoryInner::focusNextPrevChild(bool next) {
|
||||||
if (_selected.isEmpty()) {
|
if (_selected.empty()) {
|
||||||
return TWidget::focusNextPrevChild(next);
|
return TWidget::focusNextPrevChild(next);
|
||||||
} else {
|
} else {
|
||||||
clearSelectedItems();
|
clearSelectedItems();
|
||||||
|
@ -1932,7 +1939,7 @@ HistoryItem *HistoryInner::nextItem(HistoryItem *item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryInner::canCopySelected() const {
|
bool HistoryInner::canCopySelected() const {
|
||||||
return !_selected.isEmpty();
|
return !_selected.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryInner::canDeleteSelected() const {
|
bool HistoryInner::canDeleteSelected() const {
|
||||||
|
@ -1942,13 +1949,13 @@ bool HistoryInner::canDeleteSelected() const {
|
||||||
|
|
||||||
Window::TopBarWidget::SelectedState HistoryInner::getSelectionState() const {
|
Window::TopBarWidget::SelectedState HistoryInner::getSelectionState() const {
|
||||||
auto result = Window::TopBarWidget::SelectedState {};
|
auto result = Window::TopBarWidget::SelectedState {};
|
||||||
for (auto i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) {
|
for (auto &selected : _selected) {
|
||||||
if (i.value() == FullSelection) {
|
if (selected.second == FullSelection) {
|
||||||
++result.count;
|
++result.count;
|
||||||
if (i.key()->canDelete()) {
|
if (selected.first->canDelete()) {
|
||||||
++result.canDeleteCount;
|
++result.canDeleteCount;
|
||||||
}
|
}
|
||||||
if (i.key()->canForward()) {
|
if (selected.first->canForward()) {
|
||||||
++result.canForwardCount;
|
++result.canForwardCount;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1959,7 +1966,7 @@ Window::TopBarWidget::SelectedState HistoryInner::getSelectionState() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::clearSelectedItems(bool onlyTextSelection) {
|
void HistoryInner::clearSelectedItems(bool onlyTextSelection) {
|
||||||
if (!_selected.isEmpty() && (!onlyTextSelection || _selected.cbegin().value() != FullSelection)) {
|
if (!_selected.empty() && (!onlyTextSelection || _selected.cbegin()->second != FullSelection)) {
|
||||||
_selected.clear();
|
_selected.clear();
|
||||||
_widget->updateTopBarSelection();
|
_widget->updateTopBarSelection();
|
||||||
_widget->update();
|
_widget->update();
|
||||||
|
@ -1968,12 +1975,12 @@ void HistoryInner::clearSelectedItems(bool onlyTextSelection) {
|
||||||
|
|
||||||
SelectedItemSet HistoryInner::getSelectedItems() const {
|
SelectedItemSet HistoryInner::getSelectedItems() const {
|
||||||
auto result = SelectedItemSet();
|
auto result = SelectedItemSet();
|
||||||
if (_selected.isEmpty() || _selected.cbegin().value() != FullSelection) {
|
if (_selected.empty() || _selected.cbegin()->second != FullSelection) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) {
|
for (auto &selected : _selected) {
|
||||||
auto item = i.key();
|
auto item = selected.first;
|
||||||
if (item && item->toHistoryMessage() && item->id > 0) {
|
if (item && item->toHistoryMessage() && item->id > 0) {
|
||||||
if (item->history() == _migrated) {
|
if (item->history() == _migrated) {
|
||||||
result.insert(item->id - ServerMaxMsgId, item);
|
result.insert(item->id - ServerMaxMsgId, item);
|
||||||
|
@ -1986,12 +1993,12 @@ SelectedItemSet HistoryInner::getSelectedItems() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::selectItem(HistoryItem *item) {
|
void HistoryInner::selectItem(HistoryItem *item) {
|
||||||
if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
|
if (!_selected.empty() && _selected.cbegin()->second != FullSelection) {
|
||||||
_selected.clear();
|
_selected.clear();
|
||||||
} else if (_selected.size() == MaxSelectedItems && _selected.constFind(item) == _selected.cend()) {
|
} else if (_selected.size() == MaxSelectedItems && _selected.find(item) == _selected.cend()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_selected.insert(item, FullSelection);
|
_selected.emplace(item, FullSelection);
|
||||||
_widget->updateTopBarSelection();
|
_widget->updateTopBarSelection();
|
||||||
_widget->update();
|
_widget->update();
|
||||||
}
|
}
|
||||||
|
@ -2037,7 +2044,7 @@ void HistoryInner::onUpdateSelected() {
|
||||||
|
|
||||||
HistoryTextState dragState;
|
HistoryTextState dragState;
|
||||||
ClickHandlerHost *lnkhost = nullptr;
|
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 (point.y() < _historyPaddingTop) {
|
||||||
if (_botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) {
|
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);
|
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;
|
_mouseCursorState = dragState.cursor;
|
||||||
if (dragState.link) {
|
if (dragState.link) {
|
||||||
cur = style::cur_pointer;
|
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;
|
cur = style::cur_text;
|
||||||
} else if (_mouseCursorState == HistoryInDateCursorState) {
|
} else if (_mouseCursorState == HistoryInDateCursorState) {
|
||||||
// cur = style::cur_cross;
|
// cur = style::cur_cross;
|
||||||
|
@ -2203,8 +2210,8 @@ void HistoryInner::onUpdateSelected() {
|
||||||
dragFirstAffected = (dragFirstAffected == dragSelTo) ? 0 : (selectingDown ? nextItem(dragFirstAffected) : prevItem(dragFirstAffected));
|
dragFirstAffected = (dragFirstAffected == dragSelTo) ? 0 : (selectingDown ? nextItem(dragFirstAffected) : prevItem(dragFirstAffected));
|
||||||
}
|
}
|
||||||
if (dragFirstAffected) {
|
if (dragFirstAffected) {
|
||||||
auto i = _selected.constFind(dragFirstAffected);
|
auto i = _selected.find(dragFirstAffected);
|
||||||
dragSelecting = (i == _selected.cend() || i.value() != FullSelection);
|
dragSelecting = (i == _selected.cend() || i->second != FullSelection);
|
||||||
}
|
}
|
||||||
updateDragSelection(dragSelFrom, dragSelTo, dragSelecting);
|
updateDragSelection(dragSelFrom, dragSelTo, dragSelecting);
|
||||||
}
|
}
|
||||||
|
@ -2213,7 +2220,7 @@ void HistoryInner::onUpdateSelected() {
|
||||||
|
|
||||||
if (ClickHandler::getPressed()) {
|
if (ClickHandler::getPressed()) {
|
||||||
cur = style::cur_pointer;
|
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) {
|
if (!_dragSelFrom || !_dragSelTo) {
|
||||||
cur = style::cur_text;
|
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 {
|
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) {
|
if (fromblock >= 0 && fromitem >= 0 && toblock >= 0 && toitem >= 0) {
|
||||||
for (; fromblock <= toblock; ++fromblock) {
|
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) {
|
for (int32 cnt = (fromblock < toblock) ? block->items.size() : (toitem + 1); fromitem < cnt; ++fromitem) {
|
||||||
HistoryItem *item = block->items[fromitem];
|
auto item = block->items[fromitem];
|
||||||
SelectedItems::iterator i = toItems->find(item);
|
auto i = toItems->find(item);
|
||||||
if (item->id > 0 && !item->serviceMsg()) {
|
if (item->id > 0 && !item->serviceMsg()) {
|
||||||
if (i == toItems->cend()) {
|
if (i == toItems->cend()) {
|
||||||
if (toItems->size() >= MaxSelectedItems) break;
|
if (toItems->size() >= MaxSelectedItems) break;
|
||||||
toItems->insert(item, FullSelection);
|
toItems->emplace(item, FullSelection);
|
||||||
} else if (i.value() != FullSelection) {
|
} else if (i->second != FullSelection) {
|
||||||
*i = FullSelection;
|
i->second = FullSelection;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (i != toItems->cend()) {
|
if (i != toItems->cend()) {
|
||||||
|
@ -2383,7 +2390,7 @@ void HistoryInner::applyDragSelection(SelectedItems *toItems) const {
|
||||||
}
|
}
|
||||||
seltoy += _dragSelTo->height();
|
seltoy += _dragSelTo->height();
|
||||||
|
|
||||||
if (!toItems->isEmpty() && toItems->cbegin().value() != FullSelection) {
|
if (!toItems->empty() && toItems->cbegin()->second != FullSelection) {
|
||||||
toItems->clear();
|
toItems->clear();
|
||||||
}
|
}
|
||||||
if (_dragSelecting) {
|
if (_dragSelecting) {
|
||||||
|
@ -2407,8 +2414,8 @@ void HistoryInner::applyDragSelection(SelectedItems *toItems) const {
|
||||||
}
|
}
|
||||||
addSelectionRange(toItems, fromblock, fromitem, toblock, toitem, _history);
|
addSelectionRange(toItems, fromblock, fromitem, toblock, toitem, _history);
|
||||||
} else {
|
} else {
|
||||||
for (SelectedItems::iterator i = toItems->begin(); i != toItems->cend();) {
|
for (auto i = toItems->begin(); i != toItems->cend();) {
|
||||||
int32 iy = itemTop(i.key());
|
auto iy = itemTop(i->first);
|
||||||
if (iy < 0) {
|
if (iy < 0) {
|
||||||
if (iy < -1) i = toItems->erase(i);
|
if (iy < -1) i = toItems->erase(i);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
#include "ui/widgets/tooltip.h"
|
#include "ui/widgets/tooltip.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
#include "window/top_bar_widget.h"
|
#include "window/top_bar_widget.h"
|
||||||
|
@ -33,11 +34,18 @@ class PopupMenu;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
class HistoryWidget;
|
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
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
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 messagesReceived(PeerData *peer, const QVector<MTPMessage> &messages);
|
||||||
void messagesReceivedDown(PeerData *peer, const QVector<MTPMessage> &messages);
|
void messagesReceivedDown(PeerData *peer, const QVector<MTPMessage> &messages);
|
||||||
|
@ -91,7 +99,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
bool focusNextPrevChild(bool next) override;
|
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 touchEvent(QTouchEvent *e);
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
|
@ -141,7 +149,7 @@ private:
|
||||||
|
|
||||||
void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false);
|
void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false);
|
||||||
|
|
||||||
void itemRemoved(HistoryItem *item);
|
void itemRemoved(not_null<const HistoryItem*> item);
|
||||||
void savePhotoToFile(PhotoData *photo);
|
void savePhotoToFile(PhotoData *photo);
|
||||||
void saveDocumentToFile(DocumentData *document);
|
void saveDocumentToFile(DocumentData *document);
|
||||||
void copyContextImage(PhotoData *photo);
|
void copyContextImage(PhotoData *photo);
|
||||||
|
@ -206,7 +214,7 @@ private:
|
||||||
bool _firstLoading = false;
|
bool _firstLoading = false;
|
||||||
|
|
||||||
style::cursor _cursor = style::cur_default;
|
style::cursor _cursor = style::cur_default;
|
||||||
using SelectedItems = QMap<HistoryItem*, TextSelection>;
|
using SelectedItems = std::map<HistoryItem*, TextSelection, std::less<>>;
|
||||||
SelectedItems _selected;
|
SelectedItems _selected;
|
||||||
void applyDragSelection();
|
void applyDragSelection();
|
||||||
void applyDragSelection(SelectedItems *toItems) const;
|
void applyDragSelection(SelectedItems *toItems) const;
|
||||||
|
|
|
@ -685,7 +685,7 @@ void HistoryItem::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool activ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
App::hoveredLinkItem(active ? this : nullptr);
|
App::hoveredLinkItem(active ? this : nullptr);
|
||||||
Ui::repaintHistoryItem(this);
|
Auth().data().requestItemRepaint(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
|
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);
|
App::pressedLinkItem(pressed ? this : nullptr);
|
||||||
Ui::repaintHistoryItem(this);
|
Auth().data().requestItemRepaint(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::addLogEntryOriginal(WebPageId localId, const QString &label, const TextWithEntities &content) {
|
void HistoryItem::addLogEntryOriginal(WebPageId localId, const QString &label, const TextWithEntities &content) {
|
||||||
|
@ -1103,14 +1103,14 @@ void HistoryItem::clipCallback(Media::Clip::Notification notification) {
|
||||||
}
|
}
|
||||||
if (!stopped) {
|
if (!stopped) {
|
||||||
setPendingInitDimensions();
|
setPendingInitDimensions();
|
||||||
Notify::historyItemLayoutChanged(this);
|
Auth().data().markItemLayoutChanged(this);
|
||||||
Global::RefPendingRepaintItems().insert(this);
|
Global::RefPendingRepaintItems().insert(this);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NotificationRepaint: {
|
case NotificationRepaint: {
|
||||||
if (!reader->currentDisplayed()) {
|
if (!reader->currentDisplayed()) {
|
||||||
Ui::repaintHistoryItem(this);
|
Auth().data().requestItemRepaint(this);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,11 +176,11 @@ void HistoryFileMedia::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryFileMedia::thumbAnimationCallback() {
|
void HistoryFileMedia::thumbAnimationCallback() {
|
||||||
Ui::repaintHistoryItem(_parent);
|
Auth().data().requestItemRepaint(_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryFileMedia::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
|
void HistoryFileMedia::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
|
||||||
Ui::repaintHistoryItem(_parent);
|
Auth().data().requestItemRepaint(_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryFileMedia::setLinks(ClickHandlerPtr &&openl, ClickHandlerPtr &&savel, ClickHandlerPtr &&cancell) {
|
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) {
|
void HistoryFileMedia::step_radial(TimeMs ms, bool timer) {
|
||||||
if (timer) {
|
if (timer) {
|
||||||
Ui::repaintHistoryItem(_parent);
|
Auth().data().requestItemRepaint(_parent);
|
||||||
} else {
|
} else {
|
||||||
_animation->radial.update(dataProgress(), dataFinished(), ms);
|
_animation->radial.update(dataProgress(), dataFinished(), ms);
|
||||||
if (!_animation->radial.animating()) {
|
if (!_animation->radial.animating()) {
|
||||||
|
@ -1553,7 +1553,7 @@ void HistoryDocument::updatePressed(QPoint point) {
|
||||||
nameright = st::msgFilePadding.left();
|
nameright = st::msgFilePadding.left();
|
||||||
}
|
}
|
||||||
voice->setSeekingCurrent(snap((point.x() - nameleft) / float64(_width - nameleft - nameright), 0., 1.));
|
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 {
|
} else {
|
||||||
voice->_playback->a_progress.update(qMin(dt, 1.), anim::linear);
|
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) {
|
if (mode == Mode::Video) {
|
||||||
_roundPlayback = std::make_unique<Media::Clip::Playback>();
|
_roundPlayback = std::make_unique<Media::Clip::Playback>();
|
||||||
_roundPlayback->setValueChangedCallback([this](float64 value) {
|
_roundPlayback->setValueChangedCallback([this](float64 value) {
|
||||||
Ui::repaintHistoryItem(_parent);
|
Auth().data().requestItemRepaint(_parent);
|
||||||
});
|
});
|
||||||
if (App::main()) {
|
if (App::main()) {
|
||||||
App::main()->mediaMarkRead(_data);
|
App::main()->mediaMarkRead(_data);
|
||||||
|
@ -2638,7 +2638,7 @@ void HistoryGif::stopInline() {
|
||||||
clearClipReader();
|
clearClipReader();
|
||||||
|
|
||||||
_parent->setPendingInitDimensions();
|
_parent->setPendingInitDimensions();
|
||||||
Notify::historyItemLayoutChanged(_parent);
|
Auth().data().markItemLayoutChanged(_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryGif::setClipReader(Media::Clip::ReaderPointer gif) {
|
void HistoryGif::setClipReader(Media::Clip::ReaderPointer gif) {
|
||||||
|
|
|
@ -556,7 +556,7 @@ const style::TextStyle &HistoryMessage::KeyboardStyle::textStyle() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMessage::KeyboardStyle::repaint(not_null<const HistoryItem*> item) const {
|
void HistoryMessage::KeyboardStyle::repaint(not_null<const HistoryItem*> item) const {
|
||||||
Ui::repaintHistoryItem(item);
|
Auth().data().requestItemRepaint(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
int HistoryMessage::KeyboardStyle::buttonRadius() const {
|
int HistoryMessage::KeyboardStyle::buttonRadius() const {
|
||||||
|
@ -1581,7 +1581,7 @@ void HistoryMessage::setViewsCount(int32 count) {
|
||||||
views->_viewsText = (views->_views >= 0) ? formatViewsCount(views->_views) : QString();
|
views->_viewsText = (views->_views >= 0) ? formatViewsCount(views->_views) : QString();
|
||||||
views->_viewsWidth = views->_viewsText.isEmpty() ? 0 : st::msgDateFont->width(views->_viewsText);
|
views->_viewsWidth = views->_viewsText.isEmpty() ? 0 : st::msgDateFont->width(views->_viewsText);
|
||||||
if (was == views->_viewsWidth) {
|
if (was == views->_viewsWidth) {
|
||||||
Ui::repaintHistoryItem(this);
|
Auth().data().requestItemRepaint(this);
|
||||||
} else {
|
} else {
|
||||||
if (_text.hasSkipBlock()) {
|
if (_text.hasSkipBlock()) {
|
||||||
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
|
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
|
||||||
|
@ -1596,7 +1596,7 @@ void HistoryMessage::setId(MsgId newId) {
|
||||||
bool wasPositive = (id > 0), positive = (newId > 0);
|
bool wasPositive = (id > 0), positive = (newId > 0);
|
||||||
HistoryItem::setId(newId);
|
HistoryItem::setId(newId);
|
||||||
if (wasPositive == positive) {
|
if (wasPositive == positive) {
|
||||||
Ui::repaintHistoryItem(this);
|
Auth().data().requestItemRepaint(this);
|
||||||
} else {
|
} else {
|
||||||
if (_text.hasSkipBlock()) {
|
if (_text.hasSkipBlock()) {
|
||||||
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
|
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
|
||||||
|
|
|
@ -605,8 +605,7 @@ SharedMediaMergedSlice SharedMediaMergedSliceBuilder::snapshot() const {
|
||||||
return SharedMediaMergedSlice(
|
return SharedMediaMergedSlice(
|
||||||
_key,
|
_key,
|
||||||
_part,
|
_part,
|
||||||
_migrated
|
_migrated);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<SharedMediaMergedSlice> SharedMediaMergedViewer(
|
rpl::producer<SharedMediaMergedSlice> SharedMediaMergedViewer(
|
||||||
|
@ -615,7 +614,7 @@ rpl::producer<SharedMediaMergedSlice> SharedMediaMergedViewer(
|
||||||
int limitAfter) {
|
int limitAfter) {
|
||||||
Expects(IsServerMsgId(key.universalId)
|
Expects(IsServerMsgId(key.universalId)
|
||||||
|| (key.universalId == 0)
|
|| (key.universalId == 0)
|
||||||
|| (IsServerMsgId(-key.universalId) && key.migratedPeerId != 0));
|
|| (IsServerMsgId(ServerMaxMsgId + key.universalId) && key.migratedPeerId != 0));
|
||||||
Expects((key.universalId != 0) || (limitBefore == 0 && limitAfter == 0));
|
Expects((key.universalId != 0) || (limitBefore == 0 && limitAfter == 0));
|
||||||
|
|
||||||
return [=](auto consumer) {
|
return [=](auto consumer) {
|
||||||
|
|
|
@ -131,7 +131,9 @@ public:
|
||||||
return {
|
return {
|
||||||
key.migratedPeerId,
|
key.migratedPeerId,
|
||||||
key.type,
|
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]);
|
return ComputeId(slice.key().peerId, slice[index]);
|
||||||
};
|
};
|
||||||
static FullMsgId ComputeId(const Key &key) {
|
static FullMsgId ComputeId(const Key &key) {
|
||||||
return (key.universalId > 0)
|
return (key.universalId >= 0)
|
||||||
? ComputeId(key.peerId, key.universalId)
|
? ComputeId(key.peerId, key.universalId)
|
||||||
: ComputeId(key.migratedPeerId, -key.universalId);
|
: ComputeId(key.migratedPeerId, ServerMaxMsgId + key.universalId);
|
||||||
}
|
}
|
||||||
static base::optional<int> Add(
|
static base::optional<int> Add(
|
||||||
const base::optional<int> &a,
|
const base::optional<int> &a,
|
||||||
|
@ -181,7 +183,7 @@ private:
|
||||||
&& (!_migrated || _part.skippedBefore() != 0);
|
&& (!_migrated || _part.skippedBefore() != 0);
|
||||||
}
|
}
|
||||||
bool isolatedInMigrated() const {
|
bool isolatedInMigrated() const {
|
||||||
return IsServerMsgId(-_key.universalId)
|
return IsServerMsgId(ServerMaxMsgId + _key.universalId)
|
||||||
&& (_migrated->skippedAfter() != 0);
|
&& (_migrated->skippedAfter() != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,9 +300,9 @@ private:
|
||||||
}
|
}
|
||||||
static Value ComputeId(const Key &key) {
|
static Value ComputeId(const Key &key) {
|
||||||
if (auto messageId = base::get_if<MessageId>(&key.universalId)) {
|
if (auto messageId = base::get_if<MessageId>(&key.universalId)) {
|
||||||
return (*messageId > 0)
|
return (*messageId >= 0)
|
||||||
? ComputeId(key.peerId, *messageId)
|
? ComputeId(key.peerId, *messageId)
|
||||||
: ComputeId(key.migratedPeerId, -*messageId);
|
: ComputeId(key.migratedPeerId, ServerMaxMsgId + *messageId);
|
||||||
}
|
}
|
||||||
return *base::get_if<not_null<PhotoData*>>(&key.universalId);
|
return *base::get_if<not_null<PhotoData*>>(&key.universalId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,35 +171,35 @@ void ReportSpamPanel::setReported(bool reported, PeerData *onPeer) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryHider::HistoryHider(MainWidget *parent, const SelectedItemSet &items) : TWidget(parent)
|
HistoryHider::HistoryHider(MainWidget *parent, const SelectedItemSet &items) : RpWidget(parent)
|
||||||
, _forwardItems(items)
|
, _forwardItems(items)
|
||||||
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
|
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
|
||||||
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
|
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : TWidget(parent)
|
HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : RpWidget(parent)
|
||||||
, _sharedContact(sharedContact)
|
, _sharedContact(sharedContact)
|
||||||
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
|
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
|
||||||
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
|
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryHider::HistoryHider(MainWidget *parent) : TWidget(parent)
|
HistoryHider::HistoryHider(MainWidget *parent) : RpWidget(parent)
|
||||||
, _sendPath(true)
|
, _sendPath(true)
|
||||||
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
|
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
|
||||||
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
|
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryHider::HistoryHider(MainWidget *parent, const QString &botAndQuery) : TWidget(parent)
|
HistoryHider::HistoryHider(MainWidget *parent, const QString &botAndQuery) : RpWidget(parent)
|
||||||
, _botAndQuery(botAndQuery)
|
, _botAndQuery(botAndQuery)
|
||||||
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
|
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
|
||||||
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
|
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
|
||||||
init();
|
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)
|
, _shareUrl(url)
|
||||||
, _shareText(text)
|
, _shareText(text)
|
||||||
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
|
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
|
||||||
|
@ -210,17 +210,18 @@ HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString
|
||||||
void HistoryHider::init() {
|
void HistoryHider::init() {
|
||||||
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
|
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
|
||||||
if (!_forwardItems.empty()) {
|
if (!_forwardItems.empty()) {
|
||||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
Auth().data().itemRemoved()
|
||||||
for (auto i = _forwardItems.begin(); i != _forwardItems.end(); ++i) {
|
| rpl::start_with_next([this](auto item) {
|
||||||
if (i->get() == item) {
|
for (auto i = _forwardItems.begin(); i != _forwardItems.end(); ++i) {
|
||||||
i = _forwardItems.erase(i);
|
if (i->get() == item) {
|
||||||
break;
|
i = _forwardItems.erase(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (_forwardItems.empty()) {
|
||||||
if (_forwardItems.empty()) {
|
startHide();
|
||||||
startHide();
|
}
|
||||||
}
|
}, lifetime());
|
||||||
});
|
|
||||||
}
|
}
|
||||||
connect(_send, SIGNAL(clicked()), this, SLOT(forward()));
|
connect(_send, SIGNAL(clicked()), this, SLOT(forward()));
|
||||||
connect(_cancel, SIGNAL(clicked()), this, SLOT(startHide()));
|
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()));
|
connect(&_updateEditTimeLeftDisplay, SIGNAL(timeout()), this, SLOT(updateField()));
|
||||||
|
|
||||||
subscribe(Adaptive::Changed(), [this] { update(); });
|
subscribe(Adaptive::Changed(), [this] { update(); });
|
||||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
Auth().data().itemRemoved()
|
||||||
itemRemoved(item);
|
| 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) {
|
subscribe(Auth().data().contactsLoaded(), [this](bool) {
|
||||||
if (_peer) {
|
if (_peer) {
|
||||||
updateReportSpamStatus();
|
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();
|
orderWidgets();
|
||||||
}
|
}
|
||||||
|
@ -913,7 +929,7 @@ void HistoryWidget::updateHighlightedMessage() {
|
||||||
return stopMessageHighlight();
|
return stopMessageHighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ui::repaintHistoryItem(item);
|
Auth().data().requestItemRepaint(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeMs HistoryWidget::highlightStartTime(not_null<const HistoryItem*> item) const {
|
TimeMs HistoryWidget::highlightStartTime(not_null<const HistoryItem*> item) const {
|
||||||
|
@ -3272,7 +3288,7 @@ void HistoryWidget::app_sendBotCallback(const HistoryMessageReplyMarkup::Button
|
||||||
sendData = button->data;
|
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));
|
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) {
|
if (_replyToId == msg->id) {
|
||||||
cancelReply();
|
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 (info.row < markup->rows.size() && info.col < markup->rows.at(info.row).size()) {
|
||||||
if (markup->rows.at(info.row).at(info.col).requestId == req) {
|
if (markup->rows.at(info.row).at(info.col).requestId == req) {
|
||||||
markup->rows.at(info.row).at(info.col).requestId = 0;
|
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 (info.row < markup->rows.size() && info.col < markup->rows.at(info.row).size()) {
|
||||||
if (markup->rows.at(info.row).at(info.col).requestId == req) {
|
if (markup->rows.at(info.row).at(info.col).requestId == req) {
|
||||||
markup->rows.at(info.row).at(info.col).requestId = 0;
|
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()) {
|
if (!item->isPost()) {
|
||||||
updateSendAction(item->history(), SendAction::Type::UploadPhoto, 0);
|
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()) {
|
if (!item->isPost()) {
|
||||||
updateSendAction(item->history(), (document && document->voice()) ? SendAction::Type::UploadVoice : SendAction::Type::UploadFile, document ? document->uploadOffset : 0);
|
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) {
|
void HistoryWidget::onPhotoFailed(const FullMsgId &newId) {
|
||||||
HistoryItem *item = App::histItemById(newId);
|
if (auto item = App::histItemById(newId)) {
|
||||||
if (item) {
|
|
||||||
if (!item->isPost()) {
|
if (!item->isPost()) {
|
||||||
updateSendAction(item->history(), SendAction::Type::UploadPhoto, -1);
|
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()) {
|
if (!item->isPost()) {
|
||||||
updateSendAction(item->history(), (document && document->voice()) ? SendAction::Type::UploadVoice : SendAction::Type::UploadFile, -1);
|
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();
|
_topShadow->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::ui_repaintHistoryItem(not_null<const HistoryItem*> item) {
|
void HistoryWidget::repaintHistoryItem(
|
||||||
if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) {
|
not_null<const HistoryItem*> item) {
|
||||||
|
auto itemHistory = item->history();
|
||||||
|
if (itemHistory == _history || itemHistory == _migrated) {
|
||||||
auto ms = getms();
|
auto ms = getms();
|
||||||
if (_lastScrolled + kSkipRepaintWhileScrollMs <= ms) {
|
if (_lastScrolled + kSkipRepaintWhileScrollMs <= ms) {
|
||||||
_list->repaintItem(item);
|
_list->repaintItem(item);
|
||||||
} else {
|
} else {
|
||||||
_updateHistoryItems.start(_lastScrolled + kSkipRepaintWhileScrollMs - ms);
|
_updateHistoryItems.start(
|
||||||
|
_lastScrolled + kSkipRepaintWhileScrollMs - ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4611,12 +4629,6 @@ PeerData *HistoryWidget::ui_getPeerForMouseAction() {
|
||||||
return _peer;
|
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() {
|
void HistoryWidget::handlePendingHistoryUpdate() {
|
||||||
if (hasPendingResizedItems() || _updateHistoryGeometryRequired) {
|
if (hasPendingResizedItems() || _updateHistoryGeometryRequired) {
|
||||||
if (_list) {
|
if (_list) {
|
||||||
|
@ -4689,7 +4701,7 @@ void HistoryWidget::updateControlsGeometry() {
|
||||||
st::lineWidth);
|
st::lineWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::itemRemoved(HistoryItem *item) {
|
void HistoryWidget::itemRemoved(not_null<const HistoryItem*> item) {
|
||||||
if (item == _replyEditMsg) {
|
if (item == _replyEditMsg) {
|
||||||
if (_editMsgId) {
|
if (_editMsgId) {
|
||||||
cancelEdit();
|
cancelEdit();
|
||||||
|
@ -4707,6 +4719,17 @@ void HistoryWidget::itemRemoved(HistoryItem *item) {
|
||||||
onKbToggle();
|
onKbToggle();
|
||||||
_kbReplyTo = 0;
|
_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) {
|
void HistoryWidget::itemEdited(HistoryItem *item) {
|
||||||
|
@ -6148,7 +6171,6 @@ void HistoryWidget::updateForwarding() {
|
||||||
} else {
|
} else {
|
||||||
_toForward.clear();
|
_toForward.clear();
|
||||||
}
|
}
|
||||||
updateForwardingItemRemovedSubscription();
|
|
||||||
updateControlsVisibility();
|
updateControlsVisibility();
|
||||||
updateControlsGeometry();
|
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() {
|
void HistoryWidget::updateReplyToName() {
|
||||||
if (_editMsgId) return;
|
if (_editMsgId) return;
|
||||||
if (!_replyEditMsg && (_replyToId || !_kbReplyTo)) return;
|
if (!_replyEditMsg && (_replyToId || !_kbReplyTo)) return;
|
||||||
|
|
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "window/section_widget.h"
|
#include "window/section_widget.h"
|
||||||
#include "core/single_timer.h"
|
#include "core/single_timer.h"
|
||||||
#include "ui/widgets/input_fields.h"
|
#include "ui/widgets/input_fields.h"
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
#include "base/flags.h"
|
#include "base/flags.h"
|
||||||
|
|
||||||
namespace InlineBots {
|
namespace InlineBots {
|
||||||
|
@ -97,7 +98,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class HistoryHider : public TWidget, private base::Subscriber {
|
class HistoryHider : public Ui::RpWidget, private base::Subscriber {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -276,7 +277,6 @@ public:
|
||||||
void cancelEdit();
|
void cancelEdit();
|
||||||
void updateForwarding();
|
void updateForwarding();
|
||||||
void updateForwardingTexts();
|
void updateForwardingTexts();
|
||||||
void updateForwardingItemRemovedSubscription();
|
|
||||||
|
|
||||||
void clearReplyReturns();
|
void clearReplyReturns();
|
||||||
void pushReplyReturn(HistoryItem *item);
|
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 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();
|
PeerData *ui_getPeerForMouseAction();
|
||||||
|
|
||||||
void notify_historyItemLayoutChanged(const HistoryItem *item);
|
|
||||||
void notify_botCommandsChanged(UserData *user);
|
void notify_botCommandsChanged(UserData *user);
|
||||||
void notify_inlineBotRequesting(bool requesting);
|
void notify_inlineBotRequesting(bool requesting);
|
||||||
void notify_replyMarkupUpdated(const HistoryItem *item);
|
void notify_replyMarkupUpdated(const HistoryItem *item);
|
||||||
|
@ -480,6 +478,7 @@ private:
|
||||||
using TabbedPanel = ChatHelpers::TabbedPanel;
|
using TabbedPanel = ChatHelpers::TabbedPanel;
|
||||||
using TabbedSelector = ChatHelpers::TabbedSelector;
|
using TabbedSelector = ChatHelpers::TabbedSelector;
|
||||||
|
|
||||||
|
void repaintHistoryItem(not_null<const HistoryItem*> item);
|
||||||
void handlePendingHistoryUpdate();
|
void handlePendingHistoryUpdate();
|
||||||
void fullPeerUpdated(PeerData *peer);
|
void fullPeerUpdated(PeerData *peer);
|
||||||
void topBarClick();
|
void topBarClick();
|
||||||
|
@ -519,7 +518,7 @@ private:
|
||||||
// If an empty filepath is found we upload (possible) "image" with (possible) "content".
|
// 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 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,
|
// Updates position of controls around the message field,
|
||||||
// like send button, emoji button and others.
|
// like send button, emoji button and others.
|
||||||
|
@ -560,7 +559,6 @@ private:
|
||||||
SelectedItemSet _toForward;
|
SelectedItemSet _toForward;
|
||||||
Text _toForwardFrom, _toForwardText;
|
Text _toForwardFrom, _toForwardText;
|
||||||
int _toForwardNameVersion = 0;
|
int _toForwardNameVersion = 0;
|
||||||
int _forwardingItemRemovedSubscription = 0;
|
|
||||||
|
|
||||||
MsgId _editMsgId = 0;
|
MsgId _editMsgId = 0;
|
||||||
|
|
||||||
|
|
|
@ -218,10 +218,10 @@ void WrapWidget::showBackFromStack() {
|
||||||
if (!_historyStack.empty()) {
|
if (!_historyStack.empty()) {
|
||||||
auto last = std::move(_historyStack.back());
|
auto last = std::move(_historyStack.back());
|
||||||
_historyStack.pop_back();
|
_historyStack.pop_back();
|
||||||
_anotherTabMemento = std::move(last.anotherTab);
|
|
||||||
showNewContent(
|
showNewContent(
|
||||||
last.section.get(),
|
last.section.get(),
|
||||||
params);
|
params);
|
||||||
|
_anotherTabMemento = std::move(last.anotherTab);
|
||||||
} else {
|
} else {
|
||||||
controller()->showBackFromStack(params);
|
controller()->showBackFromStack(params);
|
||||||
}
|
}
|
||||||
|
@ -237,6 +237,7 @@ not_null<Ui::RpWidget*> WrapWidget::topWidget() const {
|
||||||
void WrapWidget::showContent(object_ptr<ContentWidget> content) {
|
void WrapWidget::showContent(object_ptr<ContentWidget> content) {
|
||||||
_content = std::move(content);
|
_content = std::move(content);
|
||||||
_content->show();
|
_content->show();
|
||||||
|
_anotherTabMemento = nullptr;
|
||||||
finishShowContent();
|
finishShowContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -187,8 +187,7 @@ Type InnerWidget::type() const {
|
||||||
void InnerWidget::visibleTopBottomUpdated(
|
void InnerWidget::visibleTopBottomUpdated(
|
||||||
int visibleTop,
|
int visibleTop,
|
||||||
int visibleBottom) {
|
int visibleBottom) {
|
||||||
_visibleTop = visibleTop;
|
setChildVisibleTopBottom(_list, visibleTop, visibleBottom);
|
||||||
_visibleBottom = visibleBottom;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InnerWidget::showInternal(not_null<Memento*> memento) {
|
bool InnerWidget::showInternal(not_null<Memento*> memento) {
|
||||||
|
|
|
@ -81,9 +81,6 @@ private:
|
||||||
object_ptr<Ui::PlainShadow> _otherTabsShadow = { nullptr };
|
object_ptr<Ui::PlainShadow> _otherTabsShadow = { nullptr };
|
||||||
object_ptr<ListWidget> _list = { nullptr };
|
object_ptr<ListWidget> _list = { nullptr };
|
||||||
|
|
||||||
int _visibleTop = 0;
|
|
||||||
int _visibleBottom = 0;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Media
|
} // namespace Media
|
||||||
|
|
|
@ -23,7 +23,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "overview/overview_layout.h"
|
#include "overview/overview_layout.h"
|
||||||
#include "history/history_media_types.h"
|
#include "history/history_media_types.h"
|
||||||
#include "window/themes/window_theme.h"
|
#include "window/themes/window_theme.h"
|
||||||
|
#include "storage/file_download.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
#include "auth_session.h"
|
||||||
#include "styles/style_overview.h"
|
#include "styles/style_overview.h"
|
||||||
#include "styles/style_info.h"
|
#include "styles/style_info.h"
|
||||||
|
|
||||||
|
@ -36,6 +38,21 @@ namespace {
|
||||||
constexpr auto kIdsLimit = 256;
|
constexpr auto kIdsLimit = 256;
|
||||||
|
|
||||||
using ItemBase = Layout::ItemBase;
|
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
|
} // namespace
|
||||||
|
|
||||||
|
@ -55,11 +72,30 @@ public:
|
||||||
return _items.empty();
|
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);
|
void resizeToWidth(int newWidth);
|
||||||
int height() const {
|
int height() const {
|
||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool removeItem(UniversalMsgId universalId);
|
||||||
|
base::optional<QRect> findItemRect(
|
||||||
|
UniversalMsgId universalId) const;
|
||||||
|
|
||||||
void paint(
|
void paint(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
QRect clip,
|
QRect clip,
|
||||||
|
@ -67,20 +103,33 @@ public:
|
||||||
TimeMs ms) const;
|
TimeMs ms) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
using Items = base::flat_map<
|
||||||
|
UniversalMsgId,
|
||||||
|
not_null<ItemBase*>,
|
||||||
|
std::greater<>>;
|
||||||
int headerHeight() const;
|
int headerHeight() const;
|
||||||
void appendItem(not_null<ItemBase*> item);
|
void appendItem(not_null<ItemBase*> item);
|
||||||
void setHeader(not_null<ItemBase*> item);
|
void setHeader(not_null<ItemBase*> item);
|
||||||
bool belongsHere(not_null<ItemBase*> item) const;
|
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;
|
Type _type = Type::Photo;
|
||||||
Text _header;
|
Text _header;
|
||||||
std::vector<not_null<ItemBase*>> _items;
|
Items _items;
|
||||||
int _itemsLeft = 0;
|
int _itemsLeft = 0;
|
||||||
int _itemsTop = 0;
|
int _itemsTop = 0;
|
||||||
int _itemWidth = 0;
|
int _itemWidth = 0;
|
||||||
int _itemsInRow = 1;
|
int _itemsInRow = 1;
|
||||||
int _rowsCount = 0;
|
mutable int _rowsCount = 0;
|
||||||
|
int _top = 0;
|
||||||
int _height = 0;
|
int _height = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -120,7 +169,7 @@ bool ListWidget::Section::belongsHere(
|
||||||
not_null<ItemBase*> item) const {
|
not_null<ItemBase*> item) const {
|
||||||
Expects(!_items.empty());
|
Expects(!_items.empty());
|
||||||
auto date = item->getItem()->date.date();
|
auto date = item->getItem()->date.date();
|
||||||
auto myDate = _items.back()->getItem()->date.date();
|
auto myDate = _items.back().second->getItem()->date.date();
|
||||||
|
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case Type::Photo:
|
case Type::Photo:
|
||||||
|
@ -142,25 +191,70 @@ bool ListWidget::Section::belongsHere(
|
||||||
Unexpected("Type in ListWidget::Section::belongsHere()");
|
Unexpected("Type in ListWidget::Section::belongsHere()");
|
||||||
}
|
}
|
||||||
|
|
||||||
int ListWidget::Section::countRowHeight(
|
void ListWidget::Section::appendItem(not_null<ItemBase*> item) {
|
||||||
not_null<ItemBase*> item) const {
|
_items.emplace(GetUniversalId(item), item);
|
||||||
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) {
|
bool ListWidget::Section::removeItem(UniversalMsgId universalId) {
|
||||||
_items.push_back(item);
|
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(
|
void ListWidget::Section::paint(
|
||||||
|
@ -169,9 +263,8 @@ void ListWidget::Section::paint(
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
TimeMs ms) const {
|
TimeMs ms) const {
|
||||||
auto baseIndex = 0;
|
auto baseIndex = 0;
|
||||||
auto top = _itemsTop;
|
|
||||||
auto header = headerHeight();
|
auto header = headerHeight();
|
||||||
if (header) {
|
if (QRect(0, 0, outerWidth, header).intersects(clip)) {
|
||||||
p.setPen(st::infoMediaHeaderFg);
|
p.setPen(st::infoMediaHeaderFg);
|
||||||
_header.drawLeftElided(
|
_header.drawLeftElided(
|
||||||
p,
|
p,
|
||||||
|
@ -179,14 +272,14 @@ void ListWidget::Section::paint(
|
||||||
st::infoMediaHeaderPosition.y(),
|
st::infoMediaHeaderPosition.y(),
|
||||||
outerWidth - 2 * st::infoMediaHeaderPosition.x(),
|
outerWidth - 2 * st::infoMediaHeaderPosition.x(),
|
||||||
outerWidth);
|
outerWidth);
|
||||||
top += header;
|
|
||||||
}
|
}
|
||||||
auto fromitem = floorclamp(
|
auto top = header + _itemsTop;
|
||||||
|
auto fromcol = floorclamp(
|
||||||
clip.x() - _itemsLeft,
|
clip.x() - _itemsLeft,
|
||||||
_itemWidth,
|
_itemWidth,
|
||||||
0,
|
0,
|
||||||
_itemsInRow);
|
_itemsInRow);
|
||||||
auto tillitem = ceilclamp(
|
auto tillcol = ceilclamp(
|
||||||
clip.x() + clip.width() - _itemsLeft,
|
clip.x() + clip.width() - _itemsLeft,
|
||||||
_itemWidth,
|
_itemWidth,
|
||||||
0,
|
0,
|
||||||
|
@ -194,35 +287,23 @@ void ListWidget::Section::paint(
|
||||||
Layout::PaintContext context(ms, false);
|
Layout::PaintContext context(ms, false);
|
||||||
context.isAfterDate = (header > 0);
|
context.isAfterDate = (header > 0);
|
||||||
|
|
||||||
// #TODO ranges, binary search for visible slice.
|
auto fromIt = findItemAfterTop(clip.y());
|
||||||
for (auto row = 0; row != _rowsCount; ++row) {
|
auto tillIt = findItemAfterBottom(
|
||||||
auto rowHeight = countRowHeight(_items[baseIndex]);
|
fromIt,
|
||||||
auto increment = gsl::finally([&] {
|
clip.y() + clip.height());
|
||||||
top += rowHeight;
|
for (auto it = fromIt; it != tillIt; ++it) {
|
||||||
baseIndex += _itemsInRow;
|
auto item = it->second;
|
||||||
context.isAfterDate = false;
|
auto rect = findItemRect(item);
|
||||||
});
|
context.isAfterDate = (header > 0)
|
||||||
|
&& (rect.y() <= header + _itemsTop);
|
||||||
if (top >= clip.y() + clip.height()) {
|
if (rect.intersects(clip)) {
|
||||||
break;
|
p.translate(rect.topLeft());
|
||||||
} 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);
|
|
||||||
item->paint(
|
item->paint(
|
||||||
p,
|
p,
|
||||||
clip.translated(-left, -top),
|
clip.translated(-rect.topLeft()),
|
||||||
TextSelection(),
|
TextSelection(),
|
||||||
&context);
|
&context);
|
||||||
p.translate(-left, -top);
|
p.translate(-rect.topLeft());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,7 +318,6 @@ void ListWidget::Section::resizeToWidth(int newWidth) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_height = headerHeight();
|
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case Type::Photo:
|
case Type::Photo:
|
||||||
case Type::Video:
|
case Type::Video:
|
||||||
|
@ -248,42 +328,70 @@ void ListWidget::Section::resizeToWidth(int newWidth) {
|
||||||
/ (st::infoMediaMinGridSize + st::infoMediaSkip);
|
/ (st::infoMediaMinGridSize + st::infoMediaSkip);
|
||||||
_itemWidth = ((newWidth - _itemsLeft) / _itemsInRow)
|
_itemWidth = ((newWidth - _itemsLeft) / _itemsInRow)
|
||||||
- st::infoMediaSkip;
|
- st::infoMediaSkip;
|
||||||
auto itemHeight = _itemWidth + st::infoMediaSkip;
|
for (auto &item : _items) {
|
||||||
_rowsCount = (int(_items.size()) + _itemsInRow - 1)
|
item.second->resizeGetHeight(_itemWidth);
|
||||||
/ _itemsInRow;
|
}
|
||||||
_height += _itemsTop + _rowsCount * itemHeight;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type::VoiceFile:
|
case Type::VoiceFile:
|
||||||
case Type::File:
|
case Type::File:
|
||||||
case Type::MusicFile: {
|
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::Link:
|
case Type::Link:
|
||||||
_itemsLeft = 0;
|
_itemsLeft = 0;
|
||||||
_itemsTop = 0;
|
_itemsTop = 0;
|
||||||
_itemsInRow = 1;
|
_itemsInRow = 1;
|
||||||
_itemWidth = newWidth;
|
_itemWidth = newWidth;
|
||||||
auto top = 0;
|
for (auto &item : _items) {
|
||||||
for (auto item : _items) {
|
item.second->resizeGetHeight(_itemWidth);
|
||||||
top += item->resizeGetHeight(_itemWidth);
|
|
||||||
}
|
}
|
||||||
_height += top;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_type != Type::Link) {
|
refreshHeight();
|
||||||
for (auto item : _items) {
|
}
|
||||||
item->resizeGetHeight(_itemWidth);
|
|
||||||
|
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(
|
ListWidget::ListWidget(
|
||||||
|
@ -296,13 +404,72 @@ ListWidget::ListWidget(
|
||||||
, _peer(peer)
|
, _peer(peer)
|
||||||
, _type(type)
|
, _type(type)
|
||||||
, _slice(sliceKey()) {
|
, _slice(sliceKey()) {
|
||||||
|
start();
|
||||||
refreshViewer();
|
refreshViewer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::start() {
|
||||||
ObservableViewer(*Window::Theme::Background())
|
ObservableViewer(*Window::Theme::Background())
|
||||||
| rpl::start_with_next([this](const auto &update) {
|
| rpl::start_with_next([this](const auto &update) {
|
||||||
if (update.paletteChanged()) {
|
if (update.paletteChanged()) {
|
||||||
invalidatePaletteCache();
|
invalidatePaletteCache();
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, 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() {
|
void ListWidget::invalidatePaletteCache() {
|
||||||
|
@ -314,9 +481,7 @@ void ListWidget::invalidatePaletteCache() {
|
||||||
SharedMediaMergedSlice::Key ListWidget::sliceKey() const {
|
SharedMediaMergedSlice::Key ListWidget::sliceKey() const {
|
||||||
auto universalId = _universalAroundId;
|
auto universalId = _universalAroundId;
|
||||||
using Key = SharedMediaMergedSlice::Key;
|
using Key = SharedMediaMergedSlice::Key;
|
||||||
if (auto migrateTo = _peer->migrateTo()) {
|
if (auto migrateFrom = _peer->migrateFrom()) {
|
||||||
return Key(migrateTo->id, _peer->id, _type, universalId);
|
|
||||||
} else if (auto migrateFrom = _peer->migrateFrom()) {
|
|
||||||
return Key(_peer->id, migrateFrom->id, _type, universalId);
|
return Key(_peer->id, migrateFrom->id, _type, universalId);
|
||||||
}
|
}
|
||||||
return Key(_peer->id, 0, _type, universalId);
|
return Key(_peer->id, 0, _type, universalId);
|
||||||
|
@ -338,11 +503,14 @@ int ListWidget::countIdsLimit() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemBase *ListWidget::getLayout(const FullMsgId &itemId) {
|
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 (it == _layouts.end()) {
|
||||||
if (auto layout = createLayout(itemId, _type)) {
|
if (auto layout = createLayout(itemId, _type)) {
|
||||||
layout->initDimensions();
|
layout->initDimensions();
|
||||||
it = _layouts.emplace(itemId, std::move(layout)).first;
|
it = _layouts.emplace(
|
||||||
|
universalId,
|
||||||
|
std::move(layout)).first;
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -372,34 +540,37 @@ std::unique_ptr<ItemBase> ListWidget::createLayout(
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto &fileSt = st::overviewFileLayout;
|
||||||
|
using namespace Layout;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::Photo:
|
case Type::Photo:
|
||||||
if (auto photo = getPhoto()) {
|
if (auto photo = getPhoto()) {
|
||||||
return std::make_unique<Layout::Photo>(photo, item);
|
return std::make_unique<Photo>(item, photo);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case Type::Video:
|
case Type::Video:
|
||||||
if (auto file = getFile()) {
|
if (auto file = getFile()) {
|
||||||
return std::make_unique<Layout::Video>(file, item);
|
return std::make_unique<Video>(item, file);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case Type::File:
|
case Type::File:
|
||||||
if (auto file = getFile()) {
|
if (auto file = getFile()) {
|
||||||
return std::make_unique<Layout::Document>(file, item, st::overviewFileLayout);
|
return std::make_unique<Document>(item, file, fileSt);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case Type::MusicFile:
|
case Type::MusicFile:
|
||||||
if (auto file = getFile()) {
|
if (auto file = getFile()) {
|
||||||
return std::make_unique<Layout::Document>(file, item, st::overviewFileLayout);
|
return std::make_unique<Document>(item, file, fileSt);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case Type::VoiceFile:
|
case Type::VoiceFile:
|
||||||
if (auto file = getFile()) {
|
if (auto file = getFile()) {
|
||||||
return std::make_unique<Layout::Voice>(file, item, st::overviewFileLayout);
|
return std::make_unique<Voice>(item, file, fileSt);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case Type::Link:
|
case Type::Link:
|
||||||
return std::make_unique<Layout::Link>(item->getMedia(), item);
|
return std::make_unique<Link>(item, item->getMedia());
|
||||||
case Type::RoundFile:
|
case Type::RoundFile:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -438,37 +609,60 @@ void ListWidget::markLayoutsStale() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ListWidget::resizeGetHeight(int newWidth) {
|
int ListWidget::resizeGetHeight(int newWidth) {
|
||||||
for (auto §ion : _sections) {
|
if (newWidth > 0) {
|
||||||
section.resizeToWidth(newWidth);
|
for (auto §ion : _sections) {
|
||||||
|
section.resizeToWidth(newWidth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return recountHeight();
|
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) {
|
void ListWidget::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
auto outerWidth = width();
|
auto outerWidth = width();
|
||||||
auto clip = e->rect();
|
auto clip = e->rect();
|
||||||
auto ms = getms();
|
auto ms = getms();
|
||||||
auto top = st::infoMediaMargin.top();
|
auto fromSectionIt = findSectionAfterTop(clip.y());
|
||||||
p.translate(0, top);
|
auto tillSectionIt = findSectionAfterBottom(
|
||||||
clip = clip.translated(0, -top);
|
fromSectionIt,
|
||||||
for (auto §ion : _sections) {
|
clip.y() + clip.height());
|
||||||
section.paint(p, clip, outerWidth, ms);
|
for (auto it = fromSectionIt; it != tillSectionIt; ++it) {
|
||||||
auto height = section.height();
|
auto top = it->top();
|
||||||
p.translate(0, height);
|
p.translate(0, top);
|
||||||
clip = clip.translated(0, -height);
|
it->paint(p, clip.translated(0, -top), outerWidth, ms);
|
||||||
|
p.translate(0, -top);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListWidget::refreshHeight() {
|
||||||
|
resize(width(), recountHeight());
|
||||||
|
}
|
||||||
|
|
||||||
int ListWidget::recountHeight() {
|
int ListWidget::recountHeight() {
|
||||||
auto result = 0;
|
auto cachedPadding = padding();
|
||||||
|
auto result = cachedPadding.top();
|
||||||
for (auto §ion : _sections) {
|
for (auto §ion : _sections) {
|
||||||
|
section.setTop(result);
|
||||||
result += section.height();
|
result += section.height();
|
||||||
}
|
}
|
||||||
return st::infoMediaMargin.top()
|
return result
|
||||||
+ result
|
+ cachedPadding.bottom();
|
||||||
+ st::infoMediaMargin.bottom();
|
}
|
||||||
|
|
||||||
|
void ListWidget::updateSelected() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::clearStaleLayouts() {
|
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 §ion, int universalId) {
|
||||||
|
return section.minId() > universalId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ListWidget::findSectionAfterTop(
|
||||||
|
int top) -> std::vector<Section>::iterator {
|
||||||
|
return base::lower_bound(
|
||||||
|
_sections,
|
||||||
|
top,
|
||||||
|
[](const Section §ion, 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 §ion, 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 §ion, int bottom) {
|
||||||
|
return section.top() < bottom;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ListWidget::~ListWidget() = default;
|
ListWidget::~ListWidget() = default;
|
||||||
|
|
||||||
} // namespace Media
|
} // namespace Media
|
||||||
|
|
|
@ -60,12 +60,34 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int resizeGetHeight(int newWidth) override;
|
int resizeGetHeight(int newWidth) override;
|
||||||
|
void visibleTopBottomUpdated(
|
||||||
|
int visibleTop,
|
||||||
|
int visibleBottom) override;
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using ItemBase = Overview::Layout::ItemBase;
|
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();
|
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 refreshViewer();
|
||||||
void invalidatePaletteCache();
|
void invalidatePaletteCache();
|
||||||
|
@ -79,24 +101,23 @@ private:
|
||||||
|
|
||||||
void markLayoutsStale();
|
void markLayoutsStale();
|
||||||
void clearStaleLayouts();
|
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<Window::Controller*> _controller;
|
||||||
not_null<PeerData*> _peer;
|
not_null<PeerData*> _peer;
|
||||||
Type _type = Type::Photo;
|
Type _type = Type::Photo;
|
||||||
|
|
||||||
MsgId _universalAroundId = ServerMaxMsgId - 1;
|
UniversalMsgId _universalAroundId = ServerMaxMsgId - 1;
|
||||||
SharedMediaMergedSlice _slice;
|
SharedMediaMergedSlice _slice;
|
||||||
|
|
||||||
struct CachedItem {
|
std::map<UniversalMsgId, CachedItem> _layouts;
|
||||||
CachedItem(std::unique_ptr<ItemBase> item);
|
|
||||||
~CachedItem();
|
|
||||||
|
|
||||||
std::unique_ptr<ItemBase> item;
|
|
||||||
bool stale = false;
|
|
||||||
};
|
|
||||||
std::map<FullMsgId, CachedItem> _layouts;
|
|
||||||
|
|
||||||
class Section;
|
|
||||||
std::vector<Section> _sections;
|
std::vector<Section> _sections;
|
||||||
|
|
||||||
rpl::lifetime _viewerLifetime;
|
rpl::lifetime _viewerLifetime;
|
||||||
|
|
|
@ -935,31 +935,6 @@ void MainWidget::notify_migrateUpdated(PeerData *peer) {
|
||||||
_history->notify_migrateUpdated(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) {
|
void MainWidget::notify_historyMuteUpdated(History *history) {
|
||||||
_dialogs->notify_historyMuteUpdated(history);
|
_dialogs->notify_historyMuteUpdated(history);
|
||||||
}
|
}
|
||||||
|
@ -1873,7 +1848,7 @@ void MainWidget::handleAudioUpdate(const AudioMsgId &audioId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto item = App::histItemById(audioId.contextId())) {
|
if (auto item = App::histItemById(audioId.contextId())) {
|
||||||
Ui::repaintHistoryItem(item);
|
Auth().data().requestItemRepaint(item);
|
||||||
item->audioTrackUpdated();
|
item->audioTrackUpdated();
|
||||||
}
|
}
|
||||||
if (auto items = InlineBots::Layout::documentItems()) {
|
if (auto items = InlineBots::Layout::documentItems()) {
|
||||||
|
@ -2046,7 +2021,7 @@ void MainWidget::documentLoadProgress(DocumentData *document) {
|
||||||
auto i = items.constFind(document);
|
auto i = items.constFind(document);
|
||||||
if (i != items.cend()) {
|
if (i != items.cend()) {
|
||||||
for_const (auto item, i.value()) {
|
for_const (auto item, i.value()) {
|
||||||
Ui::repaintHistoryItem(item);
|
Auth().data().requestItemRepaint(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Auth().documentUpdated.notify(document, true);
|
Auth().documentUpdated.notify(document, true);
|
||||||
|
@ -5301,7 +5276,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||||
msgRow->history()->unregSendAction(App::self());
|
msgRow->history()->unregSendAction(App::self());
|
||||||
}
|
}
|
||||||
App::historyRegItem(msgRow);
|
App::historyRegItem(msgRow);
|
||||||
Ui::repaintHistoryItem(msgRow);
|
Auth().data().requestItemRepaint(msgRow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
App::historyUnregRandom(d.vrandom_id.v);
|
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 (auto item = App::histItemById(channel, msgId.v)) {
|
||||||
if (item->isMediaUnread()) {
|
if (item->isMediaUnread()) {
|
||||||
item->markMediaRead();
|
item->markMediaRead();
|
||||||
Ui::repaintHistoryItem(item);
|
Auth().data().requestItemRepaint(item);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Perhaps it was an unread mention!
|
// Perhaps it was an unread mention!
|
||||||
|
|
|
@ -340,7 +340,6 @@ public:
|
||||||
|
|
||||||
void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col);
|
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(
|
void ui_showPeerHistory(
|
||||||
PeerId peer,
|
PeerId peer,
|
||||||
const SectionShow ¶ms,
|
const SectionShow ¶ms,
|
||||||
|
@ -355,7 +354,6 @@ public:
|
||||||
void notify_userIsBotChanged(UserData *bot);
|
void notify_userIsBotChanged(UserData *bot);
|
||||||
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
|
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
|
||||||
void notify_migrateUpdated(PeerData *peer);
|
void notify_migrateUpdated(PeerData *peer);
|
||||||
void notify_historyItemLayoutChanged(const HistoryItem *item);
|
|
||||||
void notify_historyMuteUpdated(History *history);
|
void notify_historyMuteUpdated(History *history);
|
||||||
|
|
||||||
bool cmd_search();
|
bool cmd_search();
|
||||||
|
|
|
@ -21,17 +21,23 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "media/player/media_player_float.h"
|
#include "media/player/media_player_float.h"
|
||||||
|
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "styles/style_media_player.h"
|
|
||||||
#include "history/history_media.h"
|
#include "history/history_media.h"
|
||||||
#include "media/media_clip_reader.h"
|
#include "media/media_clip_reader.h"
|
||||||
#include "media/view/media_clip_playback.h"
|
#include "media/view/media_clip_playback.h"
|
||||||
#include "media/media_audio.h"
|
#include "media/media_audio.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "styles/style_media_player.h"
|
||||||
#include "styles/style_history.h"
|
#include "styles/style_history.h"
|
||||||
|
|
||||||
namespace Media {
|
namespace Media {
|
||||||
namespace Player {
|
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)
|
, _item(item)
|
||||||
, _toggleCallback(std::move(toggleCallback))
|
, _toggleCallback(std::move(toggleCallback))
|
||||||
, _draggedCallback(std::move(draggedCallback)) {
|
, _draggedCallback(std::move(draggedCallback)) {
|
||||||
|
@ -48,11 +54,25 @@ Float::Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible)
|
||||||
|
|
||||||
prepareShadow();
|
prepareShadow();
|
||||||
|
|
||||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
// #TODO rpl::merge
|
||||||
if (_item == item) {
|
Auth().data().itemLayoutChanged()
|
||||||
detach();
|
| 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);
|
setCursor(style::cur_pointer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
namespace Media {
|
namespace Media {
|
||||||
namespace Clip {
|
namespace Clip {
|
||||||
class Playback;
|
class Playback;
|
||||||
|
@ -27,7 +29,7 @@ class Playback;
|
||||||
|
|
||||||
namespace Player {
|
namespace Player {
|
||||||
|
|
||||||
class Float : public TWidget, private base::Subscriber {
|
class Float : public Ui::RpWidget, private base::Subscriber {
|
||||||
public:
|
public:
|
||||||
Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible)> toggleCallback, base::lambda<void(bool closed)> draggedCallback);
|
Float(QWidget *parent, HistoryItem *item, base::lambda<void(bool visible)> toggleCallback, base::lambda<void(bool closed)> draggedCallback);
|
||||||
|
|
||||||
|
@ -59,11 +61,6 @@ public:
|
||||||
finishDrag(false);
|
finishDrag(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ui_repaintHistoryItem(not_null<const HistoryItem*> item) {
|
|
||||||
if (item == _item) {
|
|
||||||
repaintItem();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
|
@ -24,17 +24,25 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "overview/overview_layout.h"
|
#include "overview/overview_layout.h"
|
||||||
#include "styles/style_media_player.h"
|
#include "styles/style_media_player.h"
|
||||||
#include "history/history_media.h"
|
#include "history/history_media.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace Media {
|
namespace Media {
|
||||||
namespace Player {
|
namespace Player {
|
||||||
|
|
||||||
ListWidget::ListWidget(QWidget *parent) : TWidget(parent) {
|
ListWidget::ListWidget(QWidget *parent) : RpWidget(parent) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
playlistUpdated();
|
playlistUpdated();
|
||||||
subscribe(instance()->playlistChangedNotifier(), [this](AudioMsgId::Type type) { playlistUpdated(); });
|
subscribe(
|
||||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
instance()->playlistChangedNotifier(),
|
||||||
itemRemoved(item);
|
[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() {
|
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) {
|
void ListWidget::repaintItem(const HistoryItem *item) {
|
||||||
if (!item) return;
|
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());
|
auto layoutIt = _layouts.find(item->fullId());
|
||||||
if (layoutIt != _layouts.cend()) {
|
if (layoutIt != _layouts.cend()) {
|
||||||
auto layout = layoutIt.value();
|
auto layout = layoutIt.value();
|
||||||
|
@ -204,7 +208,7 @@ void ListWidget::playlistUpdated() {
|
||||||
if (auto item = App::histItemById(msgId)) {
|
if (auto item = App::histItemById(msgId)) {
|
||||||
if (auto media = item->getMedia()) {
|
if (auto media = item->getMedia()) {
|
||||||
if (media->type() == MediaTypeMusicFile) {
|
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();
|
layoutIt.value()->initDimensions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
namespace Overview {
|
namespace Overview {
|
||||||
namespace Layout {
|
namespace Layout {
|
||||||
class Document;
|
class Document;
|
||||||
|
@ -29,12 +31,10 @@ class Document;
|
||||||
namespace Media {
|
namespace Media {
|
||||||
namespace Player {
|
namespace Player {
|
||||||
|
|
||||||
class ListWidget : public TWidget, private base::Subscriber {
|
class ListWidget : public Ui::RpWidget, private base::Subscriber {
|
||||||
public:
|
public:
|
||||||
ListWidget(QWidget *parent);
|
ListWidget(QWidget *parent);
|
||||||
|
|
||||||
void ui_repaintHistoryItem(not_null<const HistoryItem*> item);
|
|
||||||
|
|
||||||
QRect getCurrentTrackGeometry() const;
|
QRect getCurrentTrackGeometry() const;
|
||||||
|
|
||||||
~ListWidget();
|
~ListWidget();
|
||||||
|
@ -48,7 +48,7 @@ protected:
|
||||||
int resizeGetHeight(int newWidth) override;
|
int resizeGetHeight(int newWidth) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void itemRemoved(HistoryItem *item);
|
void itemRemoved(not_null<const HistoryItem*> item);
|
||||||
int marginTop() const;
|
int marginTop() const;
|
||||||
void repaintItem(const HistoryItem *item);
|
void repaintItem(const HistoryItem *item);
|
||||||
void playlistUpdated();
|
void playlistUpdated();
|
||||||
|
|
|
@ -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 {
|
int Panel::bestPositionFor(int left) const {
|
||||||
left -= contentLeft();
|
left -= contentLeft();
|
||||||
left -= st::mediaPlayerFileLayout.songPadding.left();
|
left -= st::mediaPlayerFileLayout.songPadding.left();
|
||||||
|
|
|
@ -52,8 +52,6 @@ public:
|
||||||
void setPinCallback(ButtonCallback &&callback);
|
void setPinCallback(ButtonCallback &&callback);
|
||||||
void setCloseCallback(ButtonCallback &&callback);
|
void setCloseCallback(ButtonCallback &&callback);
|
||||||
|
|
||||||
void ui_repaintHistoryItem(not_null<const HistoryItem*> item);
|
|
||||||
|
|
||||||
int bestPositionFor(int left) const;
|
int bestPositionFor(int left) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -1023,7 +1023,7 @@ base::optional<MediaView::SharedMediaKey> MediaView::sharedMediaKey() const {
|
||||||
_history->peer->id,
|
_history->peer->id,
|
||||||
_migrated ? _migrated->peer->id : 0,
|
_migrated ? _migrated->peer->id : 0,
|
||||||
type,
|
type,
|
||||||
(_msgid.channel == _history->channelId()) ? _msgid.msg : -_msgid.msg };
|
(_msgid.channel == _history->channelId()) ? _msgid.msg : (_msgid.msg - ServerMaxMsgId) };
|
||||||
};
|
};
|
||||||
return
|
return
|
||||||
sharedMediaType()
|
sharedMediaType()
|
||||||
|
|
|
@ -67,30 +67,40 @@ TextWithEntities ComposeNameWithEntities(DocumentData *document) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ItemBase::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
void ItemBase::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
||||||
App::hoveredLinkItem(active ? _parent : nullptr);
|
App::hoveredLinkItem(active ? _parent.get() : nullptr);
|
||||||
Ui::repaintHistoryItem(_parent);
|
Auth().data().requestItemRepaint(_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemBase::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
|
void ItemBase::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
|
||||||
App::pressedLinkItem(pressed ? _parent : nullptr);
|
App::pressedLinkItem(pressed ? _parent.get() : nullptr);
|
||||||
Ui::repaintHistoryItem(_parent);
|
Auth().data().requestItemRepaint(_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RadialProgressItem::setDocumentLinks(DocumentData *document) {
|
void RadialProgressItem::setDocumentLinks(
|
||||||
ClickHandlerPtr save;
|
not_null<DocumentData*> document) {
|
||||||
if (document->voice()) {
|
auto createSaveHandler = [](
|
||||||
save.reset(new DocumentOpenClickHandler(document));
|
not_null<DocumentData*> document
|
||||||
} else {
|
) -> ClickHandlerPtr {
|
||||||
save.reset(new DocumentSaveClickHandler(document));
|
if (document->voice()) {
|
||||||
}
|
return MakeShared<DocumentOpenClickHandler>(document);
|
||||||
setLinks(MakeShared<DocumentOpenClickHandler>(document), std::move(save), MakeShared<DocumentCancelClickHandler>(document));
|
}
|
||||||
|
return MakeShared<DocumentSaveClickHandler>(document);
|
||||||
|
};
|
||||||
|
setLinks(
|
||||||
|
MakeShared<DocumentOpenClickHandler>(document),
|
||||||
|
createSaveHandler(document),
|
||||||
|
MakeShared<DocumentCancelClickHandler>(document));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RadialProgressItem::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
void RadialProgressItem::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
||||||
ItemBase::clickHandlerActiveChanged(action, active);
|
ItemBase::clickHandlerActiveChanged(action, active);
|
||||||
if (action == _openl || action == _savel || action == _cancell) {
|
if (action == _openl || action == _savel || action == _cancell) {
|
||||||
if (iconAnimated()) {
|
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) {
|
void RadialProgressItem::step_radial(TimeMs ms, bool timer) {
|
||||||
if (timer) {
|
if (timer) {
|
||||||
Ui::repaintHistoryItem(_parent);
|
Auth().data().requestItemRepaint(_parent);
|
||||||
} else {
|
} else {
|
||||||
_radial->update(dataProgress(), dataFinished(), ms);
|
_radial->update(dataProgress(), dataFinished(), ms);
|
||||||
if (!_radial->animating()) {
|
if (!_radial->animating()) {
|
||||||
|
@ -221,9 +231,12 @@ void PhotoVideoCheckbox::startAnimation() {
|
||||||
_pression.start(_updateCallback, showPressed ? 0. : 1., showPressed ? 1. : 0., st::overviewCheck.duration);
|
_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)
|
, _data(photo)
|
||||||
, _link(new PhotoOpenClickHandler(photo)) {
|
, _link(MakeShared<PhotoOpenClickHandler>(photo)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Photo::initDimensions() {
|
void Photo::initDimensions() {
|
||||||
|
@ -289,7 +302,7 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
||||||
|
|
||||||
void Photo::ensureCheckboxCreated() {
|
void Photo::ensureCheckboxCreated() {
|
||||||
if (!_check) _check = std::make_unique<PhotoVideoCheckbox>([this] {
|
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)
|
, _data(video)
|
||||||
, _duration(formatDurationText(_data->duration()))
|
, _duration(formatDurationText(_data->duration()))
|
||||||
, _thumbLoaded(false) {
|
, _thumbLoaded(false) {
|
||||||
|
@ -449,7 +465,7 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
||||||
|
|
||||||
void Video::ensureCheckboxCreated() {
|
void Video::ensureCheckboxCreated() {
|
||||||
if (!_check) _check = std::make_unique<PhotoVideoCheckbox>([this] {
|
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)
|
, _data(voice)
|
||||||
, _namel(new DocumentOpenClickHandler(_data))
|
, _namel(MakeShared<DocumentOpenClickHandler>(_data))
|
||||||
, _st(st) {
|
, _st(st) {
|
||||||
AddComponents(Info::Bit());
|
AddComponents(Info::Bit());
|
||||||
|
|
||||||
|
@ -722,10 +742,14 @@ bool Voice::updateStatusText() {
|
||||||
return showPause;
|
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)
|
, _data(document)
|
||||||
, _msgl(goToMessageClickHandler(parent))
|
, _msgl(goToMessageClickHandler(parent))
|
||||||
, _namel(new DocumentOpenClickHandler(_data))
|
, _namel(MakeShared<DocumentOpenClickHandler>(_data))
|
||||||
, _st(st)
|
, _st(st)
|
||||||
, _date(langDateTime(date(_data->date)))
|
, _date(langDateTime(date(_data->date)))
|
||||||
, _datew(st::normalFont->width(_date))
|
, _datew(st::normalFont->width(_date))
|
||||||
|
@ -1037,7 +1061,10 @@ bool Document::updateStatusText() {
|
||||||
return showPause;
|
return showPause;
|
||||||
}
|
}
|
||||||
|
|
||||||
Link::Link(HistoryMedia *media, HistoryItem *parent) : ItemBase(parent) {
|
Link::Link(
|
||||||
|
not_null<HistoryItem*> parent,
|
||||||
|
HistoryMedia *media)
|
||||||
|
: ItemBase(parent) {
|
||||||
AddComponents(Info::Bit());
|
AddComponents(Info::Bit());
|
||||||
|
|
||||||
auto textWithEntities = _parent->originalText();
|
auto textWithEntities = _parent->originalText();
|
||||||
|
|
|
@ -66,7 +66,14 @@ public:
|
||||||
|
|
||||||
class ItemBase : public AbstractItem {
|
class ItemBase : public AbstractItem {
|
||||||
public:
|
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 {
|
ItemBase *toMediaItem() final override {
|
||||||
|
@ -83,13 +90,14 @@ public:
|
||||||
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
|
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HistoryItem *_parent;
|
not_null<HistoryItem*> _parent = nullptr;
|
||||||
|
int _position = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RadialProgressItem : public ItemBase {
|
class RadialProgressItem : public ItemBase {
|
||||||
public:
|
public:
|
||||||
RadialProgressItem(HistoryItem *parent) : ItemBase(parent) {
|
RadialProgressItem(not_null<HistoryItem*> parent) : ItemBase(parent) {
|
||||||
}
|
}
|
||||||
RadialProgressItem(const RadialProgressItem &other) = delete;
|
RadialProgressItem(const RadialProgressItem &other) = delete;
|
||||||
|
|
||||||
|
@ -99,8 +107,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ClickHandlerPtr _openl, _savel, _cancell;
|
ClickHandlerPtr _openl, _savel, _cancell;
|
||||||
void setLinks(ClickHandlerPtr &&openl, ClickHandlerPtr &&savel, ClickHandlerPtr &&cancell);
|
void setLinks(
|
||||||
void setDocumentLinks(DocumentData *document);
|
ClickHandlerPtr &&openl,
|
||||||
|
ClickHandlerPtr &&savel,
|
||||||
|
ClickHandlerPtr &&cancell);
|
||||||
|
void setDocumentLinks(not_null<DocumentData*> document);
|
||||||
|
|
||||||
void step_radial(TimeMs ms, bool timer);
|
void step_radial(TimeMs ms, bool timer);
|
||||||
|
|
||||||
|
@ -171,7 +182,9 @@ class PhotoVideoCheckbox;
|
||||||
|
|
||||||
class Photo : public ItemBase {
|
class Photo : public ItemBase {
|
||||||
public:
|
public:
|
||||||
Photo(PhotoData *photo, HistoryItem *parent);
|
Photo(
|
||||||
|
not_null<HistoryItem*> parent,
|
||||||
|
not_null<PhotoData*> photo);
|
||||||
|
|
||||||
void initDimensions() override;
|
void initDimensions() override;
|
||||||
int32 resizeGetHeight(int32 width) override;
|
int32 resizeGetHeight(int32 width) override;
|
||||||
|
@ -188,7 +201,7 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<PhotoVideoCheckbox> _check;
|
std::unique_ptr<PhotoVideoCheckbox> _check;
|
||||||
|
|
||||||
PhotoData *_data;
|
not_null<PhotoData*> _data;
|
||||||
ClickHandlerPtr _link;
|
ClickHandlerPtr _link;
|
||||||
|
|
||||||
QPixmap _pix;
|
QPixmap _pix;
|
||||||
|
@ -198,7 +211,9 @@ private:
|
||||||
|
|
||||||
class Video : public RadialProgressItem {
|
class Video : public RadialProgressItem {
|
||||||
public:
|
public:
|
||||||
Video(DocumentData *video, HistoryItem *parent);
|
Video(
|
||||||
|
not_null<HistoryItem*> parent,
|
||||||
|
not_null<DocumentData*> video);
|
||||||
|
|
||||||
void initDimensions() override;
|
void initDimensions() override;
|
||||||
int32 resizeGetHeight(int32 width) override;
|
int32 resizeGetHeight(int32 width) override;
|
||||||
|
@ -221,7 +236,7 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<PhotoVideoCheckbox> _check;
|
std::unique_ptr<PhotoVideoCheckbox> _check;
|
||||||
|
|
||||||
DocumentData *_data;
|
not_null<DocumentData*> _data;
|
||||||
StatusText _status;
|
StatusText _status;
|
||||||
|
|
||||||
QString _duration;
|
QString _duration;
|
||||||
|
@ -234,7 +249,10 @@ private:
|
||||||
|
|
||||||
class Voice : public RadialProgressItem {
|
class Voice : public RadialProgressItem {
|
||||||
public:
|
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 initDimensions() override;
|
||||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||||
|
@ -247,7 +265,7 @@ protected:
|
||||||
bool iconAnimated() const override;
|
bool iconAnimated() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DocumentData *_data;
|
not_null<DocumentData*> _data;
|
||||||
StatusText _status;
|
StatusText _status;
|
||||||
ClickHandlerPtr _namel;
|
ClickHandlerPtr _namel;
|
||||||
|
|
||||||
|
@ -263,7 +281,10 @@ private:
|
||||||
|
|
||||||
class Document : public RadialProgressItem {
|
class Document : public RadialProgressItem {
|
||||||
public:
|
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 initDimensions() override;
|
||||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||||
|
@ -280,7 +301,7 @@ protected:
|
||||||
bool iconAnimated() const override;
|
bool iconAnimated() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DocumentData *_data;
|
not_null<DocumentData*> _data;
|
||||||
StatusText _status;
|
StatusText _status;
|
||||||
ClickHandlerPtr _msgl, _namel;
|
ClickHandlerPtr _msgl, _namel;
|
||||||
|
|
||||||
|
@ -301,7 +322,9 @@ private:
|
||||||
|
|
||||||
class Link : public ItemBase {
|
class Link : public ItemBase {
|
||||||
public:
|
public:
|
||||||
Link(HistoryMedia *media, HistoryItem *parent);
|
Link(
|
||||||
|
not_null<HistoryItem*> parent,
|
||||||
|
HistoryMedia *media);
|
||||||
|
|
||||||
void initDimensions() override;
|
void initDimensions() override;
|
||||||
int32 resizeGetHeight(int32 width) override;
|
int32 resizeGetHeight(int32 width) override;
|
||||||
|
|
|
@ -67,9 +67,6 @@ OverviewInner::OverviewInner(OverviewWidget *overview, Ui::ScrollArea *scroll, P
|
||||||
, _itemsToBeLoaded(LinksOverviewPerPage * 2)
|
, _itemsToBeLoaded(LinksOverviewPerPage * 2)
|
||||||
, _width(st::columnMinimalWidthMain) {
|
, _width(st::columnMinimalWidthMain) {
|
||||||
subscribe(Auth().downloader().taskFinished(), [this] { update(); });
|
subscribe(Auth().downloader().taskFinished(), [this] { update(); });
|
||||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
|
||||||
itemRemoved(item);
|
|
||||||
});
|
|
||||||
|
|
||||||
resize(_width, st::windowMinHeight);
|
resize(_width, st::windowMinHeight);
|
||||||
|
|
||||||
|
@ -1891,34 +1888,34 @@ Overview::Layout::ItemBase *OverviewInner::layoutPrepare(HistoryItem *item) {
|
||||||
if (_type == OverviewPhotos) {
|
if (_type == OverviewPhotos) {
|
||||||
if (media && media->type() == MediaTypePhoto) {
|
if (media && media->type() == MediaTypePhoto) {
|
||||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
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();
|
i.value()->initDimensions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (_type == OverviewVideos) {
|
} else if (_type == OverviewVideos) {
|
||||||
if (media && media->type() == MediaTypeVideo) {
|
if (media && media->type() == MediaTypeVideo) {
|
||||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
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();
|
i.value()->initDimensions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (_type == OverviewVoiceFiles) {
|
} else if (_type == OverviewVoiceFiles) {
|
||||||
if (media && (media->type() == MediaTypeVoiceFile)) {
|
if (media && (media->type() == MediaTypeVoiceFile)) {
|
||||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
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();
|
i.value()->initDimensions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (_type == OverviewFiles || _type == OverviewMusicFiles) {
|
} else if (_type == OverviewFiles || _type == OverviewMusicFiles) {
|
||||||
if (media && (media->type() == MediaTypeFile || media->type() == MediaTypeMusicFile || media->type() == MediaTypeGif)) {
|
if (media && (media->type() == MediaTypeFile || media->type() == MediaTypeMusicFile || media->type() == MediaTypeGif)) {
|
||||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
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();
|
i.value()->initDimensions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (_type == OverviewLinks) {
|
} else if (_type == OverviewLinks) {
|
||||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
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();
|
i.value()->initDimensions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2293,18 +2290,6 @@ void OverviewWidget::grabFinish() {
|
||||||
_topShadow->show();
|
_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 {
|
SelectedItemSet OverviewWidget::getSelectedItems() const {
|
||||||
return _inner->getSelectedItems();
|
return _inner->getSelectedItems();
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,10 +352,6 @@ public:
|
||||||
bool wheelEventFromFloatPlayer(QEvent *e) override;
|
bool wheelEventFromFloatPlayer(QEvent *e) override;
|
||||||
QRect rectForFloatPlayer() const override;
|
QRect rectForFloatPlayer() const override;
|
||||||
|
|
||||||
void ui_repaintHistoryItem(not_null<const HistoryItem*> item);
|
|
||||||
|
|
||||||
void notify_historyItemLayoutChanged(const HistoryItem *item);
|
|
||||||
|
|
||||||
~OverviewWidget();
|
~OverviewWidget();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -3162,7 +3162,7 @@ public:
|
||||||
auto i = items.constFind(_doc);
|
auto i = items.constFind(_doc);
|
||||||
if (i != items.cend()) {
|
if (i != items.cend()) {
|
||||||
for_const (auto item, i.value()) {
|
for_const (auto item, i.value()) {
|
||||||
Ui::repaintHistoryItem(item);
|
Auth().data().requestItemRepaint(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ public:
|
||||||
void remove(SharedMediaRemoveOne &&query);
|
void remove(SharedMediaRemoveOne &&query);
|
||||||
void remove(SharedMediaRemoveAll &&query);
|
void remove(SharedMediaRemoveAll &&query);
|
||||||
rpl::producer<SharedMediaResult> query(SharedMediaQuery &&query) const;
|
rpl::producer<SharedMediaResult> query(SharedMediaQuery &&query) const;
|
||||||
|
|
||||||
rpl::producer<SharedMediaSliceUpdate> sharedMediaSliceUpdated() const;
|
rpl::producer<SharedMediaSliceUpdate> sharedMediaSliceUpdated() const;
|
||||||
rpl::producer<SharedMediaRemoveOne> sharedMediaOneRemoved() const;
|
rpl::producer<SharedMediaRemoveOne> sharedMediaOneRemoved() const;
|
||||||
rpl::producer<SharedMediaRemoveAll> sharedMediaAllRemoved() const;
|
rpl::producer<SharedMediaRemoveAll> sharedMediaAllRemoved() const;
|
||||||
|
@ -43,7 +42,6 @@ public:
|
||||||
void remove(UserPhotosRemoveOne &&query);
|
void remove(UserPhotosRemoveOne &&query);
|
||||||
void remove(UserPhotosRemoveAfter &&query);
|
void remove(UserPhotosRemoveAfter &&query);
|
||||||
rpl::producer<UserPhotosResult> query(UserPhotosQuery &&query) const;
|
rpl::producer<UserPhotosResult> query(UserPhotosQuery &&query) const;
|
||||||
|
|
||||||
rpl::producer<UserPhotosSliceUpdate> userPhotosSliceUpdated() const;
|
rpl::producer<UserPhotosSliceUpdate> userPhotosSliceUpdated() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -122,11 +122,11 @@ private:
|
||||||
QRect _bar;
|
QRect _bar;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SplittedWidget : public TWidget {
|
class SplittedWidget : public Ui::RpWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SplittedWidget(QWidget *parent) : TWidget(parent) {
|
SplittedWidget(QWidget *parent) : RpWidget(parent) {
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
}
|
}
|
||||||
void setHeight(int32 newHeight) {
|
void setHeight(int32 newHeight) {
|
||||||
|
|
Loading…
Reference in New Issue