mirror of https://github.com/procxx/kepka.git
Use plain HistoryItem in channel admin events log.
Instead of using a complex AdminLog::Item use just HistoryItem*.
This commit is contained in:
parent
e39b95175b
commit
5c87b42135
|
@ -63,6 +63,16 @@ public:
|
||||||
base::Observable<gsl::not_null<const HistoryItem*>> &repaintLogEntry() {
|
base::Observable<gsl::not_null<const HistoryItem*>> &repaintLogEntry() {
|
||||||
return _repaintLogEntry;
|
return _repaintLogEntry;
|
||||||
}
|
}
|
||||||
|
base::Observable<void> &pendingHistoryResize() {
|
||||||
|
return _pendingHistoryResize;
|
||||||
|
}
|
||||||
|
struct ItemVisibilityQuery {
|
||||||
|
gsl::not_null<HistoryItem*> item;
|
||||||
|
gsl::not_null<bool*> isVisible;
|
||||||
|
};
|
||||||
|
base::Observable<ItemVisibilityQuery> &queryItemVisibility() {
|
||||||
|
return _queryItemVisibility;
|
||||||
|
}
|
||||||
|
|
||||||
void copyFrom(const AuthSessionData &other) {
|
void copyFrom(const AuthSessionData &other) {
|
||||||
_variables = other._variables;
|
_variables = other._variables;
|
||||||
|
@ -139,6 +149,8 @@ private:
|
||||||
base::Observable<void> _savedGifsUpdated;
|
base::Observable<void> _savedGifsUpdated;
|
||||||
base::Observable<gsl::not_null<History*>> _historyCleared;
|
base::Observable<gsl::not_null<History*>> _historyCleared;
|
||||||
base::Observable<gsl::not_null<const HistoryItem*>> _repaintLogEntry;
|
base::Observable<gsl::not_null<const HistoryItem*>> _repaintLogEntry;
|
||||||
|
base::Observable<void> _pendingHistoryResize;
|
||||||
|
base::Observable<ItemVisibilityQuery> _queryItemVisibility;
|
||||||
Variables _variables;
|
Variables _variables;
|
||||||
TimeMs _lastTimeVideoPlayedAt = 0;
|
TimeMs _lastTimeVideoPlayedAt = 0;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "messenger.h"
|
#include "messenger.h"
|
||||||
|
#include "auth_session.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "layerwidget.h"
|
#include "layerwidget.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
@ -368,9 +369,8 @@ void historyMuteUpdated(History *history) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handlePendingHistoryUpdate() {
|
void handlePendingHistoryUpdate() {
|
||||||
if (auto main = App::main()) {
|
AuthSession::Current().data().pendingHistoryResize().notify(true);
|
||||||
main->notify_handlePendingHistoryUpdate();
|
|
||||||
}
|
|
||||||
for (auto item : base::take(Global::RefPendingRepaintItems())) {
|
for (auto item : base::take(Global::RefPendingRepaintItems())) {
|
||||||
Ui::repaintHistoryItem(item);
|
Ui::repaintHistoryItem(item);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "styles/style_history.h"
|
#include "styles/style_history.h"
|
||||||
#include "history/history_media_types.h"
|
#include "history/history_media_types.h"
|
||||||
#include "history/history_admin_log_item.h"
|
|
||||||
#include "history/history_admin_log_section.h"
|
#include "history/history_admin_log_section.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
|
@ -46,9 +45,18 @@ InnerWidget::InnerWidget(QWidget *parent, gsl::not_null<Window::Controller*> con
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
|
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
|
||||||
subscribe(AuthSession::Current().data().repaintLogEntry(), [this](gsl::not_null<const HistoryItem*> historyItem) {
|
subscribe(AuthSession::Current().data().repaintLogEntry(), [this](gsl::not_null<const HistoryItem*> historyItem) {
|
||||||
auto it = _itemsByHistoryItems.find(historyItem);
|
if (_history == historyItem->history()) {
|
||||||
if (it != _itemsByHistoryItems.cend()) {
|
repaintItem(historyItem);
|
||||||
repaintItem(it->second);
|
}
|
||||||
|
});
|
||||||
|
subscribe(AuthSession::Current().data().pendingHistoryResize(), [this] { handlePendingHistoryResize(); });
|
||||||
|
subscribe(AuthSession::Current().data().queryItemVisibility(), [this](const AuthSessionData::ItemVisibilityQuery &query) {
|
||||||
|
if (_history != query.item->history() || !query.item->isLogEntry() || !isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto top = itemTop(query.item);
|
||||||
|
if (top >= 0 && top + query.item->height() > _visibleTop && top < _visibleBottom) {
|
||||||
|
*query.isVisible = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -64,11 +72,11 @@ void InnerWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
||||||
void InnerWidget::updateVisibleTopItem() {
|
void InnerWidget::updateVisibleTopItem() {
|
||||||
auto start = std::rbegin(_items), end = std::rend(_items);
|
auto start = std::rbegin(_items), end = std::rend(_items);
|
||||||
auto from = std::upper_bound(start, end, _visibleTop, [](int top, auto &elem) {
|
auto from = std::upper_bound(start, end, _visibleTop, [](int top, auto &elem) {
|
||||||
return top <= elem->top() + elem->height();
|
return top <= elem->y() + elem->height();
|
||||||
});
|
});
|
||||||
if (from != end) {
|
if (from != end) {
|
||||||
_visibleTopItem = from->get();
|
_visibleTopItem = *from;
|
||||||
_visibleTopFromItem = _visibleTop - _visibleTopItem->top();
|
_visibleTopFromItem = _visibleTop - _visibleTopItem->y();
|
||||||
} else {
|
} else {
|
||||||
_visibleTopItem = nullptr;
|
_visibleTopItem = nullptr;
|
||||||
_visibleTopFromItem = _visibleTop;
|
_visibleTopFromItem = _visibleTop;
|
||||||
|
@ -144,13 +152,15 @@ void InnerWidget::applyFilter(MTPDchannelAdminLogEventsFilter::Flags flags, cons
|
||||||
|
|
||||||
QString InnerWidget::tooltipText() const {
|
QString InnerWidget::tooltipText() const {
|
||||||
if (_mouseCursorState == HistoryInDateCursorState && _mouseAction == MouseAction::None) {
|
if (_mouseCursorState == HistoryInDateCursorState && _mouseAction == MouseAction::None) {
|
||||||
if (_itemOver) {
|
if (auto item = App::hoveredItem()) {
|
||||||
auto dateText = _itemOver->date().toString(QLocale::system().dateTimeFormat(QLocale::LongFormat));
|
auto dateText = item->date.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat));
|
||||||
return dateText;
|
return dateText;
|
||||||
}
|
}
|
||||||
} else if (_mouseCursorState == HistoryInForwardedCursorState && _mouseAction == MouseAction::None) {
|
} else if (_mouseCursorState == HistoryInForwardedCursorState && _mouseAction == MouseAction::None) {
|
||||||
if (_itemOver) {
|
if (auto item = App::hoveredItem()) {
|
||||||
auto forwarded = _itemOver->getForwardedInfoText();
|
if (auto forwarded = item->Get<HistoryMessageForwarded>()) {
|
||||||
|
return forwarded->_text.originalText(AllTextSelection, ExpandLinksNone);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (auto lnk = ClickHandler::getActive()) {
|
} else if (auto lnk = ClickHandler::getActive()) {
|
||||||
return lnk->tooltip();
|
return lnk->tooltip();
|
||||||
|
@ -226,11 +236,26 @@ void InnerWidget::preloadMore(Direction direction) {
|
||||||
_items.reserve(_items.size() + events.size());
|
_items.reserve(_items.size() + events.size());
|
||||||
for_const (auto &event, events) {
|
for_const (auto &event, events) {
|
||||||
t_assert(event.type() == mtpc_channelAdminLogEvent);
|
t_assert(event.type() == mtpc_channelAdminLogEvent);
|
||||||
_items.push_back(std::make_unique<Item>(_history, _idManager, event.c_channelAdminLogEvent()));
|
auto &data = event.c_channelAdminLogEvent();
|
||||||
|
auto count = 0;
|
||||||
|
GenerateItems(_history, _idManager, data, [this, id = data.vid.v, &count](HistoryItemOwned item) {
|
||||||
|
_items.push_back(std::move(item));
|
||||||
|
_itemsByIds.emplace(id, item.get());
|
||||||
|
++count;
|
||||||
|
});
|
||||||
|
if (count > 1) {
|
||||||
|
// Reverse the inner order of the added messages, because we load events
|
||||||
|
// from bottom to top but inside one event they go from top to bottom.
|
||||||
|
auto full = _items.size();
|
||||||
|
auto from = full - count;
|
||||||
|
for (auto i = 0, toReverse = count / 2; i != toReverse; ++i) {
|
||||||
|
std::swap(_items[from + i], _items[full - i - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!_items.empty()) {
|
if (!_items.empty()) {
|
||||||
_maxId = _items.front()->id();
|
_maxId = (--_itemsByIds.end())->first;
|
||||||
_minId = _items.back()->id();
|
_minId = _itemsByIds.begin()->first;
|
||||||
if (_minId == 1) {
|
if (_minId == 1) {
|
||||||
_upLoaded = true;
|
_upLoaded = true;
|
||||||
}
|
}
|
||||||
|
@ -262,7 +287,7 @@ int InnerWidget::resizeGetHeight(int newWidth) {
|
||||||
|
|
||||||
auto newHeight = 0;
|
auto newHeight = 0;
|
||||||
for (auto &item : base::reversed(_items)) {
|
for (auto &item : base::reversed(_items)) {
|
||||||
item->setTop(newHeight);
|
item->setY(newHeight);
|
||||||
newHeight += item->resizeGetHeight(newWidth);
|
newHeight += item->resizeGetHeight(newWidth);
|
||||||
}
|
}
|
||||||
_itemsHeight = newHeight;
|
_itemsHeight = newHeight;
|
||||||
|
@ -357,7 +382,10 @@ void InnerWidget::enterEventHook(QEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::leaveEventHook(QEvent *e) {
|
void InnerWidget::leaveEventHook(QEvent *e) {
|
||||||
repaintItem(base::take(_itemOver));
|
if (auto item = App::hoveredItem()) {
|
||||||
|
repaintItem(item);
|
||||||
|
App::hoveredItem(nullptr);
|
||||||
|
}
|
||||||
ClickHandler::clearActive();
|
ClickHandler::clearActive();
|
||||||
Ui::Tooltip::Hide();
|
Ui::Tooltip::Hide();
|
||||||
if (!ClickHandler::getPressed() && _cursor != style::cur_default) {
|
if (!ClickHandler::getPressed() && _cursor != style::cur_default) {
|
||||||
|
@ -372,14 +400,14 @@ void InnerWidget::mouseActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
||||||
if (button != Qt::LeftButton) return;
|
if (button != Qt::LeftButton) return;
|
||||||
|
|
||||||
ClickHandler::pressed();
|
ClickHandler::pressed();
|
||||||
if (_itemPressed != _itemOver) {
|
if (App::pressedItem() != App::hoveredItem()) {
|
||||||
repaintItem(_itemPressed);
|
repaintItem(App::pressedItem());
|
||||||
_itemPressed = _itemOver;
|
App::pressedItem(App::hoveredItem());
|
||||||
repaintItem(_itemPressed);
|
repaintItem(App::pressedItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
_mouseAction = MouseAction::None;
|
_mouseAction = MouseAction::None;
|
||||||
_mouseActionItem = _itemNearest;
|
_mouseActionItem = App::mousedItem();
|
||||||
_dragStartPosition = mapPointToItem(mapFromGlobal(screenPos), _mouseActionItem);
|
_dragStartPosition = mapPointToItem(mapFromGlobal(screenPos), _mouseActionItem);
|
||||||
_pressWasInactive = _controller->window()->wasInactivePress();
|
_pressWasInactive = _controller->window()->wasInactivePress();
|
||||||
if (_pressWasInactive) _controller->window()->setInactivePress(false);
|
if (_pressWasInactive) _controller->window()->setInactivePress(false);
|
||||||
|
@ -392,7 +420,7 @@ void InnerWidget::mouseActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
||||||
if (_trippleClickTimer.isActive() && (screenPos - _trippleClickPoint).manhattanLength() < QApplication::startDragDistance()) {
|
if (_trippleClickTimer.isActive() && (screenPos - _trippleClickPoint).manhattanLength() < QApplication::startDragDistance()) {
|
||||||
HistoryStateRequest request;
|
HistoryStateRequest request;
|
||||||
request.flags = Text::StateRequest::Flag::LookupSymbol;
|
request.flags = Text::StateRequest::Flag::LookupSymbol;
|
||||||
dragState = _mouseActionItem->getState(_dragStartPosition, request).data;
|
dragState = _mouseActionItem->getState(_dragStartPosition, request);
|
||||||
if (dragState.cursor == HistoryInTextCursorState) {
|
if (dragState.cursor == HistoryInTextCursorState) {
|
||||||
auto selection = TextSelection { dragState.symbol, dragState.symbol };
|
auto selection = TextSelection { dragState.symbol, dragState.symbol };
|
||||||
repaintItem(std::exchange(_selectedItem, _mouseActionItem));
|
repaintItem(std::exchange(_selectedItem, _mouseActionItem));
|
||||||
|
@ -403,13 +431,13 @@ void InnerWidget::mouseActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
||||||
mouseActionUpdate(_mousePosition);
|
mouseActionUpdate(_mousePosition);
|
||||||
_trippleClickTimer.callOnce(QApplication::doubleClickInterval());
|
_trippleClickTimer.callOnce(QApplication::doubleClickInterval());
|
||||||
}
|
}
|
||||||
} else if (_itemPressed) {
|
} else if (App::pressedItem()) {
|
||||||
HistoryStateRequest request;
|
HistoryStateRequest request;
|
||||||
request.flags = Text::StateRequest::Flag::LookupSymbol;
|
request.flags = Text::StateRequest::Flag::LookupSymbol;
|
||||||
dragState = _mouseActionItem->getState(_dragStartPosition, request).data;
|
dragState = _mouseActionItem->getState(_dragStartPosition, request);
|
||||||
}
|
}
|
||||||
if (_mouseSelectType != TextSelectType::Paragraphs) {
|
if (_mouseSelectType != TextSelectType::Paragraphs) {
|
||||||
if (_itemPressed) {
|
if (App::pressedItem()) {
|
||||||
_mouseTextSymbol = dragState.symbol;
|
_mouseTextSymbol = dragState.symbol;
|
||||||
auto uponSelected = (dragState.cursor == HistoryInTextCursorState);
|
auto uponSelected = (dragState.cursor == HistoryInTextCursorState);
|
||||||
if (uponSelected) {
|
if (uponSelected) {
|
||||||
|
@ -422,16 +450,16 @@ void InnerWidget::mouseActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
||||||
if (uponSelected) {
|
if (uponSelected) {
|
||||||
_mouseAction = MouseAction::PrepareDrag; // start text drag
|
_mouseAction = MouseAction::PrepareDrag; // start text drag
|
||||||
} else if (!_pressWasInactive) {
|
} else if (!_pressWasInactive) {
|
||||||
//if (dynamic_cast<HistorySticker*>(_itemPressed->getMedia())) {
|
if (dynamic_cast<HistorySticker*>(App::pressedItem()->getMedia())) {
|
||||||
// _mouseAction = MouseAction::PrepareDrag; // start sticker drag or by-date drag
|
_mouseAction = MouseAction::PrepareDrag; // start sticker drag or by-date drag
|
||||||
//} else { // TODO
|
} else {
|
||||||
if (dragState.afterSymbol) ++_mouseTextSymbol;
|
if (dragState.afterSymbol) ++_mouseTextSymbol;
|
||||||
auto selection = TextSelection { _mouseTextSymbol, _mouseTextSymbol };
|
auto selection = TextSelection { _mouseTextSymbol, _mouseTextSymbol };
|
||||||
repaintItem(std::exchange(_selectedItem, _mouseActionItem));
|
repaintItem(std::exchange(_selectedItem, _mouseActionItem));
|
||||||
_selectedText = selection;
|
_selectedText = selection;
|
||||||
_mouseAction = MouseAction::Selecting;
|
_mouseAction = MouseAction::Selecting;
|
||||||
repaintItem(_mouseActionItem);
|
repaintItem(_mouseActionItem);
|
||||||
//} // TODO
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,7 +492,10 @@ void InnerWidget::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton but
|
||||||
if (_mouseAction == MouseAction::Dragging) {
|
if (_mouseAction == MouseAction::Dragging) {
|
||||||
activated.clear();
|
activated.clear();
|
||||||
}
|
}
|
||||||
repaintItem(base::take(_itemPressed));
|
if (App::pressedItem()) {
|
||||||
|
repaintItem(App::pressedItem());
|
||||||
|
App::pressedItem(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
_wasSelectedText = false;
|
_wasSelectedText = false;
|
||||||
|
|
||||||
|
@ -504,26 +535,27 @@ void InnerWidget::updateSelected() {
|
||||||
auto from = (point.y() >= _itemsTop && point.y() < _itemsTop + _itemsHeight) ? std::upper_bound(start, end, point.y(), [this](int top, auto &elem) {
|
auto from = (point.y() >= _itemsTop && point.y() < _itemsTop + _itemsHeight) ? std::upper_bound(start, end, point.y(), [this](int top, auto &elem) {
|
||||||
return top <= itemTop(elem.get()) + elem->height();
|
return top <= itemTop(elem.get()) + elem->height();
|
||||||
}) : end;
|
}) : end;
|
||||||
if (from != end) {
|
auto item = (from != end) ? from->get() : nullptr;
|
||||||
_itemNearest = from->get();
|
if (item) {
|
||||||
itemPoint = mapPointToItem(point, _itemNearest);
|
App::mousedItem(item);
|
||||||
if (_itemNearest->hasPoint(itemPoint)) {
|
itemPoint = mapPointToItem(point, item);
|
||||||
if (_itemOver != _itemNearest) {
|
if (item->hasPoint(itemPoint)) {
|
||||||
repaintItem(std::exchange(_itemOver, _itemNearest));
|
if (App::hoveredItem() != item) {
|
||||||
repaintItem(_itemNearest);
|
repaintItem(App::hoveredItem());
|
||||||
|
App::hoveredItem(item);
|
||||||
|
repaintItem(App::hoveredItem());
|
||||||
}
|
}
|
||||||
} else {
|
} else if (App::hoveredItem()) {
|
||||||
repaintItem(base::take(_itemOver));
|
repaintItem(App::hoveredItem());
|
||||||
|
App::hoveredItem(nullptr);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
_itemNearest = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item::TextState dragState;
|
HistoryTextState dragState;
|
||||||
ClickHandlerHost *lnkhost = nullptr;
|
ClickHandlerHost *lnkhost = nullptr;
|
||||||
auto selectingText = (_itemNearest == _mouseActionItem && _itemNearest == _itemOver && _selectedItem);
|
auto selectingText = (item == _mouseActionItem && item == App::hoveredItem() && _selectedItem);
|
||||||
if (_itemNearest) {
|
if (item) {
|
||||||
if (_itemNearest != _mouseActionItem || (itemPoint - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
|
if (item != _mouseActionItem || (itemPoint - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
|
||||||
if (_mouseAction == MouseAction::PrepareDrag) {
|
if (_mouseAction == MouseAction::PrepareDrag) {
|
||||||
_mouseAction = MouseAction::Dragging;
|
_mouseAction = MouseAction::Dragging;
|
||||||
InvokeQueued(this, [this] { performDrag(); });
|
InvokeQueued(this, [this] { performDrag(); });
|
||||||
|
@ -579,60 +611,60 @@ void InnerWidget::updateSelected() {
|
||||||
// }
|
// }
|
||||||
// return true;
|
// return true;
|
||||||
//}); // TODO
|
//}); // TODO
|
||||||
if (!dragState.data.link) {
|
if (!dragState.link) {
|
||||||
HistoryStateRequest request;
|
HistoryStateRequest request;
|
||||||
if (_mouseAction == MouseAction::Selecting) {
|
if (_mouseAction == MouseAction::Selecting) {
|
||||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||||
} else {
|
} else {
|
||||||
selectingText = false;
|
selectingText = false;
|
||||||
}
|
}
|
||||||
dragState = _itemNearest->getState(itemPoint, request);
|
dragState = item->getState(itemPoint, request);
|
||||||
lnkhost = dragState.handler;
|
lnkhost = item;
|
||||||
if (!dragState.data.link && itemPoint.x() >= st::historyPhotoLeft && itemPoint.x() < st::historyPhotoLeft + st::msgPhotoSize) {
|
if (!dragState.link && itemPoint.x() >= st::historyPhotoLeft && itemPoint.x() < st::historyPhotoLeft + st::msgPhotoSize) {
|
||||||
//if (auto msg = item->toHistoryMessage()) {
|
if (auto msg = item->toHistoryMessage()) {
|
||||||
// if (msg->hasFromPhoto()) {
|
if (msg->hasFromPhoto()) {
|
||||||
// enumerateUserpics([&dragState, &lnkhost, &point](HistoryMessage *message, int userpicTop) -> bool {
|
//enumerateUserpics([&dragState, &lnkhost, &point](HistoryMessage *message, int userpicTop) -> bool {
|
||||||
// // stop enumeration if the userpic is below our point
|
// // stop enumeration if the userpic is below our point
|
||||||
// if (userpicTop > point.y()) {
|
// if (userpicTop > point.y()) {
|
||||||
// return false;
|
// return false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// // stop enumeration if we've found a userpic under the cursor
|
// // stop enumeration if we've found a userpic under the cursor
|
||||||
// if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
|
// if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
|
||||||
// dragState.link = message->from()->openLink();
|
// dragState.link = message->from()->openLink();
|
||||||
// lnkhost = message;
|
// lnkhost = message;
|
||||||
// return false;
|
// return false;
|
||||||
// }
|
// }
|
||||||
// return true;
|
// return true;
|
||||||
// });
|
//}); // TODO
|
||||||
// }
|
}
|
||||||
//} // TODO
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto lnkChanged = ClickHandler::setActive(dragState.data.link, lnkhost);
|
auto lnkChanged = ClickHandler::setActive(dragState.link, lnkhost);
|
||||||
if (lnkChanged || dragState.data.cursor != _mouseCursorState) {
|
if (lnkChanged || dragState.cursor != _mouseCursorState) {
|
||||||
Ui::Tooltip::Hide();
|
Ui::Tooltip::Hide();
|
||||||
}
|
}
|
||||||
if (dragState.data.link || dragState.data.cursor == HistoryInDateCursorState || dragState.data.cursor == HistoryInForwardedCursorState) {
|
if (dragState.link || dragState.cursor == HistoryInDateCursorState || dragState.cursor == HistoryInForwardedCursorState) {
|
||||||
Ui::Tooltip::Show(1000, this);
|
Ui::Tooltip::Show(1000, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cursor = style::cur_default;
|
auto cursor = style::cur_default;
|
||||||
if (_mouseAction == MouseAction::None) {
|
if (_mouseAction == MouseAction::None) {
|
||||||
_mouseCursorState = dragState.data.cursor;
|
_mouseCursorState = dragState.cursor;
|
||||||
if (dragState.data.link) {
|
if (dragState.link) {
|
||||||
cursor = style::cur_pointer;
|
cursor = style::cur_pointer;
|
||||||
} else if (_mouseCursorState == HistoryInTextCursorState) {
|
} else if (_mouseCursorState == HistoryInTextCursorState) {
|
||||||
cursor = style::cur_text;
|
cursor = style::cur_text;
|
||||||
} else if (_mouseCursorState == HistoryInDateCursorState) {
|
} else if (_mouseCursorState == HistoryInDateCursorState) {
|
||||||
// cursor = style::cur_cross;
|
// cursor = style::cur_cross;
|
||||||
}
|
}
|
||||||
} else if (_itemNearest) {
|
} else if (item) {
|
||||||
if (_mouseAction == MouseAction::Selecting) {
|
if (_mouseAction == MouseAction::Selecting) {
|
||||||
if (selectingText) {
|
if (selectingText) {
|
||||||
auto second = dragState.data.symbol;
|
auto second = dragState.symbol;
|
||||||
if (dragState.data.afterSymbol && _mouseSelectType == TextSelectType::Letters) {
|
if (dragState.afterSymbol && _mouseSelectType == TextSelectType::Letters) {
|
||||||
++second;
|
++second;
|
||||||
}
|
}
|
||||||
auto selection = _mouseActionItem->adjustSelection({ qMin(second, _mouseTextSymbol), qMax(second, _mouseTextSymbol) }, _mouseSelectType);
|
auto selection = _mouseActionItem->adjustSelection({ qMin(second, _mouseTextSymbol), qMax(second, _mouseTextSymbol) }, _mouseSelectType);
|
||||||
|
@ -656,9 +688,13 @@ void InnerWidget::updateSelected() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Voice message seek support.
|
// Voice message seek support.
|
||||||
if (_itemPressed) {
|
if (auto pressedItem = App::pressedLinkItem()) {
|
||||||
auto adjustedPoint = mapPointToItem(point, _itemPressed);
|
if (!pressedItem->detached()) {
|
||||||
_itemPressed->updatePressed(adjustedPoint);
|
if (pressedItem->history() == _history) {
|
||||||
|
auto adjustedPoint = mapPointToItem(point, pressedItem);
|
||||||
|
pressedItem->updatePressed(adjustedPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (_mouseAction == MouseAction::Selecting) {
|
//if (_mouseAction == MouseAction::Selecting) {
|
||||||
|
@ -763,24 +799,31 @@ void InnerWidget::performDrag() {
|
||||||
//} // TODO
|
//} // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
int InnerWidget::itemTop(gsl::not_null<Item*> item) const {
|
int InnerWidget::itemTop(gsl::not_null<const HistoryItem*> item) const {
|
||||||
return _itemsTop + item->top();
|
return _itemsTop + item->y();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::repaintItem(Item *item) {
|
void InnerWidget::repaintItem(const HistoryItem *item) {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
update(0, itemTop(item), width(), item->height());
|
update(0, itemTop(item), width(), item->height());
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint InnerWidget::mapPointToItem(QPoint point, Item *item) const {
|
QPoint InnerWidget::mapPointToItem(QPoint point, const HistoryItem *item) const {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return QPoint();
|
return QPoint();
|
||||||
}
|
}
|
||||||
return point - QPoint(0, itemTop(item));
|
return point - QPoint(0, itemTop(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InnerWidget::handlePendingHistoryResize() {
|
||||||
|
if (_history->hasPendingResizedItems()) {
|
||||||
|
_history->resizeGetHeight(width());
|
||||||
|
updateSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InnerWidget::~InnerWidget() = default;
|
InnerWidget::~InnerWidget() = default;
|
||||||
|
|
||||||
} // namespace AdminLog
|
} // namespace AdminLog
|
||||||
|
|
|
@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "history/history_admin_log_item.h"
|
||||||
#include "ui/widgets/tooltip.h"
|
#include "ui/widgets/tooltip.h"
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
|
@ -35,7 +36,6 @@ class Controller;
|
||||||
namespace AdminLog {
|
namespace AdminLog {
|
||||||
|
|
||||||
class SectionMemento;
|
class SectionMemento;
|
||||||
class Item;
|
|
||||||
|
|
||||||
class LocalIdManager {
|
class LocalIdManager {
|
||||||
public:
|
public:
|
||||||
|
@ -118,9 +118,10 @@ private:
|
||||||
void mouseActionCancel();
|
void mouseActionCancel();
|
||||||
void updateSelected();
|
void updateSelected();
|
||||||
void performDrag();
|
void performDrag();
|
||||||
int itemTop(gsl::not_null<Item*> item) const;
|
int itemTop(gsl::not_null<const HistoryItem*> item) const;
|
||||||
void repaintItem(Item *item);
|
void repaintItem(const HistoryItem *item);
|
||||||
QPoint mapPointToItem(QPoint point, Item *item) const;
|
QPoint mapPointToItem(QPoint point, const HistoryItem *item) const;
|
||||||
|
void handlePendingHistoryResize();
|
||||||
|
|
||||||
void checkPreloadMore();
|
void checkPreloadMore();
|
||||||
void updateVisibleTopItem();
|
void updateVisibleTopItem();
|
||||||
|
@ -142,8 +143,8 @@ private:
|
||||||
gsl::not_null<History*> _history;
|
gsl::not_null<History*> _history;
|
||||||
base::lambda<void()> _cancelledCallback;
|
base::lambda<void()> _cancelledCallback;
|
||||||
base::lambda<void(int top)> _scrollTo;
|
base::lambda<void(int top)> _scrollTo;
|
||||||
std::vector<std::unique_ptr<Item>> _items;
|
std::vector<HistoryItemOwned> _items;
|
||||||
std::map<gsl::not_null<HistoryItem*>, gsl::not_null<Item*>, std::less<>> _itemsByHistoryItems;
|
std::map<uint64, HistoryItem*> _itemsByIds;
|
||||||
int _itemsTop = 0;
|
int _itemsTop = 0;
|
||||||
int _itemsHeight = 0;
|
int _itemsHeight = 0;
|
||||||
|
|
||||||
|
@ -151,14 +152,14 @@ private:
|
||||||
int _minHeight = 0;
|
int _minHeight = 0;
|
||||||
int _visibleTop = 0;
|
int _visibleTop = 0;
|
||||||
int _visibleBottom = 0;
|
int _visibleBottom = 0;
|
||||||
Item *_visibleTopItem = nullptr;
|
HistoryItem *_visibleTopItem = nullptr;
|
||||||
int _visibleTopFromItem = 0;
|
int _visibleTopFromItem = 0;
|
||||||
|
|
||||||
bool _scrollDateShown = false;
|
bool _scrollDateShown = false;
|
||||||
Animation _scrollDateOpacity;
|
Animation _scrollDateOpacity;
|
||||||
SingleQueuedInvokation _scrollDateCheck;
|
SingleQueuedInvokation _scrollDateCheck;
|
||||||
base::Timer _scrollDateHideTimer;
|
base::Timer _scrollDateHideTimer;
|
||||||
Item *_scrollDateLastItem = nullptr;
|
HistoryItem *_scrollDateLastItem = nullptr;
|
||||||
int _scrollDateLastItemTop = 0;
|
int _scrollDateLastItemTop = 0;
|
||||||
ClickHandlerPtr _scrollDateLink;
|
ClickHandlerPtr _scrollDateLink;
|
||||||
|
|
||||||
|
@ -174,15 +175,12 @@ private:
|
||||||
TextSelectType _mouseSelectType = TextSelectType::Letters;
|
TextSelectType _mouseSelectType = TextSelectType::Letters;
|
||||||
QPoint _dragStartPosition;
|
QPoint _dragStartPosition;
|
||||||
QPoint _mousePosition;
|
QPoint _mousePosition;
|
||||||
Item *_mouseActionItem = nullptr;
|
HistoryItem *_mouseActionItem = nullptr;
|
||||||
HistoryCursorState _mouseCursorState = HistoryDefaultCursorState;
|
HistoryCursorState _mouseCursorState = HistoryDefaultCursorState;
|
||||||
uint16 _mouseTextSymbol = 0;
|
uint16 _mouseTextSymbol = 0;
|
||||||
bool _pressWasInactive = false;
|
bool _pressWasInactive = false;
|
||||||
|
|
||||||
Item *_itemNearest = nullptr;
|
HistoryItem *_selectedItem = nullptr;
|
||||||
Item *_itemOver = nullptr;
|
|
||||||
Item *_itemPressed = nullptr;
|
|
||||||
Item *_selectedItem = nullptr;
|
|
||||||
TextSelection _selectedText;
|
TextSelection _selectedText;
|
||||||
bool _wasSelectedText = false; // was some text selected in current drag action
|
bool _wasSelectedText = false; // was some text selected in current drag action
|
||||||
Qt::CursorShape _cursor = style::cur_default;
|
Qt::CursorShape _cursor = style::cur_default;
|
||||||
|
|
|
@ -20,6 +20,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_inner.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "messenger.h"
|
#include "messenger.h"
|
||||||
|
|
||||||
|
@ -233,35 +234,39 @@ TextWithEntities GenerateParticipantChangeText(gsl::not_null<ChannelData*> chann
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Item::Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event)
|
void GenerateItems(gsl::not_null<History*> history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event, base::lambda<void(HistoryItemOwned item)> callback) {
|
||||||
: _id(event.vid.v)
|
Expects(history->peer->isChannel());
|
||||||
, _date(::date(event.vdate))
|
|
||||||
, _history(history)
|
auto id = event.vid.v;
|
||||||
, _from(App::user(event.vuser_id.v)) {
|
auto from = App::user(event.vuser_id.v);
|
||||||
|
auto channel = history->peer->asChannel();
|
||||||
auto &action = event.vaction;
|
auto &action = event.vaction;
|
||||||
auto date = event.vdate;
|
auto date = event.vdate;
|
||||||
|
auto addPart = [&callback](gsl::not_null<HistoryItem*> item) {
|
||||||
|
return callback(HistoryItemOwned(item));
|
||||||
|
};
|
||||||
|
|
||||||
using ServiceFlag = MTPDmessageService::Flag;
|
using ServiceFlag = MTPDmessageService::Flag;
|
||||||
using Flag = MTPDmessage::Flag;
|
using Flag = MTPDmessage::Flag;
|
||||||
auto fromName = App::peerName(_from);
|
auto fromName = App::peerName(from);
|
||||||
auto fromLink = _from->openLink();
|
auto fromLink = peerOpenClickHandler(from);
|
||||||
auto fromLinkText = textcmdLink(1, fromName);
|
auto fromLinkText = textcmdLink(1, fromName);
|
||||||
|
|
||||||
auto addSimpleServiceMessage = [this, &idManager, date, fromLink](const QString &text, PhotoData *photo = nullptr) {
|
auto addSimpleServiceMessage = [&](const QString &text, PhotoData *photo = nullptr) {
|
||||||
auto message = HistoryService::PreparedText { text };
|
auto message = HistoryService::PreparedText { text };
|
||||||
message.links.push_back(fromLink);
|
message.links.push_back(fromLink);
|
||||||
addPart(HistoryService::create(_history, idManager.next(), ::date(date), message, 0, peerToUser(_from->id), photo));
|
addPart(HistoryService::create(history, idManager.next(), ::date(date), message, 0, peerToUser(from->id), photo));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createChangeTitle = [this, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionChangeTitle &action) {
|
auto createChangeTitle = [&](const MTPDchannelAdminLogEventActionChangeTitle &action) {
|
||||||
auto text = (channel()->isMegagroup() ? lng_action_changed_title : lng_admin_log_changed_title_channel)(lt_from, fromLinkText, lt_title, qs(action.vnew_value));
|
auto text = (channel->isMegagroup() ? lng_action_changed_title : lng_admin_log_changed_title_channel)(lt_from, fromLinkText, lt_title, qs(action.vnew_value));
|
||||||
addSimpleServiceMessage(text);
|
addSimpleServiceMessage(text);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createChangeAbout = [this, &idManager, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionChangeAbout &action) {
|
auto createChangeAbout = [&](const MTPDchannelAdminLogEventActionChangeAbout &action) {
|
||||||
auto newValue = qs(action.vnew_value);
|
auto newValue = qs(action.vnew_value);
|
||||||
auto oldValue = qs(action.vprev_value);
|
auto oldValue = qs(action.vprev_value);
|
||||||
auto text = (channel()->isMegagroup()
|
auto text = (channel->isMegagroup()
|
||||||
? (newValue.isEmpty() ? lng_admin_log_removed_description_group : lng_admin_log_changed_description_group)
|
? (newValue.isEmpty() ? lng_admin_log_removed_description_group : lng_admin_log_changed_description_group)
|
||||||
: (newValue.isEmpty() ? lng_admin_log_removed_description_channel : lng_admin_log_changed_description_channel)
|
: (newValue.isEmpty() ? lng_admin_log_removed_description_channel : lng_admin_log_changed_description_channel)
|
||||||
)(lt_from, fromLinkText);
|
)(lt_from, fromLinkText);
|
||||||
|
@ -271,18 +276,18 @@ Item::Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTP
|
||||||
auto bodyReplyTo = 0;
|
auto bodyReplyTo = 0;
|
||||||
auto bodyViaBotId = 0;
|
auto bodyViaBotId = 0;
|
||||||
auto newDescription = PrepareText(newValue, QString());
|
auto newDescription = PrepareText(newValue, QString());
|
||||||
auto body = HistoryMessage::create(_history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(_from->id), newDescription);
|
auto body = HistoryMessage::create(history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), newDescription);
|
||||||
if (!oldValue.isEmpty()) {
|
if (!oldValue.isEmpty()) {
|
||||||
auto oldDescription = PrepareText(oldValue, QString());
|
auto oldDescription = PrepareText(oldValue, QString());
|
||||||
body->addLogEntryOriginal(_id, lang(lng_admin_log_previous_description), oldDescription);
|
body->addLogEntryOriginal(id, lang(lng_admin_log_previous_description), oldDescription);
|
||||||
}
|
}
|
||||||
addPart(body);
|
addPart(body);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createChangeUsername = [this, &idManager, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionChangeUsername &action) {
|
auto createChangeUsername = [&](const MTPDchannelAdminLogEventActionChangeUsername &action) {
|
||||||
auto newValue = qs(action.vnew_value);
|
auto newValue = qs(action.vnew_value);
|
||||||
auto oldValue = qs(action.vprev_value);
|
auto oldValue = qs(action.vprev_value);
|
||||||
auto text = (channel()->isMegagroup()
|
auto text = (channel->isMegagroup()
|
||||||
? (newValue.isEmpty() ? lng_admin_log_removed_link_group : lng_admin_log_changed_link_group)
|
? (newValue.isEmpty() ? lng_admin_log_removed_link_group : lng_admin_log_changed_link_group)
|
||||||
: (newValue.isEmpty() ? lng_admin_log_removed_link_channel : lng_admin_log_changed_link_channel)
|
: (newValue.isEmpty() ? lng_admin_log_removed_link_channel : lng_admin_log_changed_link_channel)
|
||||||
)(lt_from, fromLinkText);
|
)(lt_from, fromLinkText);
|
||||||
|
@ -292,44 +297,44 @@ Item::Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTP
|
||||||
auto bodyReplyTo = 0;
|
auto bodyReplyTo = 0;
|
||||||
auto bodyViaBotId = 0;
|
auto bodyViaBotId = 0;
|
||||||
auto newLink = newValue.isEmpty() ? TextWithEntities() : PrepareText(Messenger::Instance().createInternalLinkFull(newValue), QString());
|
auto newLink = newValue.isEmpty() ? TextWithEntities() : PrepareText(Messenger::Instance().createInternalLinkFull(newValue), QString());
|
||||||
auto body = HistoryMessage::create(_history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(_from->id), newLink);
|
auto body = HistoryMessage::create(history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), newLink);
|
||||||
if (!oldValue.isEmpty()) {
|
if (!oldValue.isEmpty()) {
|
||||||
auto oldLink = PrepareText(Messenger::Instance().createInternalLinkFull(oldValue), QString());
|
auto oldLink = PrepareText(Messenger::Instance().createInternalLinkFull(oldValue), QString());
|
||||||
body->addLogEntryOriginal(_id, lang(lng_admin_log_previous_link), oldLink);
|
body->addLogEntryOriginal(id, lang(lng_admin_log_previous_link), oldLink);
|
||||||
}
|
}
|
||||||
addPart(body);
|
addPart(body);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createChangePhoto = [this, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionChangePhoto &action) {
|
auto createChangePhoto = [&](const MTPDchannelAdminLogEventActionChangePhoto &action) {
|
||||||
t_assert(action.vnew_photo.type() == mtpc_chatPhoto);
|
t_assert(action.vnew_photo.type() == mtpc_chatPhoto);
|
||||||
auto photo = GenerateChatPhoto(channel()->bareId(), _id, date, action.vnew_photo.c_chatPhoto());
|
auto photo = GenerateChatPhoto(channel->bareId(), id, date, action.vnew_photo.c_chatPhoto());
|
||||||
|
|
||||||
auto text = (channel()->isMegagroup() ? lng_admin_log_changed_photo_group : lng_admin_log_changed_photo_channel)(lt_from, fromLinkText);
|
auto text = (channel->isMegagroup() ? lng_admin_log_changed_photo_group : lng_admin_log_changed_photo_channel)(lt_from, fromLinkText);
|
||||||
addSimpleServiceMessage(text, photo);
|
addSimpleServiceMessage(text, photo);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createToggleInvites = [this, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionToggleInvites &action) {
|
auto createToggleInvites = [&](const MTPDchannelAdminLogEventActionToggleInvites &action) {
|
||||||
auto enabled = (action.vnew_value.type() == mtpc_boolTrue);
|
auto enabled = (action.vnew_value.type() == mtpc_boolTrue);
|
||||||
auto text = (enabled ? lng_admin_log_invites_enabled : lng_admin_log_invites_disabled)(lt_from, fromLinkText);
|
auto text = (enabled ? lng_admin_log_invites_enabled : lng_admin_log_invites_disabled)(lt_from, fromLinkText);
|
||||||
addSimpleServiceMessage(text);
|
addSimpleServiceMessage(text);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createToggleSignatures = [this, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionToggleSignatures &action) {
|
auto createToggleSignatures = [&](const MTPDchannelAdminLogEventActionToggleSignatures &action) {
|
||||||
auto enabled = (action.vnew_value.type() == mtpc_boolTrue);
|
auto enabled = (action.vnew_value.type() == mtpc_boolTrue);
|
||||||
auto text = (enabled ? lng_admin_log_signatures_enabled : lng_admin_log_signatures_disabled)(lt_from, fromLinkText);
|
auto text = (enabled ? lng_admin_log_signatures_enabled : lng_admin_log_signatures_disabled)(lt_from, fromLinkText);
|
||||||
addSimpleServiceMessage(text);
|
addSimpleServiceMessage(text);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createUpdatePinned = [this, &idManager, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionUpdatePinned &action) {
|
auto createUpdatePinned = [&](const MTPDchannelAdminLogEventActionUpdatePinned &action) {
|
||||||
auto text = lng_admin_log_pinned_message(lt_from, fromLinkText);
|
auto text = lng_admin_log_pinned_message(lt_from, fromLinkText);
|
||||||
addSimpleServiceMessage(text);
|
addSimpleServiceMessage(text);
|
||||||
|
|
||||||
auto applyServiceAction = false;
|
auto applyServiceAction = false;
|
||||||
auto detachExistingItem = false;
|
auto detachExistingItem = false;
|
||||||
addPart(_history->createItem(PrepareLogMessage(action.vmessage, idManager.next(), date.v), applyServiceAction, detachExistingItem));
|
addPart(history->createItem(PrepareLogMessage(action.vmessage, idManager.next(), date.v), applyServiceAction, detachExistingItem));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createEditMessage = [this, &idManager, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionEditMessage &action) {
|
auto createEditMessage = [&](const MTPDchannelAdminLogEventActionEditMessage &action) {
|
||||||
auto newValue = ExtractEditedText(action.vnew_message);
|
auto newValue = ExtractEditedText(action.vnew_message);
|
||||||
auto canHaveCaption = MediaCanHaveCaption(action.vnew_message);
|
auto canHaveCaption = MediaCanHaveCaption(action.vnew_message);
|
||||||
auto text = (canHaveCaption
|
auto text = (canHaveCaption
|
||||||
|
@ -341,54 +346,54 @@ Item::Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTP
|
||||||
auto oldValue = ExtractEditedText(action.vprev_message);
|
auto oldValue = ExtractEditedText(action.vprev_message);
|
||||||
auto applyServiceAction = false;
|
auto applyServiceAction = false;
|
||||||
auto detachExistingItem = false;
|
auto detachExistingItem = false;
|
||||||
auto body = _history->createItem(PrepareLogMessage(action.vnew_message, idManager.next(), date.v), applyServiceAction, detachExistingItem);
|
auto body = history->createItem(PrepareLogMessage(action.vnew_message, idManager.next(), date.v), applyServiceAction, detachExistingItem);
|
||||||
if (!oldValue.text.isEmpty()) {
|
if (!oldValue.text.isEmpty()) {
|
||||||
body->addLogEntryOriginal(_id, lang(canHaveCaption ? lng_admin_log_previous_caption : lng_admin_log_previous_message), oldValue);
|
body->addLogEntryOriginal(id, lang(canHaveCaption ? lng_admin_log_previous_caption : lng_admin_log_previous_message), oldValue);
|
||||||
}
|
}
|
||||||
addPart(body);
|
addPart(body);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createDeleteMessage = [this, &idManager, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionDeleteMessage &action) {
|
auto createDeleteMessage = [&](const MTPDchannelAdminLogEventActionDeleteMessage &action) {
|
||||||
auto text = lng_admin_log_deleted_message(lt_from, fromLinkText);
|
auto text = lng_admin_log_deleted_message(lt_from, fromLinkText);
|
||||||
addSimpleServiceMessage(text);
|
addSimpleServiceMessage(text);
|
||||||
|
|
||||||
auto applyServiceAction = false;
|
auto applyServiceAction = false;
|
||||||
auto detachExistingItem = false;
|
auto detachExistingItem = false;
|
||||||
addPart(_history->createItem(PrepareLogMessage(action.vmessage, idManager.next(), date.v), applyServiceAction, detachExistingItem));
|
addPart(history->createItem(PrepareLogMessage(action.vmessage, idManager.next(), date.v), applyServiceAction, detachExistingItem));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createParticipantJoin = [this, &idManager, addSimpleServiceMessage, fromLinkText]() {
|
auto createParticipantJoin = [&]() {
|
||||||
auto text = lng_admin_log_participant_joined(lt_from, fromLinkText);
|
auto text = lng_admin_log_participant_joined(lt_from, fromLinkText);
|
||||||
addSimpleServiceMessage(text);
|
addSimpleServiceMessage(text);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createParticipantLeave = [this, &idManager, addSimpleServiceMessage, fromLinkText]() {
|
auto createParticipantLeave = [&]() {
|
||||||
auto text = lng_admin_log_participant_left(lt_from, fromLinkText);
|
auto text = lng_admin_log_participant_left(lt_from, fromLinkText);
|
||||||
addSimpleServiceMessage(text);
|
addSimpleServiceMessage(text);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createParticipantInvite = [this, &idManager, date](const MTPDchannelAdminLogEventActionParticipantInvite &action) {
|
auto createParticipantInvite = [&](const MTPDchannelAdminLogEventActionParticipantInvite &action) {
|
||||||
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
||||||
auto bodyReplyTo = 0;
|
auto bodyReplyTo = 0;
|
||||||
auto bodyViaBotId = 0;
|
auto bodyViaBotId = 0;
|
||||||
auto bodyText = GenerateParticipantChangeText(channel(), action.vparticipant);
|
auto bodyText = GenerateParticipantChangeText(channel, action.vparticipant);
|
||||||
addPart(HistoryMessage::create(_history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(_from->id), bodyText));
|
addPart(HistoryMessage::create(history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), bodyText));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createParticipantToggleBan = [this, &idManager, date](const MTPDchannelAdminLogEventActionParticipantToggleBan &action) {
|
auto createParticipantToggleBan = [&](const MTPDchannelAdminLogEventActionParticipantToggleBan &action) {
|
||||||
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
||||||
auto bodyReplyTo = 0;
|
auto bodyReplyTo = 0;
|
||||||
auto bodyViaBotId = 0;
|
auto bodyViaBotId = 0;
|
||||||
auto bodyText = GenerateParticipantChangeText(channel(), action.vnew_participant, &action.vprev_participant);
|
auto bodyText = GenerateParticipantChangeText(channel, action.vnew_participant, &action.vprev_participant);
|
||||||
addPart(HistoryMessage::create(_history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(_from->id), bodyText));
|
addPart(HistoryMessage::create(history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), bodyText));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createParticipantToggleAdmin = [this, &idManager, date](const MTPDchannelAdminLogEventActionParticipantToggleAdmin &action) {
|
auto createParticipantToggleAdmin = [&](const MTPDchannelAdminLogEventActionParticipantToggleAdmin &action) {
|
||||||
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
||||||
auto bodyReplyTo = 0;
|
auto bodyReplyTo = 0;
|
||||||
auto bodyViaBotId = 0;
|
auto bodyViaBotId = 0;
|
||||||
auto bodyText = GenerateParticipantChangeText(channel(), action.vnew_participant, &action.vprev_participant);
|
auto bodyText = GenerateParticipantChangeText(channel, action.vnew_participant, &action.vprev_participant);
|
||||||
addPart(HistoryMessage::create(_history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(_from->id), bodyText));
|
addPart(HistoryMessage::create(history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), bodyText));
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (action.type()) {
|
switch (action.type()) {
|
||||||
|
@ -410,78 +415,4 @@ Item::Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::addPart(HistoryItem *item) {
|
|
||||||
_parts.push_back(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Item::resizeGetHeight(int newWidth) {
|
|
||||||
_height = 0;
|
|
||||||
for (auto part : _parts) {
|
|
||||||
_height += part->resizeGetHeight(newWidth);
|
|
||||||
}
|
|
||||||
return _height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Item::draw(Painter &p, QRect clip, TextSelection selection, TimeMs ms) {
|
|
||||||
auto top = 0;
|
|
||||||
for (auto part : _parts) {
|
|
||||||
auto height = part->height();
|
|
||||||
if (clip.top() < top + height && clip.top() + clip.height() > top) {
|
|
||||||
p.translate(0, top);
|
|
||||||
part->draw(p, clip.translated(0, -top), selection, ms);
|
|
||||||
p.translate(0, -top);
|
|
||||||
}
|
|
||||||
top += height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Item::hasPoint(QPoint point) const {
|
|
||||||
auto top = 0;
|
|
||||||
for (auto part : _parts) {
|
|
||||||
auto height = part->height();
|
|
||||||
if (point.y() >= top && point.y() < top + height) {
|
|
||||||
return part->hasPoint(point - QPoint(0, top));
|
|
||||||
}
|
|
||||||
top += height;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Item::TextState Item::getState(QPoint point, HistoryStateRequest request) const {
|
|
||||||
auto top = 0;
|
|
||||||
for (auto part : _parts) {
|
|
||||||
auto height = part->height();
|
|
||||||
if (point.y() >= top && point.y() < top + height) {
|
|
||||||
auto result = TextState();
|
|
||||||
result.data = part->getState(point - QPoint(0, top), request);
|
|
||||||
result.handler = part;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
top += height;
|
|
||||||
}
|
|
||||||
return Item::TextState();
|
|
||||||
}
|
|
||||||
|
|
||||||
TextSelection Item::adjustSelection(TextSelection selection, TextSelectType type) const {
|
|
||||||
return selection;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Item::updatePressed(QPoint point) {
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Item::getForwardedInfoText() const {
|
|
||||||
for (auto part : _parts) {
|
|
||||||
if (auto forwarded = part->Get<HistoryMessageForwarded>()) {
|
|
||||||
return forwarded->_text.originalText(AllTextSelection, ExpandLinksNone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
Item::~Item() {
|
|
||||||
for (auto part : _parts) {
|
|
||||||
part->destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace AdminLog
|
} // namespace AdminLog
|
||||||
|
|
|
@ -20,59 +20,44 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "history/history_admin_log_inner.h"
|
|
||||||
|
|
||||||
namespace AdminLog {
|
namespace AdminLog {
|
||||||
|
|
||||||
class Item {
|
class HistoryItemOwned;
|
||||||
|
class LocalIdManager;
|
||||||
|
|
||||||
|
void GenerateItems(gsl::not_null<History*> history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event, base::lambda<void(HistoryItemOwned item)> callback);
|
||||||
|
|
||||||
|
// Smart pointer wrapper for HistoryItem* that destroys the owned item.
|
||||||
|
class HistoryItemOwned {
|
||||||
public:
|
public:
|
||||||
struct TextState {
|
explicit HistoryItemOwned(gsl::not_null<HistoryItem*> data) : _data(data) {
|
||||||
HistoryTextState data;
|
|
||||||
ClickHandlerHost *handler = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event);
|
|
||||||
|
|
||||||
uint64 id() const {
|
|
||||||
return _id;
|
|
||||||
}
|
}
|
||||||
QDateTime date() const {
|
HistoryItemOwned(const HistoryItemOwned &other) = delete;
|
||||||
return _date;
|
HistoryItemOwned &operator=(const HistoryItemOwned &other) = delete;
|
||||||
|
HistoryItemOwned(HistoryItemOwned &&other) : _data(base::take(other._data)) {
|
||||||
}
|
}
|
||||||
int top() const {
|
HistoryItemOwned &operator=(HistoryItemOwned &&other) {
|
||||||
return _top;
|
_data = base::take(other._data);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
void setTop(int top) {
|
~HistoryItemOwned() {
|
||||||
_top = top;
|
if (_data) {
|
||||||
}
|
_data->destroy();
|
||||||
int height() const {
|
}
|
||||||
return _height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int resizeGetHeight(int newWidth);
|
HistoryItem *get() const {
|
||||||
void draw(Painter &p, QRect clip, TextSelection selection, TimeMs ms);
|
return _data;
|
||||||
bool hasPoint(QPoint point) const;
|
}
|
||||||
TextState getState(QPoint point, HistoryStateRequest request) const;
|
HistoryItem *operator->() const {
|
||||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const;
|
return get();
|
||||||
void updatePressed(QPoint point);
|
}
|
||||||
|
operator HistoryItem*() const {
|
||||||
QString getForwardedInfoText() const;
|
return get();
|
||||||
|
}
|
||||||
~Item();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gsl::not_null<ChannelData*> channel() {
|
HistoryItem *_data = nullptr;
|
||||||
return _history->peer->asChannel();
|
|
||||||
}
|
|
||||||
void addPart(HistoryItem *item);
|
|
||||||
|
|
||||||
uint64 _id = 0;
|
|
||||||
QDateTime _date;
|
|
||||||
gsl::not_null<History*> _history;
|
|
||||||
gsl::not_null<UserData*> _from;
|
|
||||||
std::vector<HistoryItem*> _parts;
|
|
||||||
int _top = 0;
|
|
||||||
int _height = 0;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -780,7 +780,7 @@ void HistoryInner::touchScrollUpdated(const QPoint &screenPos) {
|
||||||
touchUpdateSpeed();
|
touchUpdateSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint HistoryInner::mapMouseToItem(QPoint p, HistoryItem *item) {
|
QPoint HistoryInner::mapPointToItem(QPoint p, HistoryItem *item) {
|
||||||
int32 msgy = itemTop(item);
|
int32 msgy = itemTop(item);
|
||||||
if (msgy < 0) return QPoint(0, 0);
|
if (msgy < 0) return QPoint(0, 0);
|
||||||
|
|
||||||
|
@ -809,7 +809,7 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
|
||||||
|
|
||||||
_mouseAction = MouseAction::None;
|
_mouseAction = MouseAction::None;
|
||||||
_mouseActionItem = App::mousedItem();
|
_mouseActionItem = App::mousedItem();
|
||||||
_dragStartPosition = mapMouseToItem(mapFromGlobal(screenPos), _mouseActionItem);
|
_dragStartPosition = mapPointToItem(mapFromGlobal(screenPos), _mouseActionItem);
|
||||||
_pressWasInactive = _controller->window()->wasInactivePress();
|
_pressWasInactive = _controller->window()->wasInactivePress();
|
||||||
if (_pressWasInactive) _controller->window()->setInactivePress(false);
|
if (_pressWasInactive) _controller->window()->setInactivePress(false);
|
||||||
|
|
||||||
|
@ -1037,7 +1037,7 @@ void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton bu
|
||||||
// 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.isEmpty() && _selected.cbegin().value() == FullSelection && button != Qt::RightButton) {
|
||||||
if (HistoryMedia *media = pressed->getMedia()) {
|
if (auto media = pressed->getMedia()) {
|
||||||
if (media->toggleSelectionByHandlerClick(activated)) {
|
if (media->toggleSelectionByHandlerClick(activated)) {
|
||||||
activated.clear();
|
activated.clear();
|
||||||
}
|
}
|
||||||
|
@ -1174,7 +1174,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
|
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().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()) {
|
||||||
QPoint mousePos(mapMouseToItem(mapFromGlobal(_mousePosition), App::mousedItem()));
|
auto mousePos = mapPointToItem(mapFromGlobal(_mousePosition), App::mousedItem());
|
||||||
HistoryStateRequest request;
|
HistoryStateRequest request;
|
||||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||||
auto dragState = App::mousedItem()->getState(mousePos, request);
|
auto dragState = App::mousedItem()->getState(mousePos, request);
|
||||||
|
@ -2006,7 +2006,7 @@ void HistoryInner::onUpdateSelected() {
|
||||||
item = block->items[_curItem];
|
item = block->items[_curItem];
|
||||||
|
|
||||||
App::mousedItem(item);
|
App::mousedItem(item);
|
||||||
m = mapMouseToItem(point, item);
|
m = mapPointToItem(point, item);
|
||||||
if (item->hasPoint(m)) {
|
if (item->hasPoint(m)) {
|
||||||
if (App::hoveredItem() != item) {
|
if (App::hoveredItem() != item) {
|
||||||
repaintItem(App::hoveredItem());
|
repaintItem(App::hoveredItem());
|
||||||
|
@ -2208,7 +2208,7 @@ void HistoryInner::onUpdateSelected() {
|
||||||
if (auto pressedItem = App::pressedLinkItem()) {
|
if (auto pressedItem = App::pressedLinkItem()) {
|
||||||
if (!pressedItem->detached()) {
|
if (!pressedItem->detached()) {
|
||||||
if (pressedItem->history() == _history || pressedItem->history() == _migrated) {
|
if (pressedItem->history() == _history || pressedItem->history() == _migrated) {
|
||||||
auto adjustedPoint = mapMouseToItem(point, pressedItem);
|
auto adjustedPoint = mapPointToItem(point, pressedItem);
|
||||||
pressedItem->updatePressed(adjustedPoint);
|
pressedItem->updatePressed(adjustedPoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
TextWithEntities getSelectedText() const;
|
TextWithEntities getSelectedText() const;
|
||||||
|
|
||||||
void touchScrollUpdated(const QPoint &screenPos);
|
void touchScrollUpdated(const QPoint &screenPos);
|
||||||
QPoint mapMouseToItem(QPoint p, HistoryItem *item);
|
QPoint mapPointToItem(QPoint p, HistoryItem *item);
|
||||||
|
|
||||||
void recountHeight();
|
void recountHeight();
|
||||||
void updateSize();
|
void updateSize();
|
||||||
|
|
|
@ -724,34 +724,31 @@ void HistoryItem::detachFast() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::previousItemChanged() {
|
void HistoryItem::previousItemChanged() {
|
||||||
|
Expects(!isLogEntry());
|
||||||
recountDisplayDate();
|
recountDisplayDate();
|
||||||
recountAttachToPrevious();
|
recountAttachToPrevious();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called only if there is no more next item! Not always when it changes!
|
// Called only if there is no more next item! Not always when it changes!
|
||||||
void HistoryItem::nextItemChanged() {
|
void HistoryItem::nextItemChanged() {
|
||||||
|
Expects(!isLogEntry());
|
||||||
setAttachToNext(false);
|
setAttachToNext(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::recountAttachToPrevious() {
|
void HistoryItem::recountAttachToPrevious() {
|
||||||
bool attach = false;
|
Expects(!isLogEntry());
|
||||||
|
auto attachToPrevious = false;
|
||||||
if (auto previous = previousItem()) {
|
if (auto previous = previousItem()) {
|
||||||
if (!Has<HistoryMessageDate>() && !Has<HistoryMessageUnreadBar>()) {
|
if (!Has<HistoryMessageDate>() && !Has<HistoryMessageUnreadBar>()) {
|
||||||
attach = !isPost() && !previous->isPost()
|
attachToPrevious = !isPost() && !previous->isPost()
|
||||||
&& !serviceMsg() && !previous->serviceMsg()
|
&& !serviceMsg() && !previous->serviceMsg()
|
||||||
&& !isEmpty() && !previous->isEmpty()
|
&& !isEmpty() && !previous->isEmpty()
|
||||||
&& previous->from() == from()
|
&& previous->from() == from()
|
||||||
&& (qAbs(previous->date.secsTo(date)) < kAttachMessageToPreviousSecondsDelta);
|
&& (qAbs(previous->date.secsTo(date)) < kAttachMessageToPreviousSecondsDelta);
|
||||||
}
|
}
|
||||||
previous->setAttachToNext(attach);
|
previous->setAttachToNext(attachToPrevious);
|
||||||
}
|
|
||||||
if (attach && !(_flags & MTPDmessage_ClientFlag::f_attach_to_previous)) {
|
|
||||||
_flags |= MTPDmessage_ClientFlag::f_attach_to_previous;
|
|
||||||
setPendingInitDimensions();
|
|
||||||
} else if (!attach && (_flags & MTPDmessage_ClientFlag::f_attach_to_previous)) {
|
|
||||||
_flags &= ~MTPDmessage_ClientFlag::f_attach_to_previous;
|
|
||||||
setPendingInitDimensions();
|
|
||||||
}
|
}
|
||||||
|
setAttachToPrevious(attachToPrevious);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::setAttachToNext(bool attachToNext) {
|
void HistoryItem::setAttachToNext(bool attachToNext) {
|
||||||
|
@ -764,6 +761,16 @@ void HistoryItem::setAttachToNext(bool attachToNext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryItem::setAttachToPrevious(bool attachToPrevious) {
|
||||||
|
if (attachToPrevious && !(_flags & MTPDmessage_ClientFlag::f_attach_to_previous)) {
|
||||||
|
_flags |= MTPDmessage_ClientFlag::f_attach_to_previous;
|
||||||
|
setPendingInitDimensions();
|
||||||
|
} else if (!attachToPrevious && (_flags & MTPDmessage_ClientFlag::f_attach_to_previous)) {
|
||||||
|
_flags &= ~MTPDmessage_ClientFlag::f_attach_to_previous;
|
||||||
|
setPendingInitDimensions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryItem::setId(MsgId newId) {
|
void HistoryItem::setId(MsgId newId) {
|
||||||
history()->changeMsgId(id, newId);
|
history()->changeMsgId(id, newId);
|
||||||
id = newId;
|
id = newId;
|
||||||
|
@ -954,6 +961,8 @@ bool HistoryItem::unread() const {
|
||||||
|
|
||||||
void HistoryItem::destroyUnreadBar() {
|
void HistoryItem::destroyUnreadBar() {
|
||||||
if (Has<HistoryMessageUnreadBar>()) {
|
if (Has<HistoryMessageUnreadBar>()) {
|
||||||
|
t_assert(!isLogEntry());
|
||||||
|
|
||||||
RemoveComponents(HistoryMessageUnreadBar::Bit());
|
RemoveComponents(HistoryMessageUnreadBar::Bit());
|
||||||
setPendingInitDimensions();
|
setPendingInitDimensions();
|
||||||
if (_history->unreadBar == this) {
|
if (_history->unreadBar == this) {
|
||||||
|
@ -965,6 +974,7 @@ void HistoryItem::destroyUnreadBar() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::setUnreadBarCount(int count) {
|
void HistoryItem::setUnreadBarCount(int count) {
|
||||||
|
Expects(!isLogEntry());
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
HistoryMessageUnreadBar *bar;
|
HistoryMessageUnreadBar *bar;
|
||||||
if (!Has<HistoryMessageUnreadBar>()) {
|
if (!Has<HistoryMessageUnreadBar>()) {
|
||||||
|
@ -988,6 +998,7 @@ void HistoryItem::setUnreadBarCount(int count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::setUnreadBarFreezed() {
|
void HistoryItem::setUnreadBarFreezed() {
|
||||||
|
Expects(!isLogEntry());
|
||||||
if (auto bar = Get<HistoryMessageUnreadBar>()) {
|
if (auto bar = Get<HistoryMessageUnreadBar>()) {
|
||||||
bar->_freezed = true;
|
bar->_freezed = true;
|
||||||
}
|
}
|
||||||
|
@ -1010,14 +1021,14 @@ void HistoryItem::clipCallback(Media::Clip::Notification notification) {
|
||||||
case NotificationReinit: {
|
case NotificationReinit: {
|
||||||
auto stopped = false;
|
auto stopped = false;
|
||||||
if (reader->autoPausedGif()) {
|
if (reader->autoPausedGif()) {
|
||||||
if (auto m = App::main()) {
|
auto amVisible = false;
|
||||||
if (!m->isItemVisible(this)) { // stop animation if it is not visible
|
AuthSession::Current().data().queryItemVisibility().notify({ this, &amVisible }, true);
|
||||||
media->stopInline();
|
if (!amVisible) { // stop animation if it is not visible
|
||||||
if (auto document = media->getDocument()) { // forget data from memory
|
media->stopInline();
|
||||||
document->forget();
|
if (auto document = media->getDocument()) { // forget data from memory
|
||||||
}
|
document->forget();
|
||||||
stopped = true;
|
|
||||||
}
|
}
|
||||||
|
stopped = true;
|
||||||
}
|
}
|
||||||
} else if (reader->mode() == Media::Clip::Reader::Mode::Video && reader->state() == Media::Clip::State::Finished) {
|
} else if (reader->mode() == Media::Clip::Reader::Mode::Video && reader->state() == Media::Clip::State::Finished) {
|
||||||
// Stop finished video message.
|
// Stop finished video message.
|
||||||
|
@ -1065,7 +1076,8 @@ void HistoryItem::audioTrackUpdated() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::recountDisplayDate() {
|
void HistoryItem::recountDisplayDate() {
|
||||||
bool displayingDate = ([this]() {
|
Expects(!isLogEntry());
|
||||||
|
setDisplayDate(([this]() {
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1074,13 +1086,15 @@ void HistoryItem::recountDisplayDate() {
|
||||||
return previous->isEmpty() || (previous->date.date() != date.date());
|
return previous->isEmpty() || (previous->date.date() != date.date());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
})();
|
})());
|
||||||
|
}
|
||||||
|
|
||||||
if (displayingDate && !Has<HistoryMessageDate>()) {
|
void HistoryItem::setDisplayDate(bool displayDate) {
|
||||||
|
if (displayDate && !Has<HistoryMessageDate>()) {
|
||||||
AddComponents(HistoryMessageDate::Bit());
|
AddComponents(HistoryMessageDate::Bit());
|
||||||
Get<HistoryMessageDate>()->init(date);
|
Get<HistoryMessageDate>()->init(date);
|
||||||
setPendingInitDimensions();
|
setPendingInitDimensions();
|
||||||
} else if (!displayingDate && Has<HistoryMessageDate>()) {
|
} else if (!displayDate && Has<HistoryMessageDate>()) {
|
||||||
RemoveComponents(HistoryMessageDate::Bit());
|
RemoveComponents(HistoryMessageDate::Bit());
|
||||||
setPendingInitDimensions();
|
setPendingInitDimensions();
|
||||||
}
|
}
|
||||||
|
|
|
@ -542,6 +542,7 @@ public:
|
||||||
return !_block;
|
return !_block;
|
||||||
}
|
}
|
||||||
void attachToBlock(HistoryBlock *block, int index) {
|
void attachToBlock(HistoryBlock *block, int index) {
|
||||||
|
Expects(!isLogEntry());
|
||||||
Expects(_block == nullptr);
|
Expects(_block == nullptr);
|
||||||
Expects(_indexInBlock < 0);
|
Expects(_indexInBlock < 0);
|
||||||
Expects(block != nullptr);
|
Expects(block != nullptr);
|
||||||
|
@ -820,7 +821,7 @@ public:
|
||||||
}
|
}
|
||||||
void setPendingResize() {
|
void setPendingResize() {
|
||||||
_flags |= MTPDmessage_ClientFlag::f_pending_resize;
|
_flags |= MTPDmessage_ClientFlag::f_pending_resize;
|
||||||
if (!detached()) {
|
if (!detached() || isLogEntry()) {
|
||||||
_history->setHasPendingResizedItems();
|
_history->setHasPendingResizedItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -879,6 +880,19 @@ public:
|
||||||
void clipCallback(Media::Clip::Notification notification);
|
void clipCallback(Media::Clip::Notification notification);
|
||||||
void audioTrackUpdated();
|
void audioTrackUpdated();
|
||||||
|
|
||||||
|
void setLogEntryDisplayDate(bool displayDate) {
|
||||||
|
Expects(isLogEntry());
|
||||||
|
setDisplayDate(displayDate);
|
||||||
|
}
|
||||||
|
void setLogEntryAttachToPrevious(bool attachToPrevious) {
|
||||||
|
Expects(isLogEntry());
|
||||||
|
setAttachToNext(attachToPrevious);
|
||||||
|
}
|
||||||
|
void setLogEntryAttachToNext(bool attachToNext) {
|
||||||
|
Expects(isLogEntry());
|
||||||
|
setAttachToNext(attachToNext);
|
||||||
|
}
|
||||||
|
|
||||||
~HistoryItem();
|
~HistoryItem();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -929,18 +943,27 @@ protected:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this should be called only from previousItemChanged()
|
// This should be called only from previousItemChanged()
|
||||||
// to add required bits to the Composer mask
|
// to add required bits to the Composer mask
|
||||||
// after that always use Has<HistoryMessageDate>()
|
// after that always use Has<HistoryMessageDate>().
|
||||||
void recountDisplayDate();
|
void recountDisplayDate();
|
||||||
|
|
||||||
// this should be called only from previousItemChanged() or when
|
// This should be called only from previousItemChanged() or when
|
||||||
// HistoryMessageDate or HistoryMessageUnreadBar bit is changed in the Composer mask
|
// HistoryMessageDate or HistoryMessageUnreadBar bit is changed in the Composer mask
|
||||||
// then the result should be cached in a client side flag MTPDmessage_ClientFlag::f_attach_to_previous
|
// then the result should be cached in a client side flag MTPDmessage_ClientFlag::f_attach_to_previous.
|
||||||
void recountAttachToPrevious();
|
void recountAttachToPrevious();
|
||||||
|
|
||||||
// this should be called only recountAttachToPrevious() of the next item
|
// This should be called only from recountDisplayDate().
|
||||||
// or when the next item is removed through nextItemChanged() call
|
// Also this is called from setLogEntryDisplayDate() for channel log entries.
|
||||||
|
void setDisplayDate(bool displayDate);
|
||||||
|
|
||||||
|
// This should be called only from recountAttachToPrevious().
|
||||||
|
// Also this is called from setLogEntryAttachToPrevious() for channel log entries.
|
||||||
|
void setAttachToPrevious(bool attachToNext);
|
||||||
|
|
||||||
|
// This should be called only from recountAttachToPrevious() of the next item
|
||||||
|
// or when the next item is removed through nextItemChanged() call.
|
||||||
|
// Also this is called from setLogEntryAttachToNext() for channel log entries.
|
||||||
void setAttachToNext(bool attachToNext);
|
void setAttachToNext(bool attachToNext);
|
||||||
|
|
||||||
const HistoryMessageReplyMarkup *inlineReplyMarkup() const {
|
const HistoryMessageReplyMarkup *inlineReplyMarkup() const {
|
||||||
|
|
|
@ -681,6 +681,19 @@ HistoryWidget::HistoryWidget(QWidget *parent, gsl::not_null<Window::Controller*>
|
||||||
// So we force HistoryWidget::resizeEvent() here, without WA_UpdatesDisabled.
|
// So we force HistoryWidget::resizeEvent() here, without WA_UpdatesDisabled.
|
||||||
myEnsureResized(this);
|
myEnsureResized(this);
|
||||||
});
|
});
|
||||||
|
subscribe(AuthSession::Current().data().pendingHistoryResize(), [this] { handlePendingHistoryUpdate(); });
|
||||||
|
subscribe(AuthSession::Current().data().queryItemVisibility(), [this](const AuthSessionData::ItemVisibilityQuery &query) {
|
||||||
|
if (_a_show.animating() || _history != query.item->history() || query.item->detached() || !isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto top = _list->itemTop(query.item);
|
||||||
|
if (top >= 0) {
|
||||||
|
auto scrollTop = _scroll->scrollTop();
|
||||||
|
if (top + query.item->height() > scrollTop && top < scrollTop + _scroll->height()) {
|
||||||
|
*query.isVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
orderWidgets();
|
orderWidgets();
|
||||||
}
|
}
|
||||||
|
@ -701,7 +714,7 @@ void HistoryWidget::scrollToCurrentVoiceMessage(FullMsgId fromId, FullMsgId toId
|
||||||
|
|
||||||
// If history has pending resize items, the scrollTopItem won't be updated.
|
// If history has pending resize items, the scrollTopItem won't be updated.
|
||||||
// And the scrollTop will be reset back to scrollTopItem + scrollTopOffset.
|
// And the scrollTop will be reset back to scrollTopItem + scrollTopOffset.
|
||||||
notify_handlePendingHistoryUpdate();
|
handlePendingHistoryUpdate();
|
||||||
|
|
||||||
auto toTop = _list->itemTop(to);
|
auto toTop = _list->itemTop(to);
|
||||||
if (toTop >= 0 && !isItemCompletelyHidden(from)) {
|
if (toTop >= 0 && !isItemCompletelyHidden(from)) {
|
||||||
|
@ -4782,17 +4795,6 @@ void HistoryWidget::grabFinish() {
|
||||||
_topShadow->show();
|
_topShadow->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryWidget::isItemVisible(HistoryItem *item) {
|
|
||||||
if (isHidden() || _a_show.animating() || !_list) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int32 top = _list->itemTop(item), st = _scroll->scrollTop();
|
|
||||||
if (top < 0 || top + item->height() <= st || top >= st + _scroll->height()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryWidget::ui_repaintHistoryItem(gsl::not_null<const HistoryItem*> item) {
|
void HistoryWidget::ui_repaintHistoryItem(gsl::not_null<const HistoryItem*> item) {
|
||||||
if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) {
|
if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) {
|
||||||
auto ms = getms();
|
auto ms = getms();
|
||||||
|
@ -4825,7 +4827,7 @@ void HistoryWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::notify_handlePendingHistoryUpdate() {
|
void HistoryWidget::handlePendingHistoryUpdate() {
|
||||||
if (hasPendingResizedItems() || _updateHistoryGeometryRequired) {
|
if (hasPendingResizedItems() || _updateHistoryGeometryRequired) {
|
||||||
if (_list) {
|
if (_list) {
|
||||||
updateHistoryGeometry();
|
updateHistoryGeometry();
|
||||||
|
|
|
@ -356,7 +356,6 @@ public:
|
||||||
bool notify_switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot, MsgId samePeerReplyTo);
|
bool notify_switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot, MsgId samePeerReplyTo);
|
||||||
void notify_userIsBotChanged(UserData *user);
|
void notify_userIsBotChanged(UserData *user);
|
||||||
void notify_migrateUpdated(PeerData *peer);
|
void notify_migrateUpdated(PeerData *peer);
|
||||||
void notify_handlePendingHistoryUpdate();
|
|
||||||
|
|
||||||
bool cmd_search();
|
bool cmd_search();
|
||||||
bool cmd_next_chat();
|
bool cmd_next_chat();
|
||||||
|
@ -484,6 +483,7 @@ private:
|
||||||
bool allFilesForCompress = true;
|
bool allFilesForCompress = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void handlePendingHistoryUpdate();
|
||||||
void fullPeerUpdated(PeerData *peer);
|
void fullPeerUpdated(PeerData *peer);
|
||||||
void topBarClick();
|
void topBarClick();
|
||||||
void toggleTabbedSelectorMode();
|
void toggleTabbedSelectorMode();
|
||||||
|
|
|
@ -819,13 +819,6 @@ void MainWidget::onFilesOrForwardDrop(const PeerId &peerId, const QMimeData *dat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWidget::isItemVisible(HistoryItem *item) {
|
|
||||||
if (isHidden() || _a_show.animating()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return _history->isItemVisible(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWidget::notify_botCommandsChanged(UserData *bot) {
|
void MainWidget::notify_botCommandsChanged(UserData *bot) {
|
||||||
_history->notify_botCommandsChanged(bot);
|
_history->notify_botCommandsChanged(bot);
|
||||||
}
|
}
|
||||||
|
@ -901,10 +894,6 @@ void MainWidget::notify_historyMuteUpdated(History *history) {
|
||||||
_dialogs->notify_historyMuteUpdated(history);
|
_dialogs->notify_historyMuteUpdated(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::notify_handlePendingHistoryUpdate() {
|
|
||||||
_history->notify_handlePendingHistoryUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MainWidget::cmd_search() {
|
bool MainWidget::cmd_search() {
|
||||||
if (Ui::isLayerShown() || Ui::isMediaViewShown()) return false;
|
if (Ui::isLayerShown() || Ui::isMediaViewShown()) return false;
|
||||||
return _history->cmd_search();
|
return _history->cmd_search();
|
||||||
|
|
|
@ -378,8 +378,6 @@ public:
|
||||||
|
|
||||||
bool contentOverlapped(const QRect &globalRect);
|
bool contentOverlapped(const QRect &globalRect);
|
||||||
|
|
||||||
bool isItemVisible(HistoryItem *item);
|
|
||||||
|
|
||||||
void documentLoadProgress(DocumentData *document);
|
void documentLoadProgress(DocumentData *document);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -398,7 +396,6 @@ public:
|
||||||
void notify_migrateUpdated(PeerData *peer);
|
void notify_migrateUpdated(PeerData *peer);
|
||||||
void notify_historyItemLayoutChanged(const HistoryItem *item);
|
void notify_historyItemLayoutChanged(const HistoryItem *item);
|
||||||
void notify_historyMuteUpdated(History *history);
|
void notify_historyMuteUpdated(History *history);
|
||||||
void notify_handlePendingHistoryUpdate();
|
|
||||||
|
|
||||||
bool cmd_search();
|
bool cmd_search();
|
||||||
bool cmd_next_chat();
|
bool cmd_next_chat();
|
||||||
|
|
Loading…
Reference in New Issue