mirror of https://github.com/procxx/kepka.git
Save item views in App::*Item() variables.
Also remove App::contextItem. Also use owning pointers for history context menus.
This commit is contained in:
parent
8060cb7426
commit
062b0b2165
|
@ -89,11 +89,10 @@ namespace {
|
||||||
using SentData = QMap<uint64, QPair<PeerId, QString>>;
|
using SentData = QMap<uint64, QPair<PeerId, QString>>;
|
||||||
SentData sentData;
|
SentData sentData;
|
||||||
|
|
||||||
HistoryItem *hoveredItem = nullptr,
|
HistoryView::Message *hoveredItem = nullptr,
|
||||||
*pressedItem = nullptr,
|
*pressedItem = nullptr,
|
||||||
*hoveredLinkItem = nullptr,
|
*hoveredLinkItem = nullptr,
|
||||||
*pressedLinkItem = nullptr,
|
*pressedLinkItem = nullptr,
|
||||||
*contextItem = nullptr,
|
|
||||||
*mousedItem = nullptr;
|
*mousedItem = nullptr;
|
||||||
|
|
||||||
QPixmap *emoji = nullptr, *emojiLarge = nullptr;
|
QPixmap *emoji = nullptr, *emojiLarge = nullptr;
|
||||||
|
@ -934,7 +933,7 @@ namespace {
|
||||||
: nullptr);
|
: nullptr);
|
||||||
existing->setViewsCount(m.has_views() ? m.vviews.v : -1);
|
existing->setViewsCount(m.has_views() ? m.vviews.v : -1);
|
||||||
existing->indexAsNewItem();
|
existing->indexAsNewItem();
|
||||||
if (!existing->detached()) {
|
if (existing->mainView()) {
|
||||||
App::checkSavedGif(existing);
|
App::checkSavedGif(existing);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1836,23 +1835,20 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void historyItemDetached(HistoryItem *item) {
|
void messageViewDestroyed(not_null<HistoryView::Message*> view) {
|
||||||
if (::hoveredItem == item) {
|
if (::hoveredItem == view) {
|
||||||
hoveredItem(nullptr);
|
hoveredItem(nullptr);
|
||||||
}
|
}
|
||||||
if (::pressedItem == item) {
|
if (::pressedItem == view) {
|
||||||
pressedItem(nullptr);
|
pressedItem(nullptr);
|
||||||
}
|
}
|
||||||
if (::hoveredLinkItem == item) {
|
if (::hoveredLinkItem == view) {
|
||||||
hoveredLinkItem(nullptr);
|
hoveredLinkItem(nullptr);
|
||||||
}
|
}
|
||||||
if (::pressedLinkItem == item) {
|
if (::pressedLinkItem == view) {
|
||||||
pressedLinkItem(nullptr);
|
pressedLinkItem(nullptr);
|
||||||
}
|
}
|
||||||
if (::contextItem == item) {
|
if (::mousedItem == view) {
|
||||||
contextItem(nullptr);
|
|
||||||
}
|
|
||||||
if (::mousedItem == item) {
|
|
||||||
mousedItem(nullptr);
|
mousedItem(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1867,7 +1863,6 @@ namespace {
|
||||||
data->erase(i);
|
data->erase(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
historyItemDetached(item);
|
|
||||||
auto j = ::dependentItems.find(item);
|
auto j = ::dependentItems.find(item);
|
||||||
if (j != ::dependentItems.cend()) {
|
if (j != ::dependentItems.cend()) {
|
||||||
DependentItemsSet items;
|
DependentItemsSet items;
|
||||||
|
@ -1903,13 +1898,13 @@ namespace {
|
||||||
|
|
||||||
QVector<HistoryItem*> toDelete;
|
QVector<HistoryItem*> toDelete;
|
||||||
for_const (auto item, msgsData) {
|
for_const (auto item, msgsData) {
|
||||||
if (item->detached()) {
|
if (!item->mainView()) {
|
||||||
toDelete.push_back(item);
|
toDelete.push_back(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for_const (auto &chMsgsData, channelMsgsData) {
|
for_const (auto &chMsgsData, channelMsgsData) {
|
||||||
for_const (auto item, chMsgsData) {
|
for_const (auto item, chMsgsData) {
|
||||||
if (item->detached()) {
|
if (!item->mainView()) {
|
||||||
toDelete.push_back(item);
|
toDelete.push_back(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2187,51 +2182,43 @@ namespace {
|
||||||
clearAllImages();
|
clearAllImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
void hoveredItem(HistoryItem *item) {
|
void hoveredItem(HistoryView::Message *item) {
|
||||||
::hoveredItem = item;
|
::hoveredItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *hoveredItem() {
|
HistoryView::Message *hoveredItem() {
|
||||||
return ::hoveredItem;
|
return ::hoveredItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pressedItem(HistoryItem *item) {
|
void pressedItem(HistoryView::Message *item) {
|
||||||
::pressedItem = item;
|
::pressedItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *pressedItem() {
|
HistoryView::Message *pressedItem() {
|
||||||
return ::pressedItem;
|
return ::pressedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hoveredLinkItem(HistoryItem *item) {
|
void hoveredLinkItem(HistoryView::Message *item) {
|
||||||
::hoveredLinkItem = item;
|
::hoveredLinkItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *hoveredLinkItem() {
|
HistoryView::Message *hoveredLinkItem() {
|
||||||
return ::hoveredLinkItem;
|
return ::hoveredLinkItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pressedLinkItem(HistoryItem *item) {
|
void pressedLinkItem(HistoryView::Message *item) {
|
||||||
::pressedLinkItem = item;
|
::pressedLinkItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *pressedLinkItem() {
|
HistoryView::Message *pressedLinkItem() {
|
||||||
return ::pressedLinkItem;
|
return ::pressedLinkItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void contextItem(HistoryItem *item) {
|
void mousedItem(HistoryView::Message *item) {
|
||||||
::contextItem = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
HistoryItem *contextItem() {
|
|
||||||
return ::contextItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mousedItem(HistoryItem *item) {
|
|
||||||
::mousedItem = item;
|
::mousedItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *mousedItem() {
|
HistoryView::Message *mousedItem() {
|
||||||
return ::mousedItem;
|
return ::mousedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2240,7 +2227,6 @@ namespace {
|
||||||
pressedItem(nullptr);
|
pressedItem(nullptr);
|
||||||
hoveredLinkItem(nullptr);
|
hoveredLinkItem(nullptr);
|
||||||
pressedLinkItem(nullptr);
|
pressedLinkItem(nullptr);
|
||||||
contextItem(nullptr);
|
|
||||||
mousedItem(nullptr);
|
mousedItem(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
class Messenger;
|
class Messenger;
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
class MainWidget;
|
class MainWidget;
|
||||||
|
class LocationCoords;
|
||||||
|
struct LocationData;
|
||||||
|
|
||||||
|
namespace HistoryView {
|
||||||
|
class Message;
|
||||||
|
} // namespace HistoryView
|
||||||
|
|
||||||
using HistoryItemsMap = OrderedSet<HistoryItem*>;
|
using HistoryItemsMap = OrderedSet<HistoryItem*>;
|
||||||
using PhotoItems = QHash<PhotoData*, HistoryItemsMap>;
|
using PhotoItems = QHash<PhotoData*, HistoryItemsMap>;
|
||||||
|
@ -27,9 +33,6 @@ using GifItems = QHash<Media::Clip::Reader*, HistoryItem*>;
|
||||||
using PhotosData = QHash<PhotoId, PhotoData*>;
|
using PhotosData = QHash<PhotoId, PhotoData*>;
|
||||||
using DocumentsData = QHash<DocumentId, DocumentData*>;
|
using DocumentsData = QHash<DocumentId, DocumentData*>;
|
||||||
|
|
||||||
class LocationCoords;
|
|
||||||
struct LocationData;
|
|
||||||
|
|
||||||
namespace App {
|
namespace App {
|
||||||
MainWindow *wnd();
|
MainWindow *wnd();
|
||||||
MainWidget *main();
|
MainWidget *main();
|
||||||
|
@ -190,13 +193,13 @@ namespace App {
|
||||||
return histItemById(msgId.channel, msgId.msg);
|
return histItemById(msgId.channel, msgId.msg);
|
||||||
}
|
}
|
||||||
void historyRegItem(HistoryItem *item);
|
void historyRegItem(HistoryItem *item);
|
||||||
void historyItemDetached(HistoryItem *item);
|
|
||||||
void historyUnregItem(HistoryItem *item);
|
void historyUnregItem(HistoryItem *item);
|
||||||
void historyUpdateDependent(HistoryItem *item);
|
void historyUpdateDependent(HistoryItem *item);
|
||||||
void historyClearMsgs();
|
void historyClearMsgs();
|
||||||
void historyClearItems();
|
void historyClearItems();
|
||||||
void historyRegDependency(HistoryItem *dependent, HistoryItem *dependency);
|
void historyRegDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||||
void historyUnregDependency(HistoryItem *dependent, HistoryItem *dependency);
|
void historyUnregDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||||
|
void messageViewDestroyed(not_null<HistoryView::Message*> view);
|
||||||
|
|
||||||
void historyRegRandom(uint64 randomId, const FullMsgId &itemId);
|
void historyRegRandom(uint64 randomId, const FullMsgId &itemId);
|
||||||
void historyUnregRandom(uint64 randomId);
|
void historyUnregRandom(uint64 randomId);
|
||||||
|
@ -205,18 +208,16 @@ namespace App {
|
||||||
void historyUnregSentData(uint64 randomId);
|
void historyUnregSentData(uint64 randomId);
|
||||||
void histSentDataByItem(uint64 randomId, PeerId &peerId, QString &text);
|
void histSentDataByItem(uint64 randomId, PeerId &peerId, QString &text);
|
||||||
|
|
||||||
void hoveredItem(HistoryItem *item);
|
void hoveredItem(HistoryView::Message *item);
|
||||||
HistoryItem *hoveredItem();
|
HistoryView::Message *hoveredItem();
|
||||||
void pressedItem(HistoryItem *item);
|
void pressedItem(HistoryView::Message *item);
|
||||||
HistoryItem *pressedItem();
|
HistoryView::Message *pressedItem();
|
||||||
void hoveredLinkItem(HistoryItem *item);
|
void hoveredLinkItem(HistoryView::Message *item);
|
||||||
HistoryItem *hoveredLinkItem();
|
HistoryView::Message *hoveredLinkItem();
|
||||||
void pressedLinkItem(HistoryItem *item);
|
void pressedLinkItem(HistoryView::Message *item);
|
||||||
HistoryItem *pressedLinkItem();
|
HistoryView::Message *pressedLinkItem();
|
||||||
void contextItem(HistoryItem *item);
|
void mousedItem(HistoryView::Message *item);
|
||||||
HistoryItem *contextItem();
|
HistoryView::Message *mousedItem();
|
||||||
void mousedItem(HistoryItem *item);
|
|
||||||
HistoryItem *mousedItem();
|
|
||||||
void clearMousedItems();
|
void clearMousedItems();
|
||||||
|
|
||||||
const style::font &monofont();
|
const style::font &monofont();
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "messenger.h"
|
#include "messenger.h"
|
||||||
#include "platform/platform_specific.h"
|
#include "platform/platform_specific.h"
|
||||||
|
#include "history/view/history_view_message.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "base/qthelp_regex.h"
|
#include "base/qthelp_regex.h"
|
||||||
#include "base/qthelp_url.h"
|
#include "base/qthelp_url.h"
|
||||||
|
@ -241,10 +242,11 @@ void BotCommandClickHandler::onClick(Qt::MouseButton button) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto peer = Ui::getPeerForMouseAction()) { // old way
|
if (auto peer = Ui::getPeerForMouseAction()) { // old way
|
||||||
UserData *bot = peer->isUser() ? peer->asUser() : nullptr;
|
auto bot = peer->isUser() ? peer->asUser() : nullptr;
|
||||||
if (auto item = App::hoveredLinkItem()) {
|
if (!bot) {
|
||||||
if (!bot) {
|
if (const auto view = App::hoveredLinkItem()) {
|
||||||
bot = item->fromOriginal()->asUser(); // may return nullptr
|
// may return nullptr
|
||||||
|
bot = view->data()->fromOriginal()->asUser();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ui::showPeerHistory(peer, ShowAtTheEndMsgId);
|
Ui::showPeerHistory(peer, ShowAtTheEndMsgId);
|
||||||
|
|
|
@ -527,7 +527,6 @@ inline int ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) {
|
||||||
|
|
||||||
enum ForwardWhatMessages {
|
enum ForwardWhatMessages {
|
||||||
ForwardSelectedMessages,
|
ForwardSelectedMessages,
|
||||||
ForwardContextMessage,
|
|
||||||
ForwardPressedMessage,
|
ForwardPressedMessage,
|
||||||
ForwardPressedLinkMessage
|
ForwardPressedLinkMessage
|
||||||
};
|
};
|
||||||
|
|
|
@ -336,7 +336,9 @@ void DocumentSaveClickHandler::doSave(
|
||||||
bool forceSavingAs) {
|
bool forceSavingAs) {
|
||||||
if (!data->date) return;
|
if (!data->date) return;
|
||||||
|
|
||||||
auto filepath = data->filepath(DocumentData::FilePathResolveSaveFromDataSilent, forceSavingAs);
|
auto filepath = data->filepath(
|
||||||
|
DocumentData::FilePathResolveSaveFromDataSilent,
|
||||||
|
forceSavingAs);
|
||||||
if (!filepath.isEmpty() && !forceSavingAs) {
|
if (!filepath.isEmpty() && !forceSavingAs) {
|
||||||
File::OpenWith(filepath, QCursor::pos());
|
File::OpenWith(filepath, QCursor::pos());
|
||||||
} else {
|
} else {
|
||||||
|
@ -345,9 +347,7 @@ void DocumentSaveClickHandler::doSave(
|
||||||
auto filename = filepath.isEmpty() ? QString() : fileinfo.fileName();
|
auto filename = filepath.isEmpty() ? QString() : fileinfo.fileName();
|
||||||
auto newfname = documentSaveFilename(data, forceSavingAs, filename, filedir);
|
auto newfname = documentSaveFilename(data, forceSavingAs, filename, filedir);
|
||||||
if (!newfname.isEmpty()) {
|
if (!newfname.isEmpty()) {
|
||||||
auto action = (filename.isEmpty() || forceSavingAs) ? ActionOnLoadNone : ActionOnLoadOpenWith;
|
data->save(newfname, ActionOnLoadNone, FullMsgId());
|
||||||
auto actionMsgId = App::hoveredLinkItem() ? App::hoveredLinkItem()->fullId() : (App::contextItem() ? App::contextItem()->fullId() : FullMsgId());
|
|
||||||
data->save(newfname, action, actionMsgId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -362,8 +362,7 @@ void DocumentCancelClickHandler::onClickImpl() const {
|
||||||
|
|
||||||
if (data->uploading()) {
|
if (data->uploading()) {
|
||||||
if (const auto item = App::histItemById(context())) {
|
if (const auto item = App::histItemById(context())) {
|
||||||
App::contextItem(item);
|
App::main()->cancelUploadLayer(item);
|
||||||
App::main()->cancelUploadLayer();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data->cancel();
|
data->cancel();
|
||||||
|
|
|
@ -137,8 +137,7 @@ void PhotoCancelClickHandler::onClickImpl() const {
|
||||||
|
|
||||||
if (data->uploading()) {
|
if (data->uploading()) {
|
||||||
if (const auto item = App::histItemById(context())) {
|
if (const auto item = App::histItemById(context())) {
|
||||||
App::contextItem(item);
|
App::main()->cancelUploadLayer(item);
|
||||||
App::main()->cancelUploadLayer();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data->cancel();
|
data->cancel();
|
||||||
|
|
|
@ -44,9 +44,5 @@ void MessageCursor::applyTo(QTextEdit *edit) {
|
||||||
HistoryItem *FileClickHandler::getActionItem() const {
|
HistoryItem *FileClickHandler::getActionItem() const {
|
||||||
return context()
|
return context()
|
||||||
? App::histItemById(context())
|
? App::histItemById(context())
|
||||||
: App::hoveredLinkItem()
|
|
||||||
? App::hoveredLinkItem()
|
|
||||||
: App::contextItem()
|
|
||||||
? App::contextItem()
|
|
||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -418,13 +418,14 @@ void InnerWidget::updateEmptyText() {
|
||||||
|
|
||||||
QString InnerWidget::tooltipText() const {
|
QString InnerWidget::tooltipText() const {
|
||||||
if (_mouseCursorState == HistoryInDateCursorState && _mouseAction == MouseAction::None) {
|
if (_mouseCursorState == HistoryInDateCursorState && _mouseAction == MouseAction::None) {
|
||||||
if (const auto item = App::hoveredItem()) {
|
if (const auto view = App::hoveredItem()) {
|
||||||
auto dateText = item->date.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat));
|
auto dateText = view->data()->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 (const auto item = App::hoveredItem()) {
|
if (const auto view = App::hoveredItem()) {
|
||||||
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
|
if (const auto forwarded = view->data()->Get<HistoryMessageForwarded>()) {
|
||||||
return forwarded->text.originalText(AllTextSelection, ExpandLinksNone);
|
return forwarded->text.originalText(AllTextSelection, ExpandLinksNone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -808,10 +809,6 @@ void InnerWidget::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
if (_menu) {
|
|
||||||
_menu->deleteLater();
|
|
||||||
_menu = 0;
|
|
||||||
}
|
|
||||||
if (e->reason() == QContextMenuEvent::Mouse) {
|
if (e->reason() == QContextMenuEvent::Mouse) {
|
||||||
mouseActionUpdate(e->globalPos());
|
mouseActionUpdate(e->globalPos());
|
||||||
}
|
}
|
||||||
|
@ -828,10 +825,10 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
if (App::mousedItem() && App::mousedItem() == App::hoveredItem()) {
|
if (App::mousedItem() && App::mousedItem() == App::hoveredItem()) {
|
||||||
auto mousePos = mapPointToItem(
|
auto mousePos = mapPointToItem(
|
||||||
mapFromGlobal(_mousePosition),
|
mapFromGlobal(_mousePosition),
|
||||||
viewForItem(App::mousedItem()));
|
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()->data()->getState(mousePos, request);
|
||||||
if (dragState.cursor == HistoryInTextCursorState && dragState.symbol >= selFrom && dragState.symbol < selTo) {
|
if (dragState.cursor == HistoryInTextCursorState && dragState.symbol >= selFrom && dragState.symbol < selTo) {
|
||||||
isUponSelected = 1;
|
isUponSelected = 1;
|
||||||
}
|
}
|
||||||
|
@ -841,10 +838,12 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
isUponSelected = hasSelected;
|
isUponSelected = hasSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
_menu = new Ui::PopupMenu(nullptr);
|
_menu = base::make_unique_q<Ui::PopupMenu>(nullptr);
|
||||||
|
|
||||||
_contextMenuLink = ClickHandler::getActive();
|
_contextMenuLink = ClickHandler::getActive();
|
||||||
auto item = App::hoveredItem() ? App::hoveredItem() : App::hoveredLinkItem();
|
auto view = App::hoveredItem()
|
||||||
|
? App::hoveredItem()
|
||||||
|
: App::hoveredLinkItem();
|
||||||
auto lnkPhoto = dynamic_cast<PhotoClickHandler*>(_contextMenuLink.get());
|
auto lnkPhoto = dynamic_cast<PhotoClickHandler*>(_contextMenuLink.get());
|
||||||
auto lnkDocument = dynamic_cast<DocumentClickHandler*>(_contextMenuLink.get());
|
auto lnkDocument = dynamic_cast<DocumentClickHandler*>(_contextMenuLink.get());
|
||||||
auto lnkPeer = dynamic_cast<PeerClickHandler*>(_contextMenuLink.get());
|
auto lnkPeer = dynamic_cast<PeerClickHandler*>(_contextMenuLink.get());
|
||||||
|
@ -853,41 +852,52 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
auto lnkIsAudio = lnkDocument ? lnkDocument->document()->isAudioFile() : false;
|
auto lnkIsAudio = lnkDocument ? lnkDocument->document()->isAudioFile() : false;
|
||||||
if (lnkPhoto || lnkDocument) {
|
if (lnkPhoto || lnkDocument) {
|
||||||
if (isUponSelected > 0) {
|
if (isUponSelected > 0) {
|
||||||
_menu->addAction(lang(lng_context_copy_selected), [this] { copySelectedText(); })->setEnabled(true);
|
_menu->addAction(lang(lng_context_copy_selected), [=] {
|
||||||
|
copySelectedText();
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
if (lnkPhoto) {
|
if (lnkPhoto) {
|
||||||
_menu->addAction(lang(lng_context_save_image), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, photo = lnkPhoto->photo()] {
|
const auto photo = lnkPhoto->photo();
|
||||||
|
_menu->addAction(lang(lng_context_save_image), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [=] {
|
||||||
savePhotoToFile(photo);
|
savePhotoToFile(photo);
|
||||||
}))->setEnabled(true);
|
}))->setEnabled(true);
|
||||||
_menu->addAction(lang(lng_context_copy_image), [this, photo = lnkPhoto->photo()] {
|
_menu->addAction(lang(lng_context_copy_image), [=] {
|
||||||
copyContextImage(photo);
|
copyContextImage(photo);
|
||||||
})->setEnabled(true);
|
})->setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
auto document = lnkDocument->document();
|
auto document = lnkDocument->document();
|
||||||
if (document->loading()) {
|
if (document->loading()) {
|
||||||
_menu->addAction(lang(lng_context_cancel_download), [this] { cancelContextDownload(); })->setEnabled(true);
|
_menu->addAction(lang(lng_context_cancel_download), [=] {
|
||||||
|
cancelContextDownload(document);
|
||||||
|
})->setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
if (document->loaded() && document->isGifv()) {
|
if (document->loaded() && document->isGifv()) {
|
||||||
if (!cAutoPlayGif()) {
|
if (!cAutoPlayGif()) {
|
||||||
_menu->addAction(lang(lng_context_open_gif), [this] { openContextGif(); })->setEnabled(true);
|
const auto itemId = view
|
||||||
|
? view->data()->fullId()
|
||||||
|
: FullMsgId();
|
||||||
|
_menu->addAction(lang(lng_context_open_gif), [=] {
|
||||||
|
openContextGif(itemId);
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!document->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
|
if (!document->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
|
||||||
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), [this] { showContextInFolder(); })->setEnabled(true);
|
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), [=] {
|
||||||
|
showContextInFolder(document);
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
_menu->addAction(lang(lnkIsVideo ? lng_context_save_video : (lnkIsVoice ? lng_context_save_audio : (lnkIsAudio ? lng_context_save_audio_file : lng_context_save_file))), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
_menu->addAction(lang(lnkIsVideo ? lng_context_save_video : (lnkIsVoice ? lng_context_save_audio : (lnkIsAudio ? lng_context_save_audio_file : lng_context_save_file))), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
||||||
saveDocumentToFile(document);
|
saveDocumentToFile(document);
|
||||||
}))->setEnabled(true);
|
}))->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (App::hoveredLinkItem()) {
|
|
||||||
App::contextItem(App::hoveredLinkItem());
|
|
||||||
}
|
|
||||||
} else if (lnkPeer) { // suggest to block
|
} else if (lnkPeer) { // suggest to block
|
||||||
if (auto user = lnkPeer->peer()->asUser()) {
|
if (auto user = lnkPeer->peer()->asUser()) {
|
||||||
suggestRestrictUser(user);
|
suggestRestrictUser(user);
|
||||||
}
|
}
|
||||||
} else { // maybe cursor on some text history item?
|
} else { // maybe cursor on some text history item?
|
||||||
|
const auto item = view ? view->data().get() : nullptr;
|
||||||
|
const auto itemId = item ? item->fullId() : FullMsgId();
|
||||||
bool canDelete = item && item->canDelete() && (item->id > 0 || !item->serviceMsg());
|
bool canDelete = item && item->canDelete() && (item->id > 0 || !item->serviceMsg());
|
||||||
bool canForward = item && item->canForward();
|
bool canForward = item && item->canForward();
|
||||||
|
|
||||||
|
@ -903,9 +913,11 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
media = static_cast<HistoryWebPage*>(media)->attach();
|
media = static_cast<HistoryWebPage*>(media)->attach();
|
||||||
}
|
}
|
||||||
if (media->type() == MediaTypeSticker) {
|
if (media->type() == MediaTypeSticker) {
|
||||||
if (auto document = media->getDocument()) {
|
if (const auto document = media->getDocument()) {
|
||||||
if (document->sticker() && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
if (document->sticker() && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
||||||
_menu->addAction(lang(document->sticker()->setInstalled() ? lng_context_pack_info : lng_context_pack_add), [this] { showStickerPackInfo(); });
|
_menu->addAction(lang(document->sticker()->setInstalled() ? lng_context_pack_info : lng_context_pack_add), [=] {
|
||||||
|
showStickerPackInfo(document);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
_menu->addAction(lang(lng_context_save_image), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
_menu->addAction(lang(lng_context_save_image), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
||||||
saveDocumentToFile(document);
|
saveDocumentToFile(document);
|
||||||
|
@ -914,15 +926,21 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
} else if (media->type() == MediaTypeGif && !_contextMenuLink) {
|
} else if (media->type() == MediaTypeGif && !_contextMenuLink) {
|
||||||
if (auto document = media->getDocument()) {
|
if (auto document = media->getDocument()) {
|
||||||
if (document->loading()) {
|
if (document->loading()) {
|
||||||
_menu->addAction(lang(lng_context_cancel_download), [this] { cancelContextDownload(); })->setEnabled(true);
|
_menu->addAction(lang(lng_context_cancel_download), [=] {
|
||||||
|
cancelContextDownload(document);
|
||||||
|
})->setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
if (document->isGifv()) {
|
if (document->isGifv()) {
|
||||||
if (!cAutoPlayGif()) {
|
if (!cAutoPlayGif()) {
|
||||||
_menu->addAction(lang(lng_context_open_gif), [this] { openContextGif(); })->setEnabled(true);
|
_menu->addAction(lang(lng_context_open_gif), [=] {
|
||||||
|
openContextGif(itemId);
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!document->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
|
if (!document->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
|
||||||
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), [this] { showContextInFolder(); })->setEnabled(true);
|
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), [=] {
|
||||||
|
showContextInFolder(document);
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
_menu->addAction(lang(lng_context_save_file), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
_menu->addAction(lang(lng_context_save_file), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
||||||
saveDocumentToFile(document);
|
saveDocumentToFile(document);
|
||||||
|
@ -932,7 +950,9 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msg && !_contextMenuLink && (!msg->emptyText() || mediaHasTextForCopy)) {
|
if (msg && !_contextMenuLink && (!msg->emptyText() || mediaHasTextForCopy)) {
|
||||||
_menu->addAction(lang(lng_context_copy_text), [this] { copyContextText(); })->setEnabled(true);
|
_menu->addAction(lang(lng_context_copy_text), [=] {
|
||||||
|
copyContextText(itemId);
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -941,17 +961,11 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
if (!linkCopyToClipboardText.isEmpty()) {
|
if (!linkCopyToClipboardText.isEmpty()) {
|
||||||
_menu->addAction(linkCopyToClipboardText, [this] { copyContextUrl(); })->setEnabled(true);
|
_menu->addAction(linkCopyToClipboardText, [this] { copyContextUrl(); })->setEnabled(true);
|
||||||
}
|
}
|
||||||
App::contextItem(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_menu->actions().isEmpty()) {
|
if (_menu->actions().isEmpty()) {
|
||||||
delete base::take(_menu);
|
_menu = nullptr;
|
||||||
} else {
|
} else {
|
||||||
connect(_menu, &QObject::destroyed, this, [this](QObject *object) {
|
|
||||||
if (_menu == object) {
|
|
||||||
_menu = nullptr;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
_menu->popup(e->globalPos());
|
_menu->popup(e->globalPos());
|
||||||
e->accept();
|
e->accept();
|
||||||
}
|
}
|
||||||
|
@ -961,11 +975,15 @@ void InnerWidget::savePhotoToFile(PhotoData *photo) {
|
||||||
if (!photo || !photo->date || !photo->loaded()) return;
|
if (!photo || !photo->date || !photo->loaded()) return;
|
||||||
|
|
||||||
auto filter = qsl("JPEG Image (*.jpg);;") + FileDialog::AllFilesFilter();
|
auto filter = qsl("JPEG Image (*.jpg);;") + FileDialog::AllFilesFilter();
|
||||||
FileDialog::GetWritePath(lang(lng_save_photo), filter, filedialogDefaultName(qsl("photo"), qsl(".jpg")), base::lambda_guarded(this, [this, photo](const QString &result) {
|
FileDialog::GetWritePath(
|
||||||
if (!result.isEmpty()) {
|
lang(lng_save_photo),
|
||||||
photo->full->pix().toImage().save(result, "JPG");
|
filter,
|
||||||
}
|
filedialogDefaultName(qsl("photo"), qsl(".jpg")),
|
||||||
}));
|
base::lambda_guarded(this, [=](const QString &result) {
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
photo->full->pix().toImage().save(result, "JPG");
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::saveDocumentToFile(DocumentData *document) {
|
void InnerWidget::saveDocumentToFile(DocumentData *document) {
|
||||||
|
@ -988,50 +1006,28 @@ void InnerWidget::copyContextUrl() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::showStickerPackInfo() {
|
void InnerWidget::showStickerPackInfo(not_null<DocumentData*> document) {
|
||||||
if (!App::contextItem()) return;
|
if (auto sticker = document->sticker()) {
|
||||||
|
if (sticker->set.type() != mtpc_inputStickerSetEmpty) {
|
||||||
if (auto media = App::contextItem()->getMedia()) {
|
App::main()->stickersBox(sticker->set);
|
||||||
if (auto doc = media->getDocument()) {
|
|
||||||
if (auto sticker = doc->sticker()) {
|
|
||||||
if (sticker->set.type() != mtpc_inputStickerSetEmpty) {
|
|
||||||
App::main()->stickersBox(sticker->set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::cancelContextDownload() {
|
void InnerWidget::cancelContextDownload(not_null<DocumentData*> document) {
|
||||||
if (auto lnkDocument = dynamic_cast<DocumentClickHandler*>(_contextMenuLink.get())) {
|
document->cancel();
|
||||||
lnkDocument->document()->cancel();
|
|
||||||
} else if (auto item = App::contextItem()) {
|
|
||||||
if (auto media = item->getMedia()) {
|
|
||||||
if (auto doc = media->getDocument()) {
|
|
||||||
doc->cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::showContextInFolder() {
|
void InnerWidget::showContextInFolder(not_null<DocumentData*> document) {
|
||||||
QString filepath;
|
const auto filepath = document->filepath(
|
||||||
if (auto lnkDocument = dynamic_cast<DocumentClickHandler*>(_contextMenuLink.get())) {
|
DocumentData::FilePathResolveChecked);
|
||||||
filepath = lnkDocument->document()->filepath(DocumentData::FilePathResolveChecked);
|
|
||||||
} else if (auto item = App::contextItem()) {
|
|
||||||
if (auto media = item->getMedia()) {
|
|
||||||
if (auto doc = media->getDocument()) {
|
|
||||||
filepath = doc->filepath(DocumentData::FilePathResolveChecked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!filepath.isEmpty()) {
|
if (!filepath.isEmpty()) {
|
||||||
File::ShowInFolder(filepath);
|
File::ShowInFolder(filepath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::openContextGif() {
|
void InnerWidget::openContextGif(FullMsgId itemId) {
|
||||||
if (auto item = App::contextItem()) {
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
if (auto media = item->getMedia()) {
|
if (auto media = item->getMedia()) {
|
||||||
if (auto document = media->getDocument()) {
|
if (auto document = media->getDocument()) {
|
||||||
Messenger::Instance().showDocument(document, item);
|
Messenger::Instance().showDocument(document, item);
|
||||||
|
@ -1040,16 +1036,20 @@ void InnerWidget::openContextGif() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::copyContextText() {
|
void InnerWidget::copyContextText(FullMsgId itemId) {
|
||||||
auto item = App::contextItem();
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
if (!item || (item->getMedia() && item->getMedia()->type() == MediaTypeSticker)) {
|
if (const auto media = item->getMedia()) {
|
||||||
return;
|
if (media->type() == MediaTypeSticker) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setToClipboard(item->selectedText(FullSelection));
|
||||||
}
|
}
|
||||||
|
|
||||||
setToClipboard(item->selectedText(FullSelection));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::setToClipboard(const TextWithEntities &forClipboard, QClipboard::Mode mode) {
|
void InnerWidget::setToClipboard(
|
||||||
|
const TextWithEntities &forClipboard,
|
||||||
|
QClipboard::Mode mode) {
|
||||||
if (auto data = MimeDataFromTextWithEntities(forClipboard)) {
|
if (auto data = MimeDataFromTextWithEntities(forClipboard)) {
|
||||||
QApplication::clipboard()->setMimeData(data.release(), mode);
|
QApplication::clipboard()->setMimeData(data.release(), mode);
|
||||||
}
|
}
|
||||||
|
@ -1057,6 +1057,7 @@ void InnerWidget::setToClipboard(const TextWithEntities &forClipboard, QClipboar
|
||||||
|
|
||||||
void InnerWidget::suggestRestrictUser(not_null<UserData*> user) {
|
void InnerWidget::suggestRestrictUser(not_null<UserData*> user) {
|
||||||
Expects(_menu != nullptr);
|
Expects(_menu != nullptr);
|
||||||
|
|
||||||
if (!_channel->isMegagroup() || !_channel->canBanMembers() || _admins.empty()) {
|
if (!_channel->isMegagroup() || !_channel->canBanMembers() || _admins.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1065,8 +1066,8 @@ void InnerWidget::suggestRestrictUser(not_null<UserData*> user) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_menu->addAction(lang(lng_context_restrict_user), [this, user] {
|
_menu->addAction(lang(lng_context_restrict_user), [=] {
|
||||||
auto editRestrictions = [user, this](bool hasAdminRights, const MTPChannelBannedRights ¤tRights) {
|
auto editRestrictions = [=](bool hasAdminRights, const MTPChannelBannedRights ¤tRights) {
|
||||||
auto weak = QPointer<InnerWidget>(this);
|
auto weak = QPointer<InnerWidget>(this);
|
||||||
auto weakBox = std::make_shared<QPointer<EditRestrictedBox>>();
|
auto weakBox = std::make_shared<QPointer<EditRestrictedBox>>();
|
||||||
auto box = Box<EditRestrictedBox>(_channel, user, hasAdminRights, currentRights);
|
auto box = Box<EditRestrictedBox>(_channel, user, hasAdminRights, currentRights);
|
||||||
|
@ -1085,7 +1086,7 @@ void InnerWidget::suggestRestrictUser(not_null<UserData*> user) {
|
||||||
if (base::contains(_admins, user)) {
|
if (base::contains(_admins, user)) {
|
||||||
editRestrictions(true, MTP_channelBannedRights(MTP_flags(0), MTP_int(0)));
|
editRestrictions(true, MTP_channelBannedRights(MTP_flags(0), MTP_int(0)));
|
||||||
} else {
|
} else {
|
||||||
request(MTPchannels_GetParticipant(_channel->inputChannel, user->inputUser)).done([this, editRestrictions](const MTPchannels_ChannelParticipant &result) {
|
request(MTPchannels_GetParticipant(_channel->inputChannel, user->inputUser)).done([=](const MTPchannels_ChannelParticipant &result) {
|
||||||
Expects(result.type() == mtpc_channels_channelParticipant);
|
Expects(result.type() == mtpc_channels_channelParticipant);
|
||||||
|
|
||||||
auto &participant = result.c_channels_channelParticipant();
|
auto &participant = result.c_channels_channelParticipant();
|
||||||
|
@ -1162,8 +1163,8 @@ void InnerWidget::enterEventHook(QEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::leaveEventHook(QEvent *e) {
|
void InnerWidget::leaveEventHook(QEvent *e) {
|
||||||
if (auto item = App::hoveredItem()) {
|
if (const auto view = App::hoveredItem()) {
|
||||||
repaintItem(viewForItem(item));
|
repaintItem(view);
|
||||||
App::hoveredItem(nullptr);
|
App::hoveredItem(nullptr);
|
||||||
}
|
}
|
||||||
ClickHandler::clearActive();
|
ClickHandler::clearActive();
|
||||||
|
@ -1181,13 +1182,13 @@ void InnerWidget::mouseActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
||||||
|
|
||||||
ClickHandler::pressed();
|
ClickHandler::pressed();
|
||||||
if (App::pressedItem() != App::hoveredItem()) {
|
if (App::pressedItem() != App::hoveredItem()) {
|
||||||
repaintItem(viewForItem(App::pressedItem()));
|
repaintItem(App::pressedItem());
|
||||||
App::pressedItem(App::hoveredItem());
|
App::pressedItem(App::hoveredItem());
|
||||||
repaintItem(viewForItem(App::pressedItem()));
|
repaintItem(App::pressedItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
_mouseAction = MouseAction::None;
|
_mouseAction = MouseAction::None;
|
||||||
_mouseActionItem = viewForItem(App::mousedItem());
|
_mouseActionItem = App::mousedItem();
|
||||||
_dragStartPosition = mapPointToItem(
|
_dragStartPosition = mapPointToItem(
|
||||||
mapFromGlobal(screenPos),
|
mapFromGlobal(screenPos),
|
||||||
_mouseActionItem);
|
_mouseActionItem);
|
||||||
|
@ -1270,8 +1271,8 @@ void InnerWidget::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton but
|
||||||
if (_mouseAction == MouseAction::Dragging) {
|
if (_mouseAction == MouseAction::Dragging) {
|
||||||
activated = nullptr;
|
activated = nullptr;
|
||||||
}
|
}
|
||||||
if (App::pressedItem()) {
|
if (const auto view = App::pressedItem()) {
|
||||||
repaintItem(viewForItem(App::pressedItem()));
|
repaintItem(view);
|
||||||
App::pressedItem(nullptr);
|
App::pressedItem(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1318,23 +1319,25 @@ void InnerWidget::updateSelected() {
|
||||||
const auto view = (from != end) ? from->get() : nullptr;
|
const auto view = (from != end) ? from->get() : nullptr;
|
||||||
const auto item = view ? view->data().get() : nullptr;
|
const auto item = view ? view->data().get() : nullptr;
|
||||||
if (item) {
|
if (item) {
|
||||||
App::mousedItem(item);
|
App::mousedItem(view);
|
||||||
itemPoint = mapPointToItem(point, view);
|
itemPoint = mapPointToItem(point, view);
|
||||||
if (item->hasPoint(itemPoint)) {
|
if (item->hasPoint(itemPoint)) {
|
||||||
if (App::hoveredItem() != item) {
|
if (App::hoveredItem() != view) {
|
||||||
repaintItem(viewForItem(App::hoveredItem()));
|
repaintItem(App::hoveredItem());
|
||||||
App::hoveredItem(item);
|
App::hoveredItem(view);
|
||||||
repaintItem(view);
|
repaintItem(view);
|
||||||
}
|
}
|
||||||
} else if (App::hoveredItem()) {
|
} else if (const auto view = App::hoveredItem()) {
|
||||||
repaintItem(viewForItem(App::hoveredItem()));
|
repaintItem(view);
|
||||||
App::hoveredItem(nullptr);
|
App::hoveredItem(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryTextState dragState;
|
HistoryTextState dragState;
|
||||||
ClickHandlerHost *lnkhost = nullptr;
|
ClickHandlerHost *lnkhost = nullptr;
|
||||||
auto selectingText = (view == _mouseActionItem && item == App::hoveredItem() && _selectedItem);
|
auto selectingText = _selectedItem
|
||||||
|
&& (view == _mouseActionItem)
|
||||||
|
&& (view == App::hoveredItem());
|
||||||
if (view) {
|
if (view) {
|
||||||
if (view != _mouseActionItem || (itemPoint - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
|
if (view != _mouseActionItem || (itemPoint - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
|
||||||
if (_mouseAction == MouseAction::PrepareDrag) {
|
if (_mouseAction == MouseAction::PrepareDrag) {
|
||||||
|
@ -1422,13 +1425,9 @@ void InnerWidget::updateSelected() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Voice message seek support.
|
// Voice message seek support.
|
||||||
if (auto pressedItem = App::pressedLinkItem()) {
|
if (const auto pressedView = App::pressedLinkItem()) {
|
||||||
if (!pressedItem->detached()) {
|
const auto adjustedPoint = mapPointToItem(point, pressedView);
|
||||||
if (pressedItem->history() == _history) {
|
pressedView->data()->updatePressed(adjustedPoint);
|
||||||
auto adjustedPoint = mapPointToItem(point, viewForItem(pressedItem));
|
|
||||||
pressedItem->updatePressed(adjustedPoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (_mouseAction == MouseAction::Selecting) {
|
//if (_mouseAction == MouseAction::Selecting) {
|
||||||
|
|
|
@ -121,12 +121,12 @@ private:
|
||||||
void savePhotoToFile(PhotoData *photo);
|
void savePhotoToFile(PhotoData *photo);
|
||||||
void saveDocumentToFile(DocumentData *document);
|
void saveDocumentToFile(DocumentData *document);
|
||||||
void copyContextImage(PhotoData *photo);
|
void copyContextImage(PhotoData *photo);
|
||||||
void showStickerPackInfo();
|
void showStickerPackInfo(not_null<DocumentData*> document);
|
||||||
void copyContextUrl();
|
void copyContextUrl();
|
||||||
void cancelContextDownload();
|
void cancelContextDownload(not_null<DocumentData*> document);
|
||||||
void showContextInFolder();
|
void showContextInFolder(not_null<DocumentData*> document);
|
||||||
void openContextGif();
|
void openContextGif(FullMsgId itemId);
|
||||||
void copyContextText();
|
void copyContextText(FullMsgId itemId);
|
||||||
void copySelectedText();
|
void copySelectedText();
|
||||||
TextWithEntities getSelectedText() const;
|
TextWithEntities getSelectedText() const;
|
||||||
void setToClipboard(const TextWithEntities &forClipboard, QClipboard::Mode mode = QClipboard::Clipboard);
|
void setToClipboard(const TextWithEntities &forClipboard, QClipboard::Mode mode = QClipboard::Clipboard);
|
||||||
|
@ -228,8 +228,7 @@ private:
|
||||||
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;
|
||||||
|
|
||||||
// context menu
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
Ui::PopupMenu *_menu = nullptr;
|
|
||||||
|
|
||||||
QPoint _trippleClickPoint;
|
QPoint _trippleClickPoint;
|
||||||
base::Timer _trippleClickTimer;
|
base::Timer _trippleClickTimer;
|
||||||
|
|
|
@ -376,9 +376,9 @@ void ChannelHistory::getRangeDifference() {
|
||||||
for (auto blockIndex = 0, blocksCount = int(blocks.size()); blockIndex < blocksCount; ++blockIndex) {
|
for (auto blockIndex = 0, blocksCount = int(blocks.size()); blockIndex < blocksCount; ++blockIndex) {
|
||||||
const auto &block = blocks[blockIndex];
|
const auto &block = blocks[blockIndex];
|
||||||
for (auto itemIndex = 0, itemsCount = int(block->messages.size()); itemIndex < itemsCount; ++itemIndex) {
|
for (auto itemIndex = 0, itemsCount = int(block->messages.size()); itemIndex < itemsCount; ++itemIndex) {
|
||||||
const auto &message = block->messages[itemIndex];
|
const auto id = block->messages[itemIndex]->data()->id;
|
||||||
if (message->id() > 0) {
|
if (id > 0) {
|
||||||
fromId = message->id();
|
fromId = id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -389,9 +389,9 @@ void ChannelHistory::getRangeDifference() {
|
||||||
for (auto blockIndex = blocks.size(); blockIndex > 0;) {
|
for (auto blockIndex = blocks.size(); blockIndex > 0;) {
|
||||||
const auto &block = blocks[--blockIndex];
|
const auto &block = blocks[--blockIndex];
|
||||||
for (auto itemIndex = block->messages.size(); itemIndex > 0;) {
|
for (auto itemIndex = block->messages.size(); itemIndex > 0;) {
|
||||||
const auto &message = block->messages[--itemIndex];
|
const auto id = block->messages[--itemIndex]->data()->id;
|
||||||
if (message->id() > 0) {
|
if (id > 0) {
|
||||||
toId = message->id();
|
toId = id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,11 +420,16 @@ void ChannelHistory::getRangeDifferenceNext(int32 pts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) {
|
HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) {
|
||||||
if (_joinedMessage || !peer->asChannel()->amIn() || (peer->isMegagroup() && peer->asChannel()->mgInfo->joinedMessageFound)) {
|
if (_joinedMessage
|
||||||
|
|| !peer->asChannel()->amIn()
|
||||||
|
|| (peer->isMegagroup()
|
||||||
|
&& peer->asChannel()->mgInfo->joinedMessageFound)) {
|
||||||
return _joinedMessage;
|
return _joinedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto inviter = (peer->asChannel()->inviter > 0) ? App::userLoaded(peer->asChannel()->inviter) : nullptr;
|
const auto inviter = (peer->asChannel()->inviter > 0)
|
||||||
|
? App::userLoaded(peer->asChannel()->inviter)
|
||||||
|
: nullptr;
|
||||||
if (!inviter) return nullptr;
|
if (!inviter) return nullptr;
|
||||||
|
|
||||||
MTPDmessage::Flags flags = 0;
|
MTPDmessage::Flags flags = 0;
|
||||||
|
@ -491,7 +496,7 @@ void ChannelHistory::checkJoinedMessage(bool createUnread) {
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
if (loadedAtTop() && loadedAtBottom()) {
|
if (loadedAtTop() && loadedAtBottom()) {
|
||||||
if (insertJoinedMessage(createUnread)) {
|
if (insertJoinedMessage(createUnread)) {
|
||||||
if (!_joinedMessage->detached()) {
|
if (_joinedMessage->mainView()) {
|
||||||
setLastMessage(_joinedMessage);
|
setLastMessage(_joinedMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -508,7 +513,7 @@ void ChannelHistory::checkJoinedMessage(bool createUnread) {
|
||||||
if (!firstDate.isNull() && !lastDate.isNull() && (firstDate <= inviteDate || loadedAtTop()) && (lastDate > inviteDate || loadedAtBottom())) {
|
if (!firstDate.isNull() && !lastDate.isNull() && (firstDate <= inviteDate || loadedAtTop()) && (lastDate > inviteDate || loadedAtBottom())) {
|
||||||
bool willBeLastMsg = (inviteDate >= lastDate);
|
bool willBeLastMsg = (inviteDate >= lastDate);
|
||||||
if (insertJoinedMessage(createUnread && willBeLastMsg) && willBeLastMsg) {
|
if (insertJoinedMessage(createUnread && willBeLastMsg) && willBeLastMsg) {
|
||||||
if (!_joinedMessage->detached()) {
|
if (_joinedMessage->mainView()) {
|
||||||
setLastMessage(_joinedMessage);
|
setLastMessage(_joinedMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -545,8 +550,8 @@ void ChannelHistory::cleared(bool leaveItems) {
|
||||||
_joinedMessage = nullptr;
|
_joinedMessage = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelHistory::messageDetached(HistoryItem *msg) {
|
void ChannelHistory::messageDetached(not_null<HistoryItem*> message) {
|
||||||
if (_joinedMessage == msg) {
|
if (_joinedMessage == message) {
|
||||||
_joinedMessage = nullptr;
|
_joinedMessage = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,7 +570,9 @@ History *Histories::find(const PeerId &peerId) {
|
||||||
not_null<History*> Histories::findOrInsert(const PeerId &peerId) {
|
not_null<History*> Histories::findOrInsert(const PeerId &peerId) {
|
||||||
auto i = map.constFind(peerId);
|
auto i = map.constFind(peerId);
|
||||||
if (i == map.cend()) {
|
if (i == map.cend()) {
|
||||||
auto history = peerIsChannel(peerId) ? static_cast<History*>(new ChannelHistory(peerId)) : (new History(peerId));
|
auto history = peerIsChannel(peerId)
|
||||||
|
? static_cast<History*>(new ChannelHistory(peerId))
|
||||||
|
: (new History(peerId));
|
||||||
i = map.insert(peerId, history);
|
i = map.insert(peerId, history);
|
||||||
}
|
}
|
||||||
return i.value();
|
return i.value();
|
||||||
|
@ -574,7 +581,9 @@ not_null<History*> Histories::findOrInsert(const PeerId &peerId) {
|
||||||
not_null<History*> Histories::findOrInsert(const PeerId &peerId, int32 unreadCount, int32 maxInboxRead, int32 maxOutboxRead) {
|
not_null<History*> Histories::findOrInsert(const PeerId &peerId, int32 unreadCount, int32 maxInboxRead, int32 maxOutboxRead) {
|
||||||
auto i = map.constFind(peerId);
|
auto i = map.constFind(peerId);
|
||||||
if (i == map.cend()) {
|
if (i == map.cend()) {
|
||||||
auto history = peerIsChannel(peerId) ? static_cast<History*>(new ChannelHistory(peerId)) : (new History(peerId));
|
auto history = peerIsChannel(peerId)
|
||||||
|
? static_cast<History*>(new ChannelHistory(peerId))
|
||||||
|
: (new History(peerId));
|
||||||
i = map.insert(peerId, history);
|
i = map.insert(peerId, history);
|
||||||
history->setUnreadCount(unreadCount);
|
history->setUnreadCount(unreadCount);
|
||||||
history->inboxReadBefore = maxInboxRead + 1;
|
history->inboxReadBefore = maxInboxRead + 1;
|
||||||
|
@ -634,7 +643,7 @@ void Histories::step_typings(TimeMs ms, bool timer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Histories::remove(const PeerId &peer) {
|
void Histories::remove(const PeerId &peer) {
|
||||||
Map::iterator i = map.find(peer);
|
const auto i = map.find(peer);
|
||||||
if (i != map.cend()) {
|
if (i != map.cend()) {
|
||||||
typing.remove(i.value());
|
typing.remove(i.value());
|
||||||
delete i.value();
|
delete i.value();
|
||||||
|
@ -717,14 +726,17 @@ void Histories::checkSelfDestructItems() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem) {
|
HistoryItem *History::createItem(
|
||||||
|
const MTPMessage &msg,
|
||||||
|
bool applyServiceAction,
|
||||||
|
bool detachExistingItem) {
|
||||||
const auto msgId = idFromMessage(msg);
|
const auto msgId = idFromMessage(msg);
|
||||||
if (!msgId) return nullptr;
|
if (!msgId) return nullptr;
|
||||||
|
|
||||||
auto result = App::histItemById(channelId(), msgId);
|
auto result = App::histItemById(channelId(), msgId);
|
||||||
if (result) {
|
if (result) {
|
||||||
if (!result->detached() && detachExistingItem) {
|
if (detachExistingItem) {
|
||||||
result->detach();
|
result->removeMainView();
|
||||||
}
|
}
|
||||||
if (msg.type() == mtpc_message) {
|
if (msg.type() == mtpc_message) {
|
||||||
const auto media = msg.c_message().has_media()
|
const auto media = msg.c_message().has_media()
|
||||||
|
@ -1053,13 +1065,18 @@ HistoryItem *History::addNewMessage(const MTPMessage &msg, NewMessageType type)
|
||||||
return addNewToLastBlock(msg, type);
|
return addNewToLastBlock(msg, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *History::addNewToLastBlock(const MTPMessage &msg, NewMessageType type) {
|
HistoryItem *History::addNewToLastBlock(
|
||||||
|
const MTPMessage &msg,
|
||||||
|
NewMessageType type) {
|
||||||
Expects(type != NewMessageExisting);
|
Expects(type != NewMessageExisting);
|
||||||
|
|
||||||
const auto applyServiceAction = (type == NewMessageUnread);
|
const auto applyServiceAction = (type == NewMessageUnread);
|
||||||
const auto detachExistingItem = (type != NewMessageLast);
|
const auto detachExistingItem = (type != NewMessageLast);
|
||||||
const auto item = createItem(msg, applyServiceAction, detachExistingItem);
|
const auto item = createItem(
|
||||||
if (!item || !item->detached()) {
|
msg,
|
||||||
|
applyServiceAction,
|
||||||
|
detachExistingItem);
|
||||||
|
if (!item || item->mainView()) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
const auto result = addNewItem(item, (type == NewMessageUnread));
|
const auto result = addNewItem(item, (type == NewMessageUnread));
|
||||||
|
@ -1367,14 +1384,14 @@ HistoryBlock *History::prepareBlockForAddingItem() {
|
||||||
};
|
};
|
||||||
|
|
||||||
void History::addItemToBlock(not_null<HistoryItem*> item) {
|
void History::addItemToBlock(not_null<HistoryItem*> item) {
|
||||||
Expects(item->detached());
|
Expects(!item->mainView());
|
||||||
|
|
||||||
auto block = prepareBlockForAddingItem();
|
auto block = prepareBlockForAddingItem();
|
||||||
|
|
||||||
block->messages.push_back(std::make_unique<HistoryView::Message>(
|
block->messages.push_back(std::make_unique<HistoryView::Message>(
|
||||||
item,
|
item,
|
||||||
HistoryView::Context::History));
|
HistoryView::Context::History));
|
||||||
item->attachToBlock(block, block->messages.size() - 1);
|
block->messages.back()->attachToBlock(block, block->messages.size() - 1);
|
||||||
item->previousItemChanged();
|
item->previousItemChanged();
|
||||||
|
|
||||||
if (isBuildingFrontBlock() && _buildingFrontBlock->expectedItemsCount > 0) {
|
if (isBuildingFrontBlock() && _buildingFrontBlock->expectedItemsCount > 0) {
|
||||||
|
@ -1617,7 +1634,7 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice) {
|
||||||
|
|
||||||
void History::checkLastMsg() {
|
void History::checkLastMsg() {
|
||||||
if (lastMsg) {
|
if (lastMsg) {
|
||||||
if (!newLoaded && !lastMsg->detached()) {
|
if (!newLoaded && lastMsg->mainView()) {
|
||||||
newLoaded = true;
|
newLoaded = true;
|
||||||
checkAddAllToUnreadMentions();
|
checkAddAllToUnreadMentions();
|
||||||
}
|
}
|
||||||
|
@ -1840,7 +1857,7 @@ QDateTime History::adjustChatListDate() const {
|
||||||
void History::countScrollState(int top) {
|
void History::countScrollState(int top) {
|
||||||
countScrollTopItem(top);
|
countScrollTopItem(top);
|
||||||
if (scrollTopItem) {
|
if (scrollTopItem) {
|
||||||
scrollTopOffset = (top - scrollTopItem->data()->block()->y() - scrollTopItem->y());
|
scrollTopOffset = (top - scrollTopItem->block()->y() - scrollTopItem->y());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1854,8 +1871,8 @@ void History::countScrollTopItem(int top) {
|
||||||
auto blockIndex = 0;
|
auto blockIndex = 0;
|
||||||
auto itemTop = 0;
|
auto itemTop = 0;
|
||||||
if (scrollTopItem) {
|
if (scrollTopItem) {
|
||||||
itemIndex = scrollTopItem->data()->indexInBlock();
|
itemIndex = scrollTopItem->indexInBlock();
|
||||||
blockIndex = scrollTopItem->data()->block()->indexInHistory();
|
blockIndex = scrollTopItem->block()->indexInHistory();
|
||||||
itemTop = blocks[blockIndex]->y() + scrollTopItem->y();
|
itemTop = blocks[blockIndex]->y() + scrollTopItem->y();
|
||||||
}
|
}
|
||||||
if (itemTop > top) {
|
if (itemTop > top) {
|
||||||
|
@ -1915,7 +1932,9 @@ void History::getNextScrollTopItem(HistoryBlock *block, int32 i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void History::addUnreadBar() {
|
void History::addUnreadBar() {
|
||||||
if (unreadBar || !showFrom || showFrom->detached() || !unreadCount()) return;
|
if (unreadBar || !showFrom || !showFrom->mainView() || !unreadCount()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int32 count = unreadCount();
|
int32 count = unreadCount();
|
||||||
if (peer->migrateTo()) {
|
if (peer->migrateTo()) {
|
||||||
|
@ -1944,14 +1963,16 @@ not_null<HistoryItem*> History::addNewInTheMiddle(
|
||||||
|
|
||||||
const auto &block = blocks[blockIndex];
|
const auto &block = blocks[blockIndex];
|
||||||
|
|
||||||
block->messages.insert(
|
const auto it = block->messages.insert(
|
||||||
block->messages.begin() + itemIndex,
|
block->messages.begin() + itemIndex,
|
||||||
std::make_unique<HistoryView::Message>(newItem, HistoryView::Context::History));
|
std::make_unique<HistoryView::Message>(
|
||||||
newItem->attachToBlock(block.get(), itemIndex);
|
newItem,
|
||||||
|
HistoryView::Context::History));
|
||||||
|
(*it)->attachToBlock(block.get(), itemIndex);
|
||||||
newItem->previousItemChanged();
|
newItem->previousItemChanged();
|
||||||
if (itemIndex + 1 < block->messages.size()) {
|
if (itemIndex + 1 < block->messages.size()) {
|
||||||
for (auto i = itemIndex + 1, l = int(block->messages.size()); i != l; ++i) {
|
for (auto i = itemIndex + 1, l = int(block->messages.size()); i != l; ++i) {
|
||||||
block->messages[i]->data()->setIndexInBlock(i);
|
block->messages[i]->setIndexInBlock(i);
|
||||||
}
|
}
|
||||||
block->messages[itemIndex + 1]->data()->previousItemChanged();
|
block->messages[itemIndex + 1]->data()->previousItemChanged();
|
||||||
} else if (blockIndex + 1 < blocks.size() && !blocks[blockIndex + 1]->messages.empty()) {
|
} else if (blockIndex + 1 < blocks.size() && !blocks[blockIndex + 1]->messages.empty()) {
|
||||||
|
@ -1969,12 +1990,12 @@ not_null<HistoryItem*> History::addNewInTheMiddle(
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *History::findNextItem(not_null<HistoryItem*> item) const {
|
HistoryItem *History::findNextItem(not_null<HistoryItem*> item) const {
|
||||||
Expects(!item->detached());
|
Expects(item->mainView());
|
||||||
|
|
||||||
const auto nextBlockIndex = item->block()->indexInHistory() + 1;
|
const auto nextBlockIndex = item->mainView()->block()->indexInHistory() + 1;
|
||||||
const auto nextItemIndex = item->indexInBlock() + 1;
|
const auto nextItemIndex = item->mainView()->indexInBlock() + 1;
|
||||||
if (nextItemIndex < int(item->block()->messages.size())) {
|
if (nextItemIndex < int(item->mainView()->block()->messages.size())) {
|
||||||
return item->block()->messages[nextItemIndex]->data();
|
return item->mainView()->block()->messages[nextItemIndex]->data();
|
||||||
} else if (nextBlockIndex < int(blocks.size())) {
|
} else if (nextBlockIndex < int(blocks.size())) {
|
||||||
return blocks[nextBlockIndex]->messages.front()->data();
|
return blocks[nextBlockIndex]->messages.front()->data();
|
||||||
}
|
}
|
||||||
|
@ -1982,12 +2003,12 @@ HistoryItem *History::findNextItem(not_null<HistoryItem*> item) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *History::findPreviousItem(not_null<HistoryItem*> item) const {
|
HistoryItem *History::findPreviousItem(not_null<HistoryItem*> item) const {
|
||||||
Expects(!item->detached());
|
Expects(item->mainView());
|
||||||
|
|
||||||
const auto blockIndex = item->block()->indexInHistory();
|
const auto blockIndex = item->mainView()->block()->indexInHistory();
|
||||||
const auto itemIndex = item->indexInBlock();
|
const auto itemIndex = item->mainView()->indexInBlock();
|
||||||
if (itemIndex > 0) {
|
if (itemIndex > 0) {
|
||||||
return item->block()->messages[itemIndex - 1]->data();
|
return item->mainView()->block()->messages[itemIndex - 1]->data();
|
||||||
} else if (blockIndex > 0) {
|
} else if (blockIndex > 0) {
|
||||||
return blocks[blockIndex - 1]->messages.back()->data();
|
return blocks[blockIndex - 1]->messages.back()->data();
|
||||||
}
|
}
|
||||||
|
@ -2021,7 +2042,7 @@ not_null<HistoryItem*> History::findGroupLast(
|
||||||
void History::recountGroupingAround(not_null<HistoryItem*> item) {
|
void History::recountGroupingAround(not_null<HistoryItem*> item) {
|
||||||
Expects(item->history() == this);
|
Expects(item->history() == this);
|
||||||
|
|
||||||
if (!item->detached() && item->groupId()) {
|
if (item->mainView() && item->groupId()) {
|
||||||
const auto [groupFrom, groupTill] = recountGroupingFromTill(item);
|
const auto [groupFrom, groupTill] = recountGroupingFromTill(item);
|
||||||
recountGrouping(groupFrom, groupTill);
|
recountGrouping(groupFrom, groupTill);
|
||||||
}
|
}
|
||||||
|
@ -2084,8 +2105,8 @@ auto History::recountGroupingFromTill(not_null<HistoryItem*> item)
|
||||||
void History::recountGrouping(
|
void History::recountGrouping(
|
||||||
not_null<HistoryItem*> from,
|
not_null<HistoryItem*> from,
|
||||||
not_null<HistoryItem*> till) {
|
not_null<HistoryItem*> till) {
|
||||||
Expects(!from->detached());
|
Expects(from->mainView());
|
||||||
Expects(!till->detached());
|
Expects(till->mainView());
|
||||||
|
|
||||||
from->validateGroupId();
|
from->validateGroupId();
|
||||||
auto others = std::vector<not_null<HistoryItem*>>();
|
auto others = std::vector<not_null<HistoryItem*>>();
|
||||||
|
@ -2186,7 +2207,7 @@ bool History::isReadyFor(MsgId msgId) {
|
||||||
return loadedAtBottom();
|
return loadedAtBottom();
|
||||||
}
|
}
|
||||||
HistoryItem *item = App::histItemById(channelId(), msgId);
|
HistoryItem *item = App::histItemById(channelId(), msgId);
|
||||||
return item && (item->history() == this) && !item->detached();
|
return item && (item->history() == this) && item->mainView();
|
||||||
}
|
}
|
||||||
|
|
||||||
void History::getReadyFor(MsgId msgId) {
|
void History::getReadyFor(MsgId msgId) {
|
||||||
|
@ -2539,15 +2560,16 @@ void HistoryBlock::clear(bool leaveItems) {
|
||||||
|
|
||||||
if (leaveItems) {
|
if (leaveItems) {
|
||||||
for (const auto &message : list) {
|
for (const auto &message : list) {
|
||||||
message->data()->detachFast();
|
message->data()->clearMainView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #TODO feeds delete all items in history
|
// #TODO feeds delete all items in history
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryBlock::removeItem(not_null<HistoryItem*> item) {
|
void HistoryBlock::remove(not_null<Message*> view) {
|
||||||
Expects(item->block() == this);
|
Expects(view->block() == this);
|
||||||
|
|
||||||
|
const auto item = view->data();
|
||||||
auto [groupFrom, groupTill] = _history->recountGroupingFromTill(item);
|
auto [groupFrom, groupTill] = _history->recountGroupingFromTill(item);
|
||||||
const auto groupHistory = _history;
|
const auto groupHistory = _history;
|
||||||
const auto needGroupRecount = (groupFrom != groupTill);
|
const auto needGroupRecount = (groupFrom != groupTill);
|
||||||
|
@ -2561,7 +2583,7 @@ void HistoryBlock::removeItem(not_null<HistoryItem*> item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto blockIndex = indexInHistory();
|
auto blockIndex = indexInHistory();
|
||||||
auto itemIndex = item->indexInBlock();
|
auto itemIndex = view->indexInBlock();
|
||||||
if (_history->showFrom == item) {
|
if (_history->showFrom == item) {
|
||||||
_history->getNextShowFrom(this, itemIndex);
|
_history->getNextShowFrom(this, itemIndex);
|
||||||
}
|
}
|
||||||
|
@ -2575,10 +2597,10 @@ void HistoryBlock::removeItem(not_null<HistoryItem*> item) {
|
||||||
_history->getNextScrollTopItem(this, itemIndex);
|
_history->getNextScrollTopItem(this, itemIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
item->detachFast();
|
item->clearMainView();
|
||||||
messages.erase(messages.begin() + itemIndex);
|
messages.erase(messages.begin() + itemIndex);
|
||||||
for (auto i = itemIndex, l = int(messages.size()); i < l; ++i) {
|
for (auto i = itemIndex, l = int(messages.size()); i < l; ++i) {
|
||||||
messages[i]->data()->setIndexInBlock(i);
|
messages[i]->setIndexInBlock(i);
|
||||||
}
|
}
|
||||||
if (messages.empty()) {
|
if (messages.empty()) {
|
||||||
// Deletes this.
|
// Deletes this.
|
||||||
|
|
|
@ -550,7 +550,7 @@ class ChannelHistory : public History {
|
||||||
public:
|
public:
|
||||||
using History::History;
|
using History::History;
|
||||||
|
|
||||||
void messageDetached(HistoryItem *msg);
|
void messageDetached(not_null<HistoryItem*> message);
|
||||||
|
|
||||||
void getRangeDifference();
|
void getRangeDifference();
|
||||||
void getRangeDifferenceNext(int32 pts);
|
void getRangeDifferenceNext(int32 pts);
|
||||||
|
@ -579,15 +579,17 @@ private:
|
||||||
|
|
||||||
class HistoryBlock {
|
class HistoryBlock {
|
||||||
public:
|
public:
|
||||||
|
using Message = HistoryView::Message;
|
||||||
|
|
||||||
HistoryBlock(not_null<History*> history);
|
HistoryBlock(not_null<History*> history);
|
||||||
HistoryBlock(const HistoryBlock &) = delete;
|
HistoryBlock(const HistoryBlock &) = delete;
|
||||||
HistoryBlock &operator=(const HistoryBlock &) = delete;
|
HistoryBlock &operator=(const HistoryBlock &) = delete;
|
||||||
~HistoryBlock();
|
~HistoryBlock();
|
||||||
|
|
||||||
std::vector<std::unique_ptr<HistoryView::Message>> messages;
|
std::vector<std::unique_ptr<Message>> messages;
|
||||||
|
|
||||||
void clear(bool leaveItems = false);
|
void clear(bool leaveItems = false);
|
||||||
void removeItem(not_null<HistoryItem*> item);
|
void remove(not_null<Message*> view);
|
||||||
|
|
||||||
int resizeGetHeight(int newWidth, bool resizeAllItems);
|
int resizeGetHeight(int newWidth, bool resizeAllItems);
|
||||||
int y() const {
|
int y() const {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,6 +28,8 @@ class HistoryInner
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Message = HistoryView::Message;
|
||||||
|
|
||||||
HistoryInner(
|
HistoryInner(
|
||||||
not_null<HistoryWidget*> historyWidget,
|
not_null<HistoryWidget*> historyWidget,
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller,
|
||||||
|
@ -40,12 +42,12 @@ public:
|
||||||
TextWithEntities getSelectedText() const;
|
TextWithEntities getSelectedText() const;
|
||||||
|
|
||||||
void touchScrollUpdated(const QPoint &screenPos);
|
void touchScrollUpdated(const QPoint &screenPos);
|
||||||
QPoint mapPointToItem(QPoint p, HistoryItem *item);
|
|
||||||
|
|
||||||
void recountHistoryGeometry();
|
void recountHistoryGeometry();
|
||||||
void updateSize();
|
void updateSize();
|
||||||
|
|
||||||
void repaintItem(const HistoryItem *item);
|
void repaintItem(const HistoryItem *item);
|
||||||
|
void repaintItem(const Message *view);
|
||||||
|
|
||||||
bool canCopySelected() const;
|
bool canCopySelected() const;
|
||||||
bool canDeleteSelected() const;
|
bool canDeleteSelected() const;
|
||||||
|
@ -68,7 +70,10 @@ public:
|
||||||
int migratedTop() const;
|
int migratedTop() const;
|
||||||
int historyTop() const;
|
int historyTop() const;
|
||||||
int historyDrawTop() const;
|
int historyDrawTop() const;
|
||||||
int itemTop(const HistoryItem *item) const; // -1 if should not be visible, -2 if bad history()
|
|
||||||
|
// -1 if should not be visible, -2 if bad history()
|
||||||
|
int itemTop(const HistoryItem *item) const;
|
||||||
|
int itemTop(const Message *view) const;
|
||||||
|
|
||||||
void notifyIsBotChanged();
|
void notifyIsBotChanged();
|
||||||
void notifyMigrateUpdated();
|
void notifyMigrateUpdated();
|
||||||
|
@ -104,14 +109,8 @@ public slots:
|
||||||
void onParentGeometryChanged();
|
void onParentGeometryChanged();
|
||||||
|
|
||||||
void copyContextUrl();
|
void copyContextUrl();
|
||||||
void cancelContextDownload();
|
|
||||||
void showContextInFolder();
|
|
||||||
void saveContextGif();
|
|
||||||
void openContextGif();
|
|
||||||
void copyContextText();
|
|
||||||
void copySelectedText();
|
void copySelectedText();
|
||||||
|
|
||||||
void onMenuDestroy(QObject *obj);
|
|
||||||
void onTouchSelect();
|
void onTouchSelect();
|
||||||
void onTouchScrollTimer();
|
void onTouchScrollTimer();
|
||||||
|
|
||||||
|
@ -122,7 +121,6 @@ private slots:
|
||||||
private:
|
private:
|
||||||
class BotAbout;
|
class BotAbout;
|
||||||
using SelectedItems = std::map<HistoryItem*, TextSelection, std::less<>>;
|
using SelectedItems = std::map<HistoryItem*, TextSelection, std::less<>>;
|
||||||
using Message = HistoryView::Message;
|
|
||||||
enum class MouseAction {
|
enum class MouseAction {
|
||||||
None,
|
None,
|
||||||
PrepareDrag,
|
PrepareDrag,
|
||||||
|
@ -135,166 +133,6 @@ private:
|
||||||
Deselect,
|
Deselect,
|
||||||
Invert,
|
Invert,
|
||||||
};
|
};
|
||||||
|
|
||||||
void mouseActionStart(const QPoint &screenPos, Qt::MouseButton button);
|
|
||||||
void mouseActionUpdate(const QPoint &screenPos);
|
|
||||||
void mouseActionFinish(const QPoint &screenPos, Qt::MouseButton button);
|
|
||||||
void mouseActionCancel();
|
|
||||||
void performDrag();
|
|
||||||
|
|
||||||
void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false);
|
|
||||||
|
|
||||||
void itemRemoved(not_null<const HistoryItem*> item);
|
|
||||||
void savePhotoToFile(PhotoData *photo);
|
|
||||||
void saveDocumentToFile(DocumentData *document);
|
|
||||||
void copyContextImage(PhotoData *photo);
|
|
||||||
void showStickerPackInfo(DocumentData *document);
|
|
||||||
void toggleFavedSticker(DocumentData *document);
|
|
||||||
|
|
||||||
void touchResetSpeed();
|
|
||||||
void touchUpdateSpeed();
|
|
||||||
void touchDeaccelerate(int32 elapsed);
|
|
||||||
|
|
||||||
void adjustCurrent(int32 y) const;
|
|
||||||
void adjustCurrent(int32 y, History *history) const;
|
|
||||||
HistoryItem *prevItem(HistoryItem *item);
|
|
||||||
HistoryItem *nextItem(HistoryItem *item);
|
|
||||||
void updateDragSelection(HistoryItem *dragSelFrom, HistoryItem *dragSelTo, bool dragSelecting);
|
|
||||||
TextSelection itemRenderSelection(
|
|
||||||
not_null<Message*> view,
|
|
||||||
int selfromy,
|
|
||||||
int seltoy) const;
|
|
||||||
TextSelection computeRenderSelection(
|
|
||||||
not_null<const SelectedItems*> selected,
|
|
||||||
not_null<HistoryItem*> item) const;
|
|
||||||
|
|
||||||
void setToClipboard(const TextWithEntities &forClipboard, QClipboard::Mode mode = QClipboard::Clipboard);
|
|
||||||
|
|
||||||
void toggleScrollDateShown();
|
|
||||||
void repaintScrollDateCallback();
|
|
||||||
bool displayScrollDate() const;
|
|
||||||
void scrollDateHide();
|
|
||||||
void keepScrollDateForNow();
|
|
||||||
|
|
||||||
not_null<Window::Controller*> _controller;
|
|
||||||
|
|
||||||
PeerData *_peer = nullptr;
|
|
||||||
History *_migrated = nullptr;
|
|
||||||
History *_history = nullptr;
|
|
||||||
int _historyPaddingTop = 0;
|
|
||||||
|
|
||||||
// with migrated history we perhaps do not need to display first _history message
|
|
||||||
// (if last _migrated message and first _history message are both isGroupMigrate)
|
|
||||||
// or at least we don't need to display first _history date (just skip it by height)
|
|
||||||
int _historySkipHeight = 0;
|
|
||||||
|
|
||||||
std::unique_ptr<BotAbout> _botAbout;
|
|
||||||
|
|
||||||
HistoryWidget *_widget = nullptr;
|
|
||||||
Ui::ScrollArea *_scroll = nullptr;
|
|
||||||
mutable History *_curHistory = nullptr;
|
|
||||||
mutable int _curBlock = 0;
|
|
||||||
mutable int _curItem = 0;
|
|
||||||
|
|
||||||
bool _firstLoading = false;
|
|
||||||
|
|
||||||
style::cursor _cursor = style::cur_default;
|
|
||||||
SelectedItems _selected;
|
|
||||||
|
|
||||||
void applyDragSelection();
|
|
||||||
void applyDragSelection(not_null<SelectedItems*> toItems) const;
|
|
||||||
void addSelectionRange(
|
|
||||||
not_null<SelectedItems*> toItems,
|
|
||||||
not_null<History*> history,
|
|
||||||
int fromblock,
|
|
||||||
int fromitem,
|
|
||||||
int toblock,
|
|
||||||
int toitem) const;
|
|
||||||
bool isSelected(
|
|
||||||
not_null<SelectedItems*> toItems,
|
|
||||||
not_null<HistoryItem*> item) const;
|
|
||||||
bool isSelectedAsGroup(
|
|
||||||
not_null<SelectedItems*> toItems,
|
|
||||||
not_null<HistoryItem*> item) const;
|
|
||||||
bool goodForSelection(
|
|
||||||
not_null<SelectedItems*> toItems,
|
|
||||||
not_null<HistoryItem*> item,
|
|
||||||
int &totalCount) const;
|
|
||||||
void addToSelection(
|
|
||||||
not_null<SelectedItems*> toItems,
|
|
||||||
not_null<HistoryItem*> item) const;
|
|
||||||
void removeFromSelection(
|
|
||||||
not_null<SelectedItems*> toItems,
|
|
||||||
not_null<HistoryItem*> item) const;
|
|
||||||
void changeSelection(
|
|
||||||
not_null<SelectedItems*> toItems,
|
|
||||||
not_null<HistoryItem*> item,
|
|
||||||
SelectAction action) const;
|
|
||||||
void changeSelectionAsGroup(
|
|
||||||
not_null<SelectedItems*> toItems,
|
|
||||||
not_null<HistoryItem*> item,
|
|
||||||
SelectAction action) const;
|
|
||||||
void forwardItem(not_null<HistoryItem*> item);
|
|
||||||
void forwardAsGroup(not_null<HistoryItem*> item);
|
|
||||||
void deleteItem(not_null<HistoryItem*> item);
|
|
||||||
void deleteAsGroup(not_null<HistoryItem*> item);
|
|
||||||
|
|
||||||
// Does any of the shown histories has this flag set.
|
|
||||||
bool hasPendingResizedItems() const {
|
|
||||||
return (_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems());
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseAction _mouseAction = MouseAction::None;
|
|
||||||
TextSelectType _mouseSelectType = TextSelectType::Letters;
|
|
||||||
QPoint _dragStartPosition;
|
|
||||||
QPoint _mousePosition;
|
|
||||||
HistoryItem *_mouseActionItem = nullptr;
|
|
||||||
HistoryItem *_dragStateItem = nullptr;
|
|
||||||
HistoryCursorState _mouseCursorState = HistoryDefaultCursorState;
|
|
||||||
uint16 _mouseTextSymbol = 0;
|
|
||||||
bool _pressWasInactive = false;
|
|
||||||
|
|
||||||
QPoint _trippleClickPoint;
|
|
||||||
QTimer _trippleClickTimer;
|
|
||||||
|
|
||||||
ClickHandlerPtr _contextMenuLink;
|
|
||||||
|
|
||||||
HistoryItem *_dragSelFrom = nullptr;
|
|
||||||
HistoryItem *_dragSelTo = nullptr;
|
|
||||||
bool _dragSelecting = false;
|
|
||||||
bool _wasSelectedText = false; // was some text selected in current drag action
|
|
||||||
|
|
||||||
// scroll by touch support (at least Windows Surface tablets)
|
|
||||||
bool _touchScroll = false;
|
|
||||||
bool _touchSelect = false;
|
|
||||||
bool _touchInProgress = false;
|
|
||||||
QPoint _touchStart, _touchPrevPos, _touchPos;
|
|
||||||
QTimer _touchSelectTimer;
|
|
||||||
|
|
||||||
Ui::TouchScrollState _touchScrollState = Ui::TouchScrollState::Manual;
|
|
||||||
bool _touchPrevPosValid = false;
|
|
||||||
bool _touchWaitingAcceleration = false;
|
|
||||||
QPoint _touchSpeed;
|
|
||||||
TimeMs _touchSpeedTime = 0;
|
|
||||||
TimeMs _touchAccelerationTime = 0;
|
|
||||||
TimeMs _touchTime = 0;
|
|
||||||
QTimer _touchScrollTimer;
|
|
||||||
|
|
||||||
// context menu
|
|
||||||
Ui::PopupMenu *_menu = nullptr;
|
|
||||||
|
|
||||||
// save visible area coords for painting / pressing userpics
|
|
||||||
int _visibleAreaTop = 0;
|
|
||||||
int _visibleAreaBottom = 0;
|
|
||||||
|
|
||||||
bool _scrollDateShown = false;
|
|
||||||
Animation _scrollDateOpacity;
|
|
||||||
SingleQueuedInvokation _scrollDateCheck;
|
|
||||||
SingleTimer _scrollDateHideTimer;
|
|
||||||
Message *_scrollDateLastItem = nullptr;
|
|
||||||
int _scrollDateLastItemTop = 0;
|
|
||||||
ClickHandlerPtr _scrollDateLink;
|
|
||||||
|
|
||||||
enum class EnumItemsDirection {
|
enum class EnumItemsDirection {
|
||||||
TopToBottom,
|
TopToBottom,
|
||||||
BottomToTop,
|
BottomToTop,
|
||||||
|
@ -335,4 +173,171 @@ private:
|
||||||
template <typename Method>
|
template <typename Method>
|
||||||
void enumerateDates(Method method);
|
void enumerateDates(Method method);
|
||||||
|
|
||||||
|
void mouseActionStart(const QPoint &screenPos, Qt::MouseButton button);
|
||||||
|
void mouseActionUpdate(const QPoint &screenPos);
|
||||||
|
void mouseActionFinish(const QPoint &screenPos, Qt::MouseButton button);
|
||||||
|
void mouseActionCancel();
|
||||||
|
void performDrag();
|
||||||
|
|
||||||
|
QPoint mapPointToItem(QPoint p, const Message *view);
|
||||||
|
QPoint mapPointToItem(QPoint p, const HistoryItem *item);
|
||||||
|
|
||||||
|
void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false);
|
||||||
|
void cancelContextDownload(not_null<DocumentData*> document);
|
||||||
|
void openContextGif(FullMsgId itemId);
|
||||||
|
void saveContextGif(FullMsgId itemId);
|
||||||
|
void copyContextText(FullMsgId itemId);
|
||||||
|
void showContextInFolder(not_null<DocumentData*> document);
|
||||||
|
void savePhotoToFile(not_null<PhotoData*> photo);
|
||||||
|
void saveDocumentToFile(not_null<DocumentData*> document);
|
||||||
|
void copyContextImage(not_null<PhotoData*> photo);
|
||||||
|
void showStickerPackInfo(not_null<DocumentData*> document);
|
||||||
|
void toggleFavedSticker(not_null<DocumentData*> document);
|
||||||
|
|
||||||
|
void itemRemoved(not_null<const HistoryItem*> item);
|
||||||
|
|
||||||
|
void touchResetSpeed();
|
||||||
|
void touchUpdateSpeed();
|
||||||
|
void touchDeaccelerate(int32 elapsed);
|
||||||
|
|
||||||
|
void adjustCurrent(int32 y) const;
|
||||||
|
void adjustCurrent(int32 y, History *history) const;
|
||||||
|
Message *prevItem(Message *item);
|
||||||
|
Message *nextItem(Message *item);
|
||||||
|
void updateDragSelection(Message *dragSelFrom, Message *dragSelTo, bool dragSelecting);
|
||||||
|
TextSelection itemRenderSelection(
|
||||||
|
not_null<Message*> view,
|
||||||
|
int selfromy,
|
||||||
|
int seltoy) const;
|
||||||
|
TextSelection computeRenderSelection(
|
||||||
|
not_null<const SelectedItems*> selected,
|
||||||
|
not_null<HistoryItem*> item) const;
|
||||||
|
|
||||||
|
void setToClipboard(const TextWithEntities &forClipboard, QClipboard::Mode mode = QClipboard::Clipboard);
|
||||||
|
|
||||||
|
void toggleScrollDateShown();
|
||||||
|
void repaintScrollDateCallback();
|
||||||
|
bool displayScrollDate() const;
|
||||||
|
void scrollDateHide();
|
||||||
|
void keepScrollDateForNow();
|
||||||
|
|
||||||
|
void applyDragSelection();
|
||||||
|
void applyDragSelection(not_null<SelectedItems*> toItems) const;
|
||||||
|
void addSelectionRange(
|
||||||
|
not_null<SelectedItems*> toItems,
|
||||||
|
not_null<History*> history,
|
||||||
|
int fromblock,
|
||||||
|
int fromitem,
|
||||||
|
int toblock,
|
||||||
|
int toitem) const;
|
||||||
|
bool isSelected(
|
||||||
|
not_null<SelectedItems*> toItems,
|
||||||
|
not_null<HistoryItem*> item) const;
|
||||||
|
bool isSelectedAsGroup(
|
||||||
|
not_null<SelectedItems*> toItems,
|
||||||
|
not_null<HistoryItem*> item) const;
|
||||||
|
bool goodForSelection(
|
||||||
|
not_null<SelectedItems*> toItems,
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
int &totalCount) const;
|
||||||
|
void addToSelection(
|
||||||
|
not_null<SelectedItems*> toItems,
|
||||||
|
not_null<HistoryItem*> item) const;
|
||||||
|
void removeFromSelection(
|
||||||
|
not_null<SelectedItems*> toItems,
|
||||||
|
not_null<HistoryItem*> item) const;
|
||||||
|
void changeSelection(
|
||||||
|
not_null<SelectedItems*> toItems,
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
SelectAction action) const;
|
||||||
|
void changeSelectionAsGroup(
|
||||||
|
not_null<SelectedItems*> toItems,
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
SelectAction action) const;
|
||||||
|
void forwardItem(FullMsgId itemId);
|
||||||
|
void forwardAsGroup(FullMsgId itemId);
|
||||||
|
void deleteItem(not_null<HistoryItem*> item);
|
||||||
|
void deleteItem(FullMsgId itemId);
|
||||||
|
void deleteAsGroup(FullMsgId itemId);
|
||||||
|
|
||||||
|
// Does any of the shown histories has this flag set.
|
||||||
|
bool hasPendingResizedItems() const {
|
||||||
|
return (_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems());
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<Window::Controller*> _controller;
|
||||||
|
|
||||||
|
not_null<PeerData*> _peer;
|
||||||
|
not_null<History*> _history;
|
||||||
|
History *_migrated = nullptr;
|
||||||
|
int _historyPaddingTop = 0;
|
||||||
|
|
||||||
|
// with migrated history we perhaps do not need to display first _history message
|
||||||
|
// (if last _migrated message and first _history message are both isGroupMigrate)
|
||||||
|
// or at least we don't need to display first _history date (just skip it by height)
|
||||||
|
int _historySkipHeight = 0;
|
||||||
|
|
||||||
|
std::unique_ptr<BotAbout> _botAbout;
|
||||||
|
|
||||||
|
HistoryWidget *_widget = nullptr;
|
||||||
|
Ui::ScrollArea *_scroll = nullptr;
|
||||||
|
mutable History *_curHistory = nullptr;
|
||||||
|
mutable int _curBlock = 0;
|
||||||
|
mutable int _curItem = 0;
|
||||||
|
|
||||||
|
bool _firstLoading = false;
|
||||||
|
|
||||||
|
style::cursor _cursor = style::cur_default;
|
||||||
|
SelectedItems _selected;
|
||||||
|
|
||||||
|
MouseAction _mouseAction = MouseAction::None;
|
||||||
|
TextSelectType _mouseSelectType = TextSelectType::Letters;
|
||||||
|
QPoint _dragStartPosition;
|
||||||
|
QPoint _mousePosition;
|
||||||
|
HistoryItem *_mouseActionItem = nullptr;
|
||||||
|
HistoryItem *_dragStateItem = nullptr;
|
||||||
|
HistoryCursorState _mouseCursorState = HistoryDefaultCursorState;
|
||||||
|
uint16 _mouseTextSymbol = 0;
|
||||||
|
bool _pressWasInactive = false;
|
||||||
|
|
||||||
|
QPoint _trippleClickPoint;
|
||||||
|
QTimer _trippleClickTimer;
|
||||||
|
|
||||||
|
ClickHandlerPtr _contextMenuLink;
|
||||||
|
|
||||||
|
Message *_dragSelFrom = nullptr;
|
||||||
|
Message *_dragSelTo = nullptr;
|
||||||
|
bool _dragSelecting = false;
|
||||||
|
bool _wasSelectedText = false; // was some text selected in current drag action
|
||||||
|
|
||||||
|
// scroll by touch support (at least Windows Surface tablets)
|
||||||
|
bool _touchScroll = false;
|
||||||
|
bool _touchSelect = false;
|
||||||
|
bool _touchInProgress = false;
|
||||||
|
QPoint _touchStart, _touchPrevPos, _touchPos;
|
||||||
|
QTimer _touchSelectTimer;
|
||||||
|
|
||||||
|
Ui::TouchScrollState _touchScrollState = Ui::TouchScrollState::Manual;
|
||||||
|
bool _touchPrevPosValid = false;
|
||||||
|
bool _touchWaitingAcceleration = false;
|
||||||
|
QPoint _touchSpeed;
|
||||||
|
TimeMs _touchSpeedTime = 0;
|
||||||
|
TimeMs _touchAccelerationTime = 0;
|
||||||
|
TimeMs _touchTime = 0;
|
||||||
|
QTimer _touchScrollTimer;
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
|
||||||
|
// save visible area coords for painting / pressing userpics
|
||||||
|
int _visibleAreaTop = 0;
|
||||||
|
int _visibleAreaBottom = 0;
|
||||||
|
|
||||||
|
bool _scrollDateShown = false;
|
||||||
|
Animation _scrollDateOpacity;
|
||||||
|
SingleQueuedInvokation _scrollDateCheck;
|
||||||
|
SingleTimer _scrollDateHideTimer;
|
||||||
|
Message *_scrollDateLastItem = nullptr;
|
||||||
|
int _scrollDateLastItemTop = 0;
|
||||||
|
ClickHandlerPtr _scrollDateLink;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -259,7 +259,8 @@ void HistoryItem::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool activ
|
||||||
markup->inlineKeyboard->clickHandlerActiveChanged(p, active);
|
markup->inlineKeyboard->clickHandlerActiveChanged(p, active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
App::hoveredLinkItem(active ? this : nullptr);
|
// #TODO hoveredLinkItem
|
||||||
|
// App::hoveredLinkItem(active ? this : nullptr);
|
||||||
Auth().data().requestItemRepaint(this);
|
Auth().data().requestItemRepaint(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +270,8 @@ void HistoryItem::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pres
|
||||||
markup->inlineKeyboard->clickHandlerPressedChanged(p, pressed);
|
markup->inlineKeyboard->clickHandlerPressedChanged(p, pressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
App::pressedLinkItem(pressed ? this : nullptr);
|
// #TODO hoveredLinkItem
|
||||||
|
// App::pressedLinkItem(pressed ? this : nullptr);
|
||||||
Auth().data().requestItemRepaint(this);
|
Auth().data().requestItemRepaint(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +293,7 @@ UserData *HistoryItem::viaBot() const {
|
||||||
void HistoryItem::destroy() {
|
void HistoryItem::destroy() {
|
||||||
const auto history = this->history();
|
const auto history = this->history();
|
||||||
if (isLogEntry()) {
|
if (isLogEntry()) {
|
||||||
Assert(detached());
|
Assert(!mainView());
|
||||||
} else {
|
} else {
|
||||||
// All this must be done for all items manually in History::clear(false)!
|
// All this must be done for all items manually in History::clear(false)!
|
||||||
eraseFromUnreadMentions();
|
eraseFromUnreadMentions();
|
||||||
|
@ -309,7 +311,7 @@ void HistoryItem::destroy() {
|
||||||
const auto wasAtBottom = history->loadedAtBottom();
|
const auto wasAtBottom = history->loadedAtBottom();
|
||||||
history->removeNotification(this);
|
history->removeNotification(this);
|
||||||
|
|
||||||
detach();
|
removeMainView();
|
||||||
|
|
||||||
if (history->lastMsg == this) {
|
if (history->lastMsg == this) {
|
||||||
history->fixLastMessage(wasAtBottom);
|
history->fixLastMessage(wasAtBottom);
|
||||||
|
@ -336,33 +338,18 @@ void HistoryItem::destroy() {
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::detach() {
|
void HistoryItem::removeMainView() {
|
||||||
if (detached()) return;
|
if (const auto view = mainView()) {
|
||||||
|
if (const auto channelHistory = _history->asChannelHistory()) {
|
||||||
if (_history->isChannel()) {
|
channelHistory->messageDetached(this);
|
||||||
_history->asChannelHistory()->messageDetached(this);
|
}
|
||||||
|
_history->setPendingResize();
|
||||||
|
view->removeFromBlock();
|
||||||
|
_mainView = nullptr;
|
||||||
}
|
}
|
||||||
_block->removeItem(this);
|
|
||||||
App::historyItemDetached(this);
|
|
||||||
|
|
||||||
_history->setPendingResize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::attachToBlock(not_null<HistoryBlock*> block, int index) {
|
void HistoryItem::clearMainView() {
|
||||||
Expects(!isLogEntry());
|
|
||||||
Expects(_block == nullptr);
|
|
||||||
Expects(_indexInBlock < 0);
|
|
||||||
Expects(index >= 0);
|
|
||||||
|
|
||||||
_block = block;
|
|
||||||
_indexInBlock = index;
|
|
||||||
_mainView = block->messages[index].get();
|
|
||||||
setPendingResize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryItem::detachFast() {
|
|
||||||
_block = nullptr;
|
|
||||||
_indexInBlock = -1;
|
|
||||||
_mainView = nullptr;
|
_mainView = nullptr;
|
||||||
|
|
||||||
validateGroupId();
|
validateGroupId();
|
||||||
|
@ -391,6 +378,7 @@ void HistoryItem::indexAsNewItem() {
|
||||||
|
|
||||||
void HistoryItem::previousItemChanged() {
|
void HistoryItem::previousItemChanged() {
|
||||||
Expects(!isLogEntry());
|
Expects(!isLogEntry());
|
||||||
|
|
||||||
recountDisplayDate();
|
recountDisplayDate();
|
||||||
recountAttachToPrevious();
|
recountAttachToPrevious();
|
||||||
}
|
}
|
||||||
|
@ -398,6 +386,7 @@ void HistoryItem::previousItemChanged() {
|
||||||
// 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());
|
Expects(!isLogEntry());
|
||||||
|
|
||||||
setAttachToNext(false);
|
setAttachToNext(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,6 +410,7 @@ bool HistoryItem::computeIsAttachToPrevious(not_null<HistoryItem*> previous) {
|
||||||
|
|
||||||
void HistoryItem::recountAttachToPrevious() {
|
void HistoryItem::recountAttachToPrevious() {
|
||||||
Expects(!isLogEntry());
|
Expects(!isLogEntry());
|
||||||
|
|
||||||
auto attachToPrevious = false;
|
auto attachToPrevious = false;
|
||||||
if (auto previous = previousItem()) {
|
if (auto previous = previousItem()) {
|
||||||
attachToPrevious = computeIsAttachToPrevious(previous);
|
attachToPrevious = computeIsAttachToPrevious(previous);
|
||||||
|
@ -940,11 +930,6 @@ void HistoryItem::clipCallback(Media::Clip::Notification notification) {
|
||||||
}
|
}
|
||||||
if (!stopped) {
|
if (!stopped) {
|
||||||
setPendingInitDimensions();
|
setPendingInitDimensions();
|
||||||
if (detached()) {
|
|
||||||
// We still want to handle our pending initDimensions and
|
|
||||||
// resize state even if we're detached in history.
|
|
||||||
_history->setHasPendingResizedItems();
|
|
||||||
}
|
|
||||||
Auth().data().markItemLayoutChanged(this);
|
Auth().data().markItemLayoutChanged(this);
|
||||||
Global::RefPendingRepaintItems().insert(this);
|
Global::RefPendingRepaintItems().insert(this);
|
||||||
}
|
}
|
||||||
|
@ -984,27 +969,26 @@ void HistoryItem::audioTrackUpdated() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HistoryItem::isUnderCursor() const {
|
||||||
|
if (const auto view = App::hoveredItem()) {
|
||||||
|
return view->data() == this;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
HistoryItem *HistoryItem::previousItem() const {
|
HistoryItem *HistoryItem::previousItem() const {
|
||||||
if (_block && _indexInBlock >= 0) {
|
if (const auto view = mainView()) {
|
||||||
if (_indexInBlock > 0) {
|
if (const auto previous = view->previousInBlocks()) {
|
||||||
return _block->messages[_indexInBlock - 1]->data();
|
return previous->data();
|
||||||
}
|
|
||||||
if (auto previous = _block->previousBlock()) {
|
|
||||||
Assert(!previous->messages.empty());
|
|
||||||
return previous->messages.back()->data();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *HistoryItem::nextItem() const {
|
HistoryItem *HistoryItem::nextItem() const {
|
||||||
if (_block && _indexInBlock >= 0) {
|
if (const auto view = mainView()) {
|
||||||
if (_indexInBlock + 1 < _block->messages.size()) {
|
if (const auto next = view->nextInBlocks()) {
|
||||||
return _block->messages[_indexInBlock + 1]->data();
|
return next->data();
|
||||||
}
|
|
||||||
if (auto next = _block->nextBlock()) {
|
|
||||||
Assert(!next->messages.empty());
|
|
||||||
return next->messages.front()->data();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1107,9 +1091,9 @@ HistoryItem::~HistoryItem() {
|
||||||
ClickHandlerPtr goToMessageClickHandler(PeerData *peer, MsgId msgId) {
|
ClickHandlerPtr goToMessageClickHandler(PeerData *peer, MsgId msgId) {
|
||||||
return std::make_shared<LambdaClickHandler>([peer, msgId] {
|
return std::make_shared<LambdaClickHandler>([peer, msgId] {
|
||||||
if (App::main()) {
|
if (App::main()) {
|
||||||
auto current = App::mousedItem();
|
auto view = App::mousedItem();
|
||||||
if (current && current->history()->peer == peer) {
|
if (view && view->data()->history()->peer == peer) {
|
||||||
App::main()->pushReplyReturn(current);
|
App::main()->pushReplyReturn(view->data());
|
||||||
}
|
}
|
||||||
App::wnd()->controller()->showPeerHistory(
|
App::wnd()->controller()->showPeerHistory(
|
||||||
peer,
|
peer,
|
||||||
|
|
|
@ -53,6 +53,9 @@ public:
|
||||||
int minHeight() const {
|
int minHeight() const {
|
||||||
return _minh;
|
return _minh;
|
||||||
}
|
}
|
||||||
|
int width() const {
|
||||||
|
return _width;
|
||||||
|
}
|
||||||
int height() const {
|
int height() const {
|
||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +65,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
mutable int _maxw = 0;
|
mutable int _maxw = 0;
|
||||||
mutable int _minh = 0;
|
mutable int _minh = 0;
|
||||||
|
mutable int _width = 0;
|
||||||
mutable int _height = 0;
|
mutable int _height = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -226,34 +230,16 @@ public:
|
||||||
PeerData *from() const {
|
PeerData *from() const {
|
||||||
return _from;
|
return _from;
|
||||||
}
|
}
|
||||||
HistoryBlock *block() {
|
|
||||||
return _block;
|
|
||||||
}
|
|
||||||
const HistoryBlock *block() const {
|
|
||||||
return _block;
|
|
||||||
}
|
|
||||||
HistoryView::Message *mainView() const {
|
HistoryView::Message *mainView() const {
|
||||||
return _mainView;
|
return _mainView;
|
||||||
}
|
}
|
||||||
|
void setMainView(HistoryView::Message *view) {
|
||||||
|
_mainView = view;
|
||||||
|
}
|
||||||
|
void clearMainView();
|
||||||
|
void removeMainView();
|
||||||
|
|
||||||
void destroy();
|
void destroy();
|
||||||
void detach();
|
|
||||||
void detachFast();
|
|
||||||
bool detached() const {
|
|
||||||
return !_block;
|
|
||||||
}
|
|
||||||
void attachToBlock(not_null<HistoryBlock*> block, int index);
|
|
||||||
void setIndexInBlock(int index) {
|
|
||||||
Expects(_block != nullptr);
|
|
||||||
Expects(index >= 0);
|
|
||||||
|
|
||||||
_indexInBlock = index;
|
|
||||||
}
|
|
||||||
int indexInBlock() const {
|
|
||||||
Expects((_indexInBlock >= 0) == (_block != nullptr));
|
|
||||||
//Expects((_block == nullptr) || (_block->messages[_indexInBlock]->data() == this));
|
|
||||||
|
|
||||||
return _indexInBlock;
|
|
||||||
}
|
|
||||||
bool out() const {
|
bool out() const {
|
||||||
return _flags & MTPDmessage::Flag::f_out;
|
return _flags & MTPDmessage::Flag::f_out;
|
||||||
}
|
}
|
||||||
|
@ -493,9 +479,7 @@ public:
|
||||||
}
|
}
|
||||||
void setPendingResize() {
|
void setPendingResize() {
|
||||||
_flags |= MTPDmessage_ClientFlag::f_pending_resize;
|
_flags |= MTPDmessage_ClientFlag::f_pending_resize;
|
||||||
if (!detached() || isLogEntry()) {
|
_history->setHasPendingResizedItems();
|
||||||
_history->setHasPendingResizedItems();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bool pendingInitDimensions() const {
|
bool pendingInitDimensions() const {
|
||||||
return _flags & MTPDmessage_ClientFlag::f_pending_init_dimensions;
|
return _flags & MTPDmessage_ClientFlag::f_pending_init_dimensions;
|
||||||
|
@ -535,10 +519,6 @@ public:
|
||||||
void makeGroupLeader(std::vector<not_null<HistoryItem*>> &&others);
|
void makeGroupLeader(std::vector<not_null<HistoryItem*>> &&others);
|
||||||
HistoryMessageGroup *getFullGroup();
|
HistoryMessageGroup *getFullGroup();
|
||||||
|
|
||||||
int width() const {
|
|
||||||
return _width;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clipCallback(Media::Clip::Notification notification);
|
void clipCallback(Media::Clip::Notification notification);
|
||||||
void audioTrackUpdated();
|
void audioTrackUpdated();
|
||||||
|
|
||||||
|
@ -556,6 +536,8 @@ public:
|
||||||
setAttachToNext(attachToNext);
|
setAttachToNext(attachToNext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isUnderCursor() const;
|
||||||
|
|
||||||
HistoryItem *previousItem() const;
|
HistoryItem *previousItem() const;
|
||||||
HistoryItem *nextItem() const;
|
HistoryItem *nextItem() const;
|
||||||
|
|
||||||
|
@ -586,8 +568,6 @@ protected:
|
||||||
|
|
||||||
const not_null<History*> _history;
|
const not_null<History*> _history;
|
||||||
not_null<PeerData*> _from;
|
not_null<PeerData*> _from;
|
||||||
HistoryBlock *_block = nullptr;
|
|
||||||
int _indexInBlock = -1;
|
|
||||||
MTPDmessage::Flags _flags = 0;
|
MTPDmessage::Flags _flags = 0;
|
||||||
|
|
||||||
// This should be called only from previousItemChanged()
|
// This should be called only from previousItemChanged()
|
||||||
|
@ -642,7 +622,6 @@ private:
|
||||||
void resetGroupMedia(const std::vector<not_null<HistoryItem*>> &others);
|
void resetGroupMedia(const std::vector<not_null<HistoryItem*>> &others);
|
||||||
|
|
||||||
HistoryView::Message *_mainView = nullptr;
|
HistoryView::Message *_mainView = nullptr;
|
||||||
int _width = 0;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -398,8 +398,9 @@ struct HistoryMessageLogEntryOriginal : public RuntimeComponent<HistoryMessageLo
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FileClickHandler;
|
||||||
struct HistoryDocumentThumbed : public RuntimeComponent<HistoryDocumentThumbed> {
|
struct HistoryDocumentThumbed : public RuntimeComponent<HistoryDocumentThumbed> {
|
||||||
ClickHandlerPtr _linksavel, _linkcancell;
|
std::shared_ptr<FileClickHandler> _linksavel, _linkcancell;
|
||||||
int _thumbw = 0;
|
int _thumbw = 0;
|
||||||
|
|
||||||
mutable int _linkw = 0;
|
mutable int _linkw = 0;
|
||||||
|
|
|
@ -230,10 +230,6 @@ public:
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentWidth() const {
|
|
||||||
return _width;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInBubbleState(MediaInBubbleState state) {
|
void setInBubbleState(MediaInBubbleState state) {
|
||||||
_inBubbleState = state;
|
_inBubbleState = state;
|
||||||
}
|
}
|
||||||
|
@ -265,7 +261,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
not_null<HistoryItem*> _parent;
|
not_null<HistoryItem*> _parent;
|
||||||
int _width = 0;
|
|
||||||
MediaInBubbleState _inBubbleState = MediaInBubbleState::None;
|
MediaInBubbleState _inBubbleState = MediaInBubbleState::None;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/history_item_components.h"
|
#include "history/history_item_components.h"
|
||||||
#include "history/history_media_types.h"
|
#include "history/history_media_types.h"
|
||||||
#include "history/history_message.h"
|
#include "history/history_message.h"
|
||||||
|
#include "history/view/history_view_message.h"
|
||||||
#include "storage/storage_shared_media.h"
|
#include "storage/storage_shared_media.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "ui/grouped_layout.h"
|
#include "ui/grouped_layout.h"
|
||||||
|
@ -176,7 +177,7 @@ void HistoryGroupedMedia::draw(
|
||||||
} else if (_parent->getMedia() == this) {
|
} else if (_parent->getMedia() == this) {
|
||||||
auto fullRight = _width;
|
auto fullRight = _width;
|
||||||
auto fullBottom = _height;
|
auto fullBottom = _height;
|
||||||
if (_parent->id < 0 || App::hoveredItem() == _parent) {
|
if (needInfoDisplay()) {
|
||||||
_parent->drawInfo(p, fullRight, fullBottom, _width, selected, InfoDisplayOverImage);
|
_parent->drawInfo(p, fullRight, fullBottom, _width, selected, InfoDisplayOverImage);
|
||||||
}
|
}
|
||||||
if (!_parent->hasBubble() && _parent->displayRightAction()) {
|
if (!_parent->hasBubble() && _parent->displayRightAction()) {
|
||||||
|
@ -295,7 +296,8 @@ void HistoryGroupedMedia::clickHandlerPressedChanged(
|
||||||
for (const auto &element : _elements) {
|
for (const auto &element : _elements) {
|
||||||
element.content->clickHandlerPressedChanged(p, pressed);
|
element.content->clickHandlerPressedChanged(p, pressed);
|
||||||
if (pressed && element.content->dragItemByHandler(p)) {
|
if (pressed && element.content->dragItemByHandler(p)) {
|
||||||
App::pressedLinkItem(element.item);
|
// #TODO pressedLinkItem
|
||||||
|
//App::pressedLinkItem(element.item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -455,3 +457,7 @@ bool HistoryGroupedMedia::computeNeedBubble() const {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HistoryGroupedMedia::needInfoDisplay() const {
|
||||||
|
return (_parent->id < 0 || _parent->isUnderCursor());
|
||||||
|
}
|
||||||
|
|
|
@ -115,6 +115,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool needInfoDisplay() const;
|
||||||
bool computeNeedBubble() const;
|
bool computeNeedBubble() const;
|
||||||
not_null<HistoryMedia*> main() const;
|
not_null<HistoryMedia*> main() const;
|
||||||
bool validateGroupElements(
|
bool validateGroupElements(
|
||||||
|
|
|
@ -446,7 +446,7 @@ void HistoryPhoto::draw(Painter &p, const QRect &r, TextSelection selection, Tim
|
||||||
} else if (notChild) {
|
} else if (notChild) {
|
||||||
auto fullRight = skipx + width;
|
auto fullRight = skipx + width;
|
||||||
auto fullBottom = skipy + height;
|
auto fullBottom = skipy + height;
|
||||||
if (_data->uploading() || App::hoveredItem() == _parent) {
|
if (needInfoDisplay()) {
|
||||||
_parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage);
|
_parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage);
|
||||||
}
|
}
|
||||||
if (!bubble && _parent->displayRightAction()) {
|
if (!bubble && _parent->displayRightAction()) {
|
||||||
|
@ -646,6 +646,10 @@ bool HistoryPhoto::dataLoaded() const {
|
||||||
return _data->loaded();
|
return _data->loaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HistoryPhoto::needInfoDisplay() const {
|
||||||
|
return (_data->uploading() || _parent->isUnderCursor());
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryPhoto::validateGroupedCache(
|
void HistoryPhoto::validateGroupedCache(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
|
@ -1402,11 +1406,17 @@ void HistoryDocument::createComponents(bool caption) {
|
||||||
}
|
}
|
||||||
UpdateComponents(mask);
|
UpdateComponents(mask);
|
||||||
if (auto thumbed = Get<HistoryDocumentThumbed>()) {
|
if (auto thumbed = Get<HistoryDocumentThumbed>()) {
|
||||||
thumbed->_linksavel = std::make_shared<DocumentSaveClickHandler>(_data);
|
thumbed->_linksavel = std::make_shared<DocumentSaveClickHandler>(
|
||||||
thumbed->_linkcancell = std::make_shared<DocumentCancelClickHandler>(_data);
|
_data,
|
||||||
|
_parent->fullId());
|
||||||
|
thumbed->_linkcancell = std::make_shared<DocumentCancelClickHandler>(
|
||||||
|
_data,
|
||||||
|
_parent->fullId());
|
||||||
}
|
}
|
||||||
if (auto voice = Get<HistoryDocumentVoice>()) {
|
if (auto voice = Get<HistoryDocumentVoice>()) {
|
||||||
voice->_seekl = std::make_shared<VoiceSeekClickHandler>(_data);
|
voice->_seekl = std::make_shared<VoiceSeekClickHandler>(
|
||||||
|
_data,
|
||||||
|
_parent->fullId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2066,6 +2076,23 @@ void HistoryDocument::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool
|
||||||
HistoryFileMedia::clickHandlerPressedChanged(p, pressed);
|
HistoryFileMedia::clickHandlerPressedChanged(p, pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryDocument::refreshParentId(not_null<HistoryItem*> realParent) {
|
||||||
|
HistoryFileMedia::refreshParentId(realParent);
|
||||||
|
|
||||||
|
const auto contextId = realParent->fullId();
|
||||||
|
if (auto thumbed = Get<HistoryDocumentThumbed>()) {
|
||||||
|
if (thumbed->_linksavel) {
|
||||||
|
thumbed->_linksavel->setMessageId(contextId);
|
||||||
|
thumbed->_linkcancell->setMessageId(contextId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (auto voice = Get<HistoryDocumentVoice>()) {
|
||||||
|
if (voice->_seekl) {
|
||||||
|
voice->_seekl->setMessageId(contextId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool HistoryDocument::playInline(bool autoplay) {
|
bool HistoryDocument::playInline(bool autoplay) {
|
||||||
if (_data->isVoiceMessage()) {
|
if (_data->isVoiceMessage()) {
|
||||||
DocumentOpenClickHandler::doOpen(_data, _parent, ActionOnLoadPlayInline);
|
DocumentOpenClickHandler::doOpen(_data, _parent, ActionOnLoadPlayInline);
|
||||||
|
@ -2157,7 +2184,9 @@ void HistoryGif::initDimensions() {
|
||||||
_caption.setSkipBlock(_parent->skipBlockWidth(), _parent->skipBlockHeight());
|
_caption.setSkipBlock(_parent->skipBlockWidth(), _parent->skipBlockHeight());
|
||||||
}
|
}
|
||||||
if (!_openInMediaviewLink) {
|
if (!_openInMediaviewLink) {
|
||||||
_openInMediaviewLink = std::make_shared<DocumentOpenClickHandler>(_data);
|
_openInMediaviewLink = std::make_shared<DocumentOpenClickHandler>(
|
||||||
|
_data,
|
||||||
|
_parent->fullId());
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 tw = 0, th = 0;
|
int32 tw = 0, th = 0;
|
||||||
|
@ -2548,7 +2577,7 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM
|
||||||
fullRight = maxRight;
|
fullRight = maxRight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isRound || _data->uploading() || App::hoveredItem() == _parent) {
|
if (isRound || needInfoDisplay()) {
|
||||||
_parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, isRound ? InfoDisplayOverBackground : InfoDisplayOverImage);
|
_parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, isRound ? InfoDisplayOverBackground : InfoDisplayOverImage);
|
||||||
}
|
}
|
||||||
if (!bubble && _parent->displayRightAction()) {
|
if (!bubble && _parent->displayRightAction()) {
|
||||||
|
@ -2955,6 +2984,10 @@ bool HistoryGif::dataLoaded() const {
|
||||||
return (_parent->id > 0) ? _data->loaded() : false;
|
return (_parent->id > 0) ? _data->loaded() : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HistoryGif::needInfoDisplay() const {
|
||||||
|
return (_data->uploading() || _parent->isUnderCursor());
|
||||||
|
}
|
||||||
|
|
||||||
HistorySticker::HistorySticker(
|
HistorySticker::HistorySticker(
|
||||||
not_null<HistoryItem*> parent,
|
not_null<HistoryItem*> parent,
|
||||||
not_null<DocumentData*> document)
|
not_null<DocumentData*> document)
|
||||||
|
@ -3835,7 +3868,7 @@ int HistoryWebPage::resizeGetHeight(int width) {
|
||||||
_height += _attach->height() - bubble.top() - bubble.bottom();
|
_height += _attach->height() - bubble.top() - bubble.bottom();
|
||||||
if (!_attach->additionalInfoString().isEmpty()) {
|
if (!_attach->additionalInfoString().isEmpty()) {
|
||||||
_height += bottomInfoPadding();
|
_height += bottomInfoPadding();
|
||||||
} else if (isBubbleBottom() && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
} else if (isBubbleBottom() && _attach->customInfoLayout() && _attach->width() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
||||||
_height += bottomInfoPadding();
|
_height += bottomInfoPadding();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3873,7 +3906,7 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, T
|
||||||
bshift += bottomInfoPadding();
|
bshift += bottomInfoPadding();
|
||||||
} else if (!attachAdditionalInfoText.isEmpty()) {
|
} else if (!attachAdditionalInfoText.isEmpty()) {
|
||||||
bshift += bottomInfoPadding();
|
bshift += bottomInfoPadding();
|
||||||
} else if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
} else if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->width() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
||||||
bshift += bottomInfoPadding();
|
bshift += bottomInfoPadding();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3939,13 +3972,13 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, T
|
||||||
|
|
||||||
auto attachLeft = padding.left() - bubble.left();
|
auto attachLeft = padding.left() - bubble.left();
|
||||||
auto attachTop = tshift - bubble.top();
|
auto attachTop = tshift - bubble.top();
|
||||||
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth();
|
if (rtl()) attachLeft = _width - attachLeft - _attach->width();
|
||||||
|
|
||||||
p.translate(attachLeft, attachTop);
|
p.translate(attachLeft, attachTop);
|
||||||
|
|
||||||
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
|
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
|
||||||
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
||||||
int32 pixwidth = _attach->currentWidth(), pixheight = _attach->height();
|
int32 pixwidth = _attach->width(), pixheight = _attach->height();
|
||||||
|
|
||||||
if (_data->type == WebPageVideo && _attach->type() == MediaTypePhoto) {
|
if (_data->type == WebPageVideo && _attach->type() == MediaTypePhoto) {
|
||||||
if (_attach->isReadyForOpen()) {
|
if (_attach->isReadyForOpen()) {
|
||||||
|
@ -3991,7 +4024,7 @@ HistoryTextState HistoryWebPage::getState(QPoint point, HistoryStateRequest requ
|
||||||
auto padding = inBubblePadding();
|
auto padding = inBubblePadding();
|
||||||
auto tshift = padding.top();
|
auto tshift = padding.top();
|
||||||
auto bshift = padding.bottom();
|
auto bshift = padding.bottom();
|
||||||
if (_asArticle || (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right())) {
|
if (_asArticle || (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->width() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right())) {
|
||||||
bshift += bottomInfoPadding();
|
bshift += bottomInfoPadding();
|
||||||
}
|
}
|
||||||
width -= padding.left() + padding.right();
|
width -= padding.left() + padding.right();
|
||||||
|
@ -4055,7 +4088,7 @@ HistoryTextState HistoryWebPage::getState(QPoint point, HistoryStateRequest requ
|
||||||
if (QRect(padding.left(), tshift, width, _height - tshift - bshift).contains(point)) {
|
if (QRect(padding.left(), tshift, width, _height - tshift - bshift).contains(point)) {
|
||||||
auto attachLeft = padding.left() - bubble.left();
|
auto attachLeft = padding.left() - bubble.left();
|
||||||
auto attachTop = tshift - bubble.top();
|
auto attachTop = tshift - bubble.top();
|
||||||
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth();
|
if (rtl()) attachLeft = _width - attachLeft - _attach->width();
|
||||||
result = _attach->getState(point - QPoint(attachLeft, attachTop), request);
|
result = _attach->getState(point - QPoint(attachLeft, attachTop), request);
|
||||||
|
|
||||||
if (result.link && !_data->document && _data->photo && _attach->isReadyForOpen()) {
|
if (result.link && !_data->document && _data->photo && _attach->isReadyForOpen()) {
|
||||||
|
@ -4325,7 +4358,7 @@ int HistoryGame::resizeGetHeight(int width) {
|
||||||
|
|
||||||
_attach->resizeGetHeight(width + bubble.left() + bubble.right());
|
_attach->resizeGetHeight(width + bubble.left() + bubble.right());
|
||||||
_height += _attach->height() - bubble.top() - bubble.bottom();
|
_height += _attach->height() - bubble.top() - bubble.bottom();
|
||||||
if (isBubbleBottom() && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
if (isBubbleBottom() && _attach->customInfoLayout() && _attach->width() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
||||||
_height += bottomInfoPadding();
|
_height += bottomInfoPadding();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4351,7 +4384,7 @@ void HistoryGame::draw(Painter &p, const QRect &r, TextSelection selection, Time
|
||||||
auto tshift = padding.top();
|
auto tshift = padding.top();
|
||||||
auto bshift = padding.bottom();
|
auto bshift = padding.bottom();
|
||||||
width -= padding.left() + padding.right();
|
width -= padding.left() + padding.right();
|
||||||
if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->width() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
||||||
bshift += bottomInfoPadding();
|
bshift += bottomInfoPadding();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4383,13 +4416,13 @@ void HistoryGame::draw(Painter &p, const QRect &r, TextSelection selection, Time
|
||||||
|
|
||||||
auto attachLeft = padding.left() - bubble.left();
|
auto attachLeft = padding.left() - bubble.left();
|
||||||
auto attachTop = tshift - bubble.top();
|
auto attachTop = tshift - bubble.top();
|
||||||
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth();
|
if (rtl()) attachLeft = _width - attachLeft - _attach->width();
|
||||||
|
|
||||||
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
|
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
|
||||||
|
|
||||||
p.translate(attachLeft, attachTop);
|
p.translate(attachLeft, attachTop);
|
||||||
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
||||||
auto pixwidth = _attach->currentWidth();
|
auto pixwidth = _attach->width();
|
||||||
auto pixheight = _attach->height();
|
auto pixheight = _attach->height();
|
||||||
|
|
||||||
auto gameW = _gameTagWidth + 2 * st::msgDateImgPadding.x();
|
auto gameW = _gameTagWidth + 2 * st::msgDateImgPadding.x();
|
||||||
|
@ -4419,7 +4452,7 @@ HistoryTextState HistoryGame::getState(QPoint point, HistoryStateRequest request
|
||||||
auto padding = inBubblePadding();
|
auto padding = inBubblePadding();
|
||||||
auto tshift = padding.top();
|
auto tshift = padding.top();
|
||||||
auto bshift = padding.bottom();
|
auto bshift = padding.bottom();
|
||||||
if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->width() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
||||||
bshift += bottomInfoPadding();
|
bshift += bottomInfoPadding();
|
||||||
}
|
}
|
||||||
width -= padding.left() + padding.right();
|
width -= padding.left() + padding.right();
|
||||||
|
@ -4465,9 +4498,9 @@ HistoryTextState HistoryGame::getState(QPoint point, HistoryStateRequest request
|
||||||
|
|
||||||
auto attachLeft = padding.left() - bubble.left();
|
auto attachLeft = padding.left() - bubble.left();
|
||||||
auto attachTop = tshift - bubble.top();
|
auto attachTop = tshift - bubble.top();
|
||||||
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth();
|
if (rtl()) attachLeft = _width - attachLeft - _attach->width();
|
||||||
|
|
||||||
if (QRect(attachLeft, tshift, _attach->currentWidth(), _height - tshift - bshift).contains(point)) {
|
if (QRect(attachLeft, tshift, _attach->width(), _height - tshift - bshift).contains(point)) {
|
||||||
if (_attach->isReadyForOpen()) {
|
if (_attach->isReadyForOpen()) {
|
||||||
if (!_parent->isLogEntry()) {
|
if (!_parent->isLogEntry()) {
|
||||||
result.link = _openl;
|
result.link = _openl;
|
||||||
|
@ -4782,7 +4815,7 @@ int HistoryInvoice::resizeGetHeight(int width) {
|
||||||
|
|
||||||
_attach->resizeGetHeight(width + bubble.left() + bubble.right());
|
_attach->resizeGetHeight(width + bubble.left() + bubble.right());
|
||||||
_height += _attach->height() - bubble.top() - bubble.bottom();
|
_height += _attach->height() - bubble.top() - bubble.bottom();
|
||||||
if (isBubbleBottom() && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
if (isBubbleBottom() && _attach->customInfoLayout() && _attach->width() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
||||||
_height += bottomInfoPadding();
|
_height += bottomInfoPadding();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -4816,7 +4849,7 @@ void HistoryInvoice::draw(Painter &p, const QRect &r, TextSelection selection, T
|
||||||
auto tshift = padding.top();
|
auto tshift = padding.top();
|
||||||
auto bshift = padding.bottom();
|
auto bshift = padding.bottom();
|
||||||
width -= padding.left() + padding.right();
|
width -= padding.left() + padding.right();
|
||||||
if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->width() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
||||||
bshift += bottomInfoPadding();
|
bshift += bottomInfoPadding();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4845,13 +4878,13 @@ void HistoryInvoice::draw(Painter &p, const QRect &r, TextSelection selection, T
|
||||||
|
|
||||||
auto attachLeft = padding.left() - bubble.left();
|
auto attachLeft = padding.left() - bubble.left();
|
||||||
auto attachTop = tshift - bubble.top();
|
auto attachTop = tshift - bubble.top();
|
||||||
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth();
|
if (rtl()) attachLeft = _width - attachLeft - _attach->width();
|
||||||
|
|
||||||
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
|
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
|
||||||
|
|
||||||
p.translate(attachLeft, attachTop);
|
p.translate(attachLeft, attachTop);
|
||||||
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
||||||
auto pixwidth = _attach->currentWidth();
|
auto pixwidth = _attach->width();
|
||||||
auto pixheight = _attach->height();
|
auto pixheight = _attach->height();
|
||||||
|
|
||||||
auto available = _status.maxWidth();
|
auto available = _status.maxWidth();
|
||||||
|
@ -4885,7 +4918,7 @@ HistoryTextState HistoryInvoice::getState(QPoint point, HistoryStateRequest requ
|
||||||
auto padding = inBubblePadding();
|
auto padding = inBubblePadding();
|
||||||
auto tshift = padding.top();
|
auto tshift = padding.top();
|
||||||
auto bshift = padding.bottom();
|
auto bshift = padding.bottom();
|
||||||
if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->width() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
|
||||||
bshift += bottomInfoPadding();
|
bshift += bottomInfoPadding();
|
||||||
}
|
}
|
||||||
width -= padding.left() + padding.right();
|
width -= padding.left() + padding.right();
|
||||||
|
@ -4924,9 +4957,9 @@ HistoryTextState HistoryInvoice::getState(QPoint point, HistoryStateRequest requ
|
||||||
|
|
||||||
auto attachLeft = padding.left() - bubble.left();
|
auto attachLeft = padding.left() - bubble.left();
|
||||||
auto attachTop = tshift - bubble.top();
|
auto attachTop = tshift - bubble.top();
|
||||||
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth();
|
if (rtl()) attachLeft = _width - attachLeft - _attach->width();
|
||||||
|
|
||||||
if (QRect(attachLeft, tshift, _attach->currentWidth(), _height - tshift - bshift).contains(point)) {
|
if (QRect(attachLeft, tshift, _attach->width(), _height - tshift - bshift).contains(point)) {
|
||||||
result = _attach->getState(point - QPoint(attachLeft, attachTop), request);
|
result = _attach->getState(point - QPoint(attachLeft, attachTop), request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,6 +254,7 @@ protected:
|
||||||
bool dataLoaded() const override;
|
bool dataLoaded() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool needInfoDisplay() const;
|
||||||
void validateGroupedCache(
|
void validateGroupedCache(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
|
@ -466,6 +467,8 @@ public:
|
||||||
|
|
||||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override;
|
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override;
|
||||||
|
|
||||||
|
void refreshParentId(not_null<HistoryItem*> realParent) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float64 dataProgress() const override;
|
float64 dataProgress() const override;
|
||||||
bool dataFinished() const override;
|
bool dataFinished() const override;
|
||||||
|
@ -588,6 +591,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool needInfoDisplay() const;
|
||||||
int additionalWidth(
|
int additionalWidth(
|
||||||
const HistoryMessageVia *via,
|
const HistoryMessageVia *via,
|
||||||
const HistoryMessageReply *reply,
|
const HistoryMessageReply *reply,
|
||||||
|
|
|
@ -1227,8 +1227,8 @@ bool HistoryMessage::displayFastReply() const {
|
||||||
|
|
||||||
QRect HistoryMessage::countGeometry() const {
|
QRect HistoryMessage::countGeometry() const {
|
||||||
auto maxwidth = qMin(st::msgMaxWidth, _maxw);
|
auto maxwidth = qMin(st::msgMaxWidth, _maxw);
|
||||||
if (_media && _media->currentWidth() < maxwidth) {
|
if (_media && _media->width() < maxwidth) {
|
||||||
maxwidth = qMax(_media->currentWidth(), qMin(maxwidth, plainMaxWidth()));
|
maxwidth = qMax(_media->width(), qMin(maxwidth, plainMaxWidth()));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto outLayout = hasOutLayout();
|
const auto outLayout = hasOutLayout();
|
||||||
|
@ -1904,7 +1904,7 @@ void HistoryMessage::paintFromName(
|
||||||
return 0;
|
return 0;
|
||||||
}();
|
}();
|
||||||
const auto replyWidth = [&] {
|
const auto replyWidth = [&] {
|
||||||
if (App::hoveredItem() == this && displayFastReply()) {
|
if (isUnderCursor() && displayFastReply()) {
|
||||||
return st::msgFont->width(FastReplyText());
|
return st::msgFont->width(FastReplyText());
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2364,7 +2364,7 @@ bool HistoryMessage::getStateFromName(
|
||||||
not_null<HistoryTextState*> outResult) const {
|
not_null<HistoryTextState*> outResult) const {
|
||||||
if (displayFromName()) {
|
if (displayFromName()) {
|
||||||
const auto replyWidth = [&] {
|
const auto replyWidth = [&] {
|
||||||
if (App::hoveredItem() == this && displayFastReply()) {
|
if (isUnderCursor() && displayFastReply()) {
|
||||||
return st::msgFont->width(FastReplyText());
|
return st::msgFont->width(FastReplyText());
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -550,7 +550,7 @@ int HistoryService::resizeContentGetHeight() {
|
||||||
}
|
}
|
||||||
_height += st::msgServicePadding.top() + st::msgServicePadding.bottom() + st::msgServiceMargin.top() + st::msgServiceMargin.bottom();
|
_height += st::msgServicePadding.top() + st::msgServicePadding.bottom() + st::msgServiceMargin.top() + st::msgServiceMargin.bottom();
|
||||||
if (_media) {
|
if (_media) {
|
||||||
_height += st::msgServiceMargin.top() + _media->resizeGetHeight(_media->currentWidth());
|
_height += st::msgServiceMargin.top() + _media->resizeGetHeight(_media->width());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -628,7 +628,7 @@ HistoryWidget::HistoryWidget(QWidget *parent, not_null<Window::Controller*> cont
|
||||||
}));
|
}));
|
||||||
subscribe(Auth().data().pendingHistoryResize(), [this] { handlePendingHistoryUpdate(); });
|
subscribe(Auth().data().pendingHistoryResize(), [this] { handlePendingHistoryUpdate(); });
|
||||||
subscribe(Auth().data().queryItemVisibility(), [this](const Data::Session::ItemVisibilityQuery &query) {
|
subscribe(Auth().data().queryItemVisibility(), [this](const Data::Session::ItemVisibilityQuery &query) {
|
||||||
if (_a_show.animating() || _history != query.item->history() || query.item->detached() || !isVisible()) {
|
if (_a_show.animating() || _history != query.item->history() || !query.item->mainView() || !isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto top = _list->itemTop(query.item);
|
auto top = _list->itemTop(query.item);
|
||||||
|
@ -642,9 +642,7 @@ HistoryWidget::HistoryWidget(QWidget *parent, not_null<Window::Controller*> cont
|
||||||
Auth().data().itemLayoutChanged(
|
Auth().data().itemLayoutChanged(
|
||||||
) | rpl::start_with_next([this](auto item) {
|
) | rpl::start_with_next([this](auto item) {
|
||||||
if (_peer && _list) {
|
if (_peer && _list) {
|
||||||
if ((item == App::mousedItem())
|
if (item->isUnderCursor()) {
|
||||||
|| (item == App::hoveredItem())
|
|
||||||
|| (item == App::hoveredLinkItem())) {
|
|
||||||
_list->onUpdateSelected();
|
_list->onUpdateSelected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -804,7 +802,7 @@ void HistoryWidget::adjustHighlightedMessageToMigrated() {
|
||||||
_history->channelId(),
|
_history->channelId(),
|
||||||
_highlightedMessageId);
|
_highlightedMessageId);
|
||||||
if (highlighted && highlighted->isGroupMigrate()) {
|
if (highlighted && highlighted->isGroupMigrate()) {
|
||||||
_highlightedMessageId = -_migrated->blocks.back()->messages.back()->id();
|
_highlightedMessageId = -_migrated->blocks.back()->messages.back()->data()->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -818,7 +816,7 @@ void HistoryWidget::checkNextHighlight() {
|
||||||
auto msgId = _highlightQueue.front();
|
auto msgId = _highlightQueue.front();
|
||||||
_highlightQueue.pop_front();
|
_highlightQueue.pop_front();
|
||||||
auto item = getItemFromHistoryOrMigrated(msgId);
|
auto item = getItemFromHistoryOrMigrated(msgId);
|
||||||
if (item && !item->detached()) {
|
if (item && item->mainView()) {
|
||||||
return msgId;
|
return msgId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -832,7 +830,7 @@ void HistoryWidget::checkNextHighlight() {
|
||||||
|
|
||||||
void HistoryWidget::updateHighlightedMessage() {
|
void HistoryWidget::updateHighlightedMessage() {
|
||||||
auto item = getItemFromHistoryOrMigrated(_highlightedMessageId);
|
auto item = getItemFromHistoryOrMigrated(_highlightedMessageId);
|
||||||
if (!item || item->detached()) {
|
if (!item || !item->mainView()) {
|
||||||
return stopMessageHighlight();
|
return stopMessageHighlight();
|
||||||
}
|
}
|
||||||
auto duration = st::activeFadeInDuration + st::activeFadeOutDuration;
|
auto duration = st::activeFadeInDuration + st::activeFadeOutDuration;
|
||||||
|
@ -1440,8 +1438,7 @@ void HistoryWidget::clearReplyReturns() {
|
||||||
_replyReturn = 0;
|
_replyReturn = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::pushReplyReturn(HistoryItem *item) {
|
void HistoryWidget::pushReplyReturn(not_null<HistoryItem*> item) {
|
||||||
if (!item) return;
|
|
||||||
if (item->history() == _history) {
|
if (item->history() == _history) {
|
||||||
_replyReturns.push_back(item->id);
|
_replyReturns.push_back(item->id);
|
||||||
} else if (item->history() == _migrated) {
|
} else if (item->history() == _migrated) {
|
||||||
|
@ -1707,13 +1704,6 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
||||||
_nonEmptySelection = false;
|
_nonEmptySelection = false;
|
||||||
_topBar->showSelected(HistoryView::TopBarWidget::SelectedState {});
|
_topBar->showSelected(HistoryView::TopBarWidget::SelectedState {});
|
||||||
|
|
||||||
App::hoveredItem(nullptr);
|
|
||||||
App::pressedItem(nullptr);
|
|
||||||
App::hoveredLinkItem(nullptr);
|
|
||||||
App::pressedLinkItem(nullptr);
|
|
||||||
App::contextItem(nullptr);
|
|
||||||
App::mousedItem(nullptr);
|
|
||||||
|
|
||||||
if (_peer) {
|
if (_peer) {
|
||||||
App::forgetMedia();
|
App::forgetMedia();
|
||||||
_serviceImageCacheSize = imageCacheSize();
|
_serviceImageCacheSize = imageCacheSize();
|
||||||
|
@ -2424,7 +2414,7 @@ bool HistoryWidget::doWeReadServerHistory() const {
|
||||||
if (scrollTop + 1 > _scroll->scrollTopMax()) return true;
|
if (scrollTop + 1 > _scroll->scrollTopMax()) return true;
|
||||||
|
|
||||||
auto showFrom = (_migrated && _migrated->showFrom) ? _migrated->showFrom : (_history ? _history->showFrom : nullptr);
|
auto showFrom = (_migrated && _migrated->showFrom) ? _migrated->showFrom : (_history ? _history->showFrom : nullptr);
|
||||||
if (showFrom && !showFrom->detached()) {
|
if (showFrom && showFrom->mainView()) {
|
||||||
int scrollBottom = scrollTop + _scroll->height();
|
int scrollBottom = scrollTop + _scroll->height();
|
||||||
if (scrollBottom > _list->itemTop(showFrom)) return true;
|
if (scrollBottom > _list->itemTop(showFrom)) return true;
|
||||||
}
|
}
|
||||||
|
@ -2445,7 +2435,7 @@ bool HistoryWidget::doWeReadMentions() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryWidget::historyHasNotFreezedUnreadBar(History *history) const {
|
bool HistoryWidget::historyHasNotFreezedUnreadBar(History *history) const {
|
||||||
if (history && history->showFrom && !history->showFrom->detached() && history->unreadBar) {
|
if (history && history->showFrom && history->showFrom->mainView() && history->unreadBar) {
|
||||||
if (auto unreadBar = history->unreadBar->Get<HistoryMessageUnreadBar>()) {
|
if (auto unreadBar = history->unreadBar->Get<HistoryMessageUnreadBar>()) {
|
||||||
return !unreadBar->_freezed;
|
return !unreadBar->_freezed;
|
||||||
}
|
}
|
||||||
|
@ -2675,7 +2665,7 @@ void HistoryWidget::visibleAreaUpdated() {
|
||||||
_list->visibleAreaUpdated(scrollTop, scrollBottom);
|
_list->visibleAreaUpdated(scrollTop, scrollBottom);
|
||||||
if (_history->loadedAtBottom() && (_history->unreadCount() > 0 || (_migrated && _migrated->unreadCount() > 0))) {
|
if (_history->loadedAtBottom() && (_history->unreadCount() > 0 || (_migrated && _migrated->unreadCount() > 0))) {
|
||||||
auto showFrom = (_migrated && _migrated->showFrom) ? _migrated->showFrom : (_history ? _history->showFrom : nullptr);
|
auto showFrom = (_migrated && _migrated->showFrom) ? _migrated->showFrom : (_history ? _history->showFrom : nullptr);
|
||||||
auto showFromVisible = (showFrom && !showFrom->detached() && scrollBottom > _list->itemTop(showFrom));
|
auto showFromVisible = (showFrom && showFrom->mainView() && scrollBottom > _list->itemTop(showFrom));
|
||||||
auto atBottom = (scrollTop >= _scroll->scrollTopMax());
|
auto atBottom = (scrollTop >= _scroll->scrollTopMax());
|
||||||
if ((showFromVisible || atBottom) && App::wnd()->doWeReadServerHistory()) {
|
if ((showFromVisible || atBottom) && App::wnd()->doWeReadServerHistory()) {
|
||||||
Auth().api().readServerHistory(_history);
|
Auth().api().readServerHistory(_history);
|
||||||
|
@ -2727,14 +2717,14 @@ void HistoryWidget::checkReplyReturns() {
|
||||||
auto scrollTopMax = _scroll->scrollTopMax();
|
auto scrollTopMax = _scroll->scrollTopMax();
|
||||||
auto scrollHeight = _scroll->height();
|
auto scrollHeight = _scroll->height();
|
||||||
while (_replyReturn) {
|
while (_replyReturn) {
|
||||||
auto below = (_replyReturn->detached() && _replyReturn->history() == _history && !_history->isEmpty() && _replyReturn->id < _history->blocks.back()->messages.back()->id());
|
auto below = (!_replyReturn->mainView() && _replyReturn->history() == _history && !_history->isEmpty() && _replyReturn->id < _history->blocks.back()->messages.back()->data()->id);
|
||||||
if (!below) {
|
if (!below) {
|
||||||
below = (_replyReturn->detached() && _replyReturn->history() == _migrated && !_history->isEmpty());
|
below = (!_replyReturn->mainView() && _replyReturn->history() == _migrated && !_history->isEmpty());
|
||||||
}
|
}
|
||||||
if (!below) {
|
if (!below) {
|
||||||
below = (_replyReturn->detached() && _migrated && _replyReturn->history() == _migrated && !_migrated->isEmpty() && _replyReturn->id < _migrated->blocks.back()->messages.back()->id());
|
below = (!_replyReturn->mainView() && _migrated && _replyReturn->history() == _migrated && !_migrated->isEmpty() && _replyReturn->id < _migrated->blocks.back()->messages.back()->data()->id);
|
||||||
}
|
}
|
||||||
if (!below && !_replyReturn->detached()) {
|
if (!below && _replyReturn->mainView()) {
|
||||||
below = (scrollTop >= scrollTopMax) || (_list->itemTop(_replyReturn) < scrollTop + scrollHeight / 2);
|
below = (scrollTop >= scrollTopMax) || (_list->itemTop(_replyReturn) < scrollTop + scrollHeight / 2);
|
||||||
}
|
}
|
||||||
if (below) {
|
if (below) {
|
||||||
|
@ -3424,7 +3414,7 @@ bool HistoryWidget::insertBotCommand(const QString &cmd) {
|
||||||
auto insertingInlineBot = !cmd.isEmpty() && (cmd.at(0) == '@');
|
auto insertingInlineBot = !cmd.isEmpty() && (cmd.at(0) == '@');
|
||||||
auto toInsert = cmd;
|
auto toInsert = cmd;
|
||||||
if (!toInsert.isEmpty() && !insertingInlineBot) {
|
if (!toInsert.isEmpty() && !insertingInlineBot) {
|
||||||
auto bot = _peer->isUser() ? _peer : (App::hoveredLinkItem() ? App::hoveredLinkItem()->fromOriginal() : nullptr);
|
auto bot = _peer->isUser() ? _peer : (App::hoveredLinkItem() ? App::hoveredLinkItem()->data()->fromOriginal() : nullptr);
|
||||||
if (bot && (!bot->isUser() || !bot->asUser()->botInfo)) {
|
if (bot && (!bot->isUser() || !bot->asUser()->botInfo)) {
|
||||||
bot = nullptr;
|
bot = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -4951,7 +4941,7 @@ void HistoryWidget::updateHistoryDownVisibility() {
|
||||||
if (!_list || !history || history->unreadCount() <= 0) {
|
if (!_list || !history || history->unreadCount() <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!history->showFrom || history->showFrom->detached()) {
|
if (!history->showFrom || !history->showFrom->mainView()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (_list->itemTop(history->showFrom) >= _scroll->scrollTop() + _scroll->height());
|
return (_list->itemTop(history->showFrom) >= _scroll->scrollTop() + _scroll->height());
|
||||||
|
@ -5052,41 +5042,34 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) {
|
||||||
_scroll->keyPressEvent(e);
|
_scroll->keyPressEvent(e);
|
||||||
} else if ((e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier)) == Qt::ControlModifier) {
|
} else if ((e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier)) == Qt::ControlModifier) {
|
||||||
if (_history && _history->lastMsg && !_editMsgId) {
|
if (_history && _history->lastMsg && !_editMsgId) {
|
||||||
if (_replyToId) {
|
if (const auto item = App::histItemById(_history->channelId(), _replyToId)) {
|
||||||
HistoryItem *item = App::histItemById(_history->channelId(), _replyToId)->nextItem();
|
if (const auto next = item->nextItem()) {
|
||||||
if (item) App::contextItem(item);
|
Ui::showPeerHistory(_peer, next->id);
|
||||||
else { cancelReply(); return; }
|
replyToMessage(next);
|
||||||
} else {
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
Ui::showPeerHistory(_peer, App::contextItem()->id);
|
|
||||||
onReplyToMessage();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (e->key() == Qt::Key_Up) {
|
} else if (e->key() == Qt::Key_Up) {
|
||||||
if (!(e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier))) {
|
if (!(e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier))) {
|
||||||
if (_history && _history->lastSentMsg && _history->lastSentMsg->canEdit(::date(unixtime()))) {
|
if (_history && _history->lastSentMsg && _history->lastSentMsg->canEdit(::date(unixtime()))) {
|
||||||
if (_field->isEmpty() && !_editMsgId && !_replyToId) {
|
if (_field->isEmpty() && !_editMsgId && !_replyToId && _history->lastSentMsg) {
|
||||||
App::contextItem(_history->lastSentMsg);
|
editMessage(_history->lastSentMsg);
|
||||||
onEditMessage();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_scroll->keyPressEvent(e);
|
_scroll->keyPressEvent(e);
|
||||||
} else if ((e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier)) == Qt::ControlModifier) {
|
} else if ((e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier)) == Qt::ControlModifier) {
|
||||||
if (_history && _history->lastMsg && !_editMsgId) {
|
if (_history && _history->lastMsg && !_editMsgId) {
|
||||||
if (_replyToId) {
|
if (const auto item = App::histItemById(_history->channelId(), _replyToId)) {
|
||||||
HistoryItem *item = App::histItemById(_history->channelId(), _replyToId);
|
if (const auto previous = item->previousItem()) {
|
||||||
App::contextItem(item->previousItem());
|
Ui::showPeerHistory(_peer, previous->id);
|
||||||
} else {
|
replyToMessage(previous);
|
||||||
App::contextItem(_history->lastMsg);
|
}
|
||||||
|
} else if (const auto previous = _history->lastMsg) {
|
||||||
|
Ui::showPeerHistory(_peer, previous->id);
|
||||||
|
replyToMessage(previous);
|
||||||
}
|
}
|
||||||
if (App::contextItem()) {
|
|
||||||
Ui::showPeerHistory(_peer, App::contextItem()->id);
|
|
||||||
onReplyToMessage();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
|
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
|
||||||
|
@ -5517,26 +5500,31 @@ void HistoryWidget::setFieldText(const TextWithTags &textWithTags, TextUpdateEve
|
||||||
_previewLinks.clear();
|
_previewLinks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onReplyToMessage() {
|
void HistoryWidget::replyToMessage(FullMsgId itemId) {
|
||||||
auto to = App::contextItem();
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
if (!to || to->id <= 0 || !_canSendMessages) return;
|
replyToMessage(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (to->history() == _migrated) {
|
void HistoryWidget::replyToMessage(not_null<HistoryItem*> item) {
|
||||||
if (to->isGroupMigrate() && !_history->isEmpty() && _history->blocks.front()->messages.front()->data()->isGroupMigrate() && _history != _migrated) {
|
if (!IsServerMsgId(item->id) || !_canSendMessages) {
|
||||||
App::contextItem(_history->blocks.front()->messages.front()->data());
|
return;
|
||||||
onReplyToMessage();
|
}
|
||||||
App::contextItem(to);
|
if (item->history() == _migrated) {
|
||||||
|
if (item->isGroupMigrate()
|
||||||
|
&& !_history->isEmpty()
|
||||||
|
&& _history->blocks.front()->messages.front()->data()->isGroupMigrate()
|
||||||
|
&& _history != _migrated) {
|
||||||
|
replyToMessage(_history->blocks.front()->messages.front()->data());
|
||||||
} else {
|
} else {
|
||||||
if (to->id < 0 || to->serviceMsg()) {
|
if (item->serviceMsg()) {
|
||||||
Ui::show(Box<InformBox>(lang(lng_reply_cant)));
|
Ui::show(Box<InformBox>(lang(lng_reply_cant)));
|
||||||
} else {
|
} else {
|
||||||
Ui::show(Box<ConfirmBox>(lang(lng_reply_cant_forward), lang(lng_selected_forward), base::lambda_guarded(this, [this] {
|
const auto itemId = item->fullId();
|
||||||
auto item = App::contextItem();
|
Ui::show(Box<ConfirmBox>(lang(lng_reply_cant_forward), lang(lng_selected_forward), base::lambda_guarded(this, [=] {
|
||||||
if (!item || item->id < 0 || item->serviceMsg()) return;
|
|
||||||
|
|
||||||
App::main()->setForwardDraft(
|
App::main()->setForwardDraft(
|
||||||
_peer->id,
|
_peer->id,
|
||||||
{ 1, item->fullId() });
|
{ 1, itemId });
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5547,13 +5535,17 @@ void HistoryWidget::onReplyToMessage() {
|
||||||
|
|
||||||
if (_editMsgId) {
|
if (_editMsgId) {
|
||||||
if (auto localDraft = _history->localDraft()) {
|
if (auto localDraft = _history->localDraft()) {
|
||||||
localDraft->msgId = to->id;
|
localDraft->msgId = item->id;
|
||||||
} else {
|
} else {
|
||||||
_history->setLocalDraft(std::make_unique<Data::Draft>(TextWithTags(), to->id, MessageCursor(), false));
|
_history->setLocalDraft(std::make_unique<Data::Draft>(
|
||||||
|
TextWithTags(),
|
||||||
|
item->id,
|
||||||
|
MessageCursor(),
|
||||||
|
false));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_replyEditMsg = to;
|
_replyEditMsg = item;
|
||||||
_replyToId = to->id;
|
_replyToId = item->id;
|
||||||
_replyEditMsgText.setText(
|
_replyEditMsgText.setText(
|
||||||
st::messageTextStyle,
|
st::messageTextStyle,
|
||||||
TextUtilities::Clean(_replyEditMsg->inReplyText()),
|
TextUtilities::Clean(_replyEditMsg->inReplyText()),
|
||||||
|
@ -5575,13 +5567,16 @@ void HistoryWidget::onReplyToMessage() {
|
||||||
_field->setFocus();
|
_field->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onEditMessage() {
|
void HistoryWidget::editMessage(FullMsgId itemId) {
|
||||||
auto to = App::contextItem();
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
if (!to) return;
|
editMessage(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (auto media = to->getMedia()) {
|
void HistoryWidget::editMessage(not_null<HistoryItem*> item) {
|
||||||
|
if (const auto media = item->getMedia()) {
|
||||||
if (media->canEditCaption()) {
|
if (media->canEditCaption()) {
|
||||||
Ui::show(Box<EditCaptionBox>(media, to->fullId()));
|
Ui::show(Box<EditCaptionBox>(media, item->fullId()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5598,14 +5593,25 @@ void HistoryWidget::onEditMessage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto original = to->originalText();
|
const auto original = item->originalText();
|
||||||
auto editData = TextWithTags { TextUtilities::ApplyEntities(original), ConvertEntitiesToTextTags(original.entities) };
|
const auto editData = TextWithTags {
|
||||||
auto cursor = MessageCursor { editData.text.size(), editData.text.size(), QFIXED_MAX };
|
TextUtilities::ApplyEntities(original),
|
||||||
_history->setEditDraft(std::make_unique<Data::Draft>(editData, to->id, cursor, false));
|
ConvertEntitiesToTextTags(original.entities)
|
||||||
|
};
|
||||||
|
const auto cursor = MessageCursor {
|
||||||
|
editData.text.size(),
|
||||||
|
editData.text.size(),
|
||||||
|
QFIXED_MAX
|
||||||
|
};
|
||||||
|
_history->setEditDraft(std::make_unique<Data::Draft>(
|
||||||
|
editData,
|
||||||
|
item->id,
|
||||||
|
cursor,
|
||||||
|
false));
|
||||||
applyDraft(false);
|
applyDraft(false);
|
||||||
|
|
||||||
_previewData = nullptr;
|
_previewData = nullptr;
|
||||||
if (auto media = to->getMedia()) {
|
if (const auto media = item->getMedia()) {
|
||||||
if (media->type() == MediaTypeWebPage) {
|
if (media->type() == MediaTypeWebPage) {
|
||||||
_previewData = static_cast<HistoryWebPage*>(media)->webpage();
|
_previewData = static_cast<HistoryWebPage*>(media)->webpage();
|
||||||
updatePreview();
|
updatePreview();
|
||||||
|
@ -5631,22 +5637,23 @@ void HistoryWidget::onEditMessage() {
|
||||||
_field->setFocus();
|
_field->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onPinMessage() {
|
void HistoryWidget::pinMessage(FullMsgId itemId) {
|
||||||
auto to = App::contextItem();
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
if (!to || !to->canPin()) return;
|
if (item->canPin()) {
|
||||||
|
const auto channel = item->history()->peer->asChannel();
|
||||||
Ui::show(Box<PinMessageBox>(
|
Assert(channel != nullptr);
|
||||||
to->history()->peer->asChannel(),
|
Ui::show(Box<PinMessageBox>(channel, item->id));
|
||||||
to->id));
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onUnpinMessage() {
|
void HistoryWidget::unpinMessage(FullMsgId itemId) {
|
||||||
if (!_peer || !_peer->isChannel()) return;
|
const auto channel = _peer ? _peer->asChannel() : nullptr;
|
||||||
|
if (!channel) {
|
||||||
Ui::show(Box<ConfirmBox>(lang(lng_pinned_unpin_sure), lang(lng_pinned_unpin), base::lambda_guarded(this, [this] {
|
return;
|
||||||
auto channel = _peer ? _peer->asChannel() : nullptr;
|
}
|
||||||
if (!channel) return;
|
|
||||||
|
|
||||||
|
Ui::show(Box<ConfirmBox>(lang(lng_pinned_unpin_sure), lang(lng_pinned_unpin), base::lambda_guarded(this, [=] {
|
||||||
channel->clearPinnedMessage();
|
channel->clearPinnedMessage();
|
||||||
|
|
||||||
Ui::hideLayer();
|
Ui::hideLayer();
|
||||||
|
@ -5666,8 +5673,8 @@ void HistoryWidget::unpinDone(const MTPUpdates &updates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onPinnedHide() {
|
void HistoryWidget::onPinnedHide() {
|
||||||
auto channel = _peer ? _peer->asChannel() : nullptr;
|
const auto channel = _peer ? _peer->asChannel() : nullptr;
|
||||||
auto pinnedId = channel->pinnedMessageId();
|
const auto pinnedId = channel ? channel->pinnedMessageId() : MsgId(0);
|
||||||
if (!pinnedId) {
|
if (!pinnedId) {
|
||||||
if (pinnedMsgVisibilityUpdated()) {
|
if (pinnedMsgVisibilityUpdated()) {
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
|
@ -5677,9 +5684,9 @@ void HistoryWidget::onPinnedHide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel->canPinMessages()) {
|
if (channel->canPinMessages()) {
|
||||||
onUnpinMessage();
|
unpinMessage(FullMsgId(peerToChannel(channel->id), pinnedId));
|
||||||
} else {
|
} else {
|
||||||
Global::RefHiddenPinnedMessages().insert(_peer->id, pinnedId);
|
Global::RefHiddenPinnedMessages().insert(channel->id, pinnedId);
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
if (pinnedMsgVisibilityUpdated()) {
|
if (pinnedMsgVisibilityUpdated()) {
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
|
@ -5688,11 +5695,12 @@ void HistoryWidget::onPinnedHide() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onCopyPostLink() {
|
void HistoryWidget::copyPostLink(FullMsgId itemId) {
|
||||||
auto item = App::contextItem();
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
if (!item || !item->hasDirectLink()) return;
|
if (item->hasDirectLink()) {
|
||||||
|
QApplication::clipboard()->setText(item->directLink());
|
||||||
QApplication::clipboard()->setText(item->directLink());
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryWidget::lastForceReplyReplied(const FullMsgId &replyTo) const {
|
bool HistoryWidget::lastForceReplyReplied(const FullMsgId &replyTo) const {
|
||||||
|
@ -6076,10 +6084,7 @@ void HistoryWidget::onForwardSelected() {
|
||||||
void HistoryWidget::confirmDeleteSelectedItems() {
|
void HistoryWidget::confirmDeleteSelectedItems() {
|
||||||
if (!_list) return;
|
if (!_list) return;
|
||||||
|
|
||||||
auto selected = _list->getSelectedItems();
|
App::main()->deleteLayer(_list->getSelectedItems());
|
||||||
if (selected.empty()) return;
|
|
||||||
|
|
||||||
App::main()->deleteLayer(int(selected.size()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::deleteSelectedItems(bool forEveryone) {
|
void HistoryWidget::deleteSelectedItems(bool forEveryone) {
|
||||||
|
|
|
@ -250,6 +250,14 @@ public:
|
||||||
|
|
||||||
void updateScrollColors();
|
void updateScrollColors();
|
||||||
|
|
||||||
|
void replyToMessage(FullMsgId itemId);
|
||||||
|
void replyToMessage(not_null<HistoryItem*> item);
|
||||||
|
void editMessage(FullMsgId itemId);
|
||||||
|
void editMessage(not_null<HistoryItem*> item);
|
||||||
|
void pinMessage(FullMsgId itemId);
|
||||||
|
void unpinMessage(FullMsgId itemId);
|
||||||
|
void copyPostLink(FullMsgId itemId);
|
||||||
|
|
||||||
MsgId replyToId() const;
|
MsgId replyToId() const;
|
||||||
void messageDataReceived(ChannelData *channel, MsgId msgId);
|
void messageDataReceived(ChannelData *channel, MsgId msgId);
|
||||||
bool lastForceReplyReplied(const FullMsgId &replyTo) const;
|
bool lastForceReplyReplied(const FullMsgId &replyTo) const;
|
||||||
|
@ -260,7 +268,7 @@ public:
|
||||||
void updateForwardingTexts();
|
void updateForwardingTexts();
|
||||||
|
|
||||||
void clearReplyReturns();
|
void clearReplyReturns();
|
||||||
void pushReplyReturn(HistoryItem *item);
|
void pushReplyReturn(not_null<HistoryItem*> item);
|
||||||
QList<MsgId> replyReturns();
|
QList<MsgId> replyReturns();
|
||||||
void setReplyReturns(PeerId peer, const QList<MsgId> &replyReturns);
|
void setReplyReturns(PeerId peer, const QList<MsgId> &replyReturns);
|
||||||
void calcNextReplyReturn();
|
void calcNextReplyReturn();
|
||||||
|
@ -361,12 +369,7 @@ signals:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onCancel();
|
void onCancel();
|
||||||
void onReplyToMessage();
|
|
||||||
void onEditMessage();
|
|
||||||
void onPinMessage();
|
|
||||||
void onUnpinMessage();
|
|
||||||
void onPinnedHide();
|
void onPinnedHide();
|
||||||
void onCopyPostLink();
|
|
||||||
void onFieldBarCancel();
|
void onFieldBarCancel();
|
||||||
|
|
||||||
void onPreviewParse();
|
void onPreviewParse();
|
||||||
|
|
|
@ -466,13 +466,13 @@ void ListWidget::checkMoveToOtherViewer() {
|
||||||
|
|
||||||
QString ListWidget::tooltipText() const {
|
QString ListWidget::tooltipText() const {
|
||||||
if (_mouseCursorState == HistoryInDateCursorState && _mouseAction == MouseAction::None) {
|
if (_mouseCursorState == HistoryInDateCursorState && _mouseAction == MouseAction::None) {
|
||||||
if (const auto item = App::hoveredItem()) {
|
if (const auto view = App::hoveredItem()) {
|
||||||
auto dateText = item->date.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat));
|
auto dateText = view->data()->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 (const auto item = App::hoveredItem()) {
|
if (const auto view = App::hoveredItem()) {
|
||||||
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
|
if (const auto forwarded = view->data()->Get<HistoryMessageForwarded>()) {
|
||||||
return forwarded->text.originalText(AllTextSelection, ExpandLinksNone);
|
return forwarded->text.originalText(AllTextSelection, ExpandLinksNone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -724,10 +724,6 @@ void ListWidget::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
if (_menu) {
|
|
||||||
_menu->deleteLater();
|
|
||||||
_menu = 0;
|
|
||||||
}
|
|
||||||
if (e->reason() == QContextMenuEvent::Mouse) {
|
if (e->reason() == QContextMenuEvent::Mouse) {
|
||||||
mouseActionUpdate(e->globalPos());
|
mouseActionUpdate(e->globalPos());
|
||||||
}
|
}
|
||||||
|
@ -742,10 +738,12 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
auto selTo = _selectedText.to;
|
auto selTo = _selectedText.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), viewForItem(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()->data()->getState(mousePos, request);
|
||||||
if (dragState.cursor == HistoryInTextCursorState && dragState.symbol >= selFrom && dragState.symbol < selTo) {
|
if (dragState.cursor == HistoryInTextCursorState && dragState.symbol >= selFrom && dragState.symbol < selTo) {
|
||||||
isUponSelected = 1;
|
isUponSelected = 1;
|
||||||
}
|
}
|
||||||
|
@ -755,10 +753,12 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
isUponSelected = hasSelected;
|
isUponSelected = hasSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
_menu = new Ui::PopupMenu(nullptr);
|
_menu = base::make_unique_q<Ui::PopupMenu>(nullptr);
|
||||||
|
|
||||||
_contextMenuLink = ClickHandler::getActive();
|
_contextMenuLink = ClickHandler::getActive();
|
||||||
auto item = App::hoveredItem() ? App::hoveredItem() : App::hoveredLinkItem();
|
auto view = App::hoveredItem()
|
||||||
|
? App::hoveredItem()
|
||||||
|
: App::hoveredLinkItem();
|
||||||
auto lnkPhoto = dynamic_cast<PhotoClickHandler*>(_contextMenuLink.get());
|
auto lnkPhoto = dynamic_cast<PhotoClickHandler*>(_contextMenuLink.get());
|
||||||
auto lnkDocument = dynamic_cast<DocumentClickHandler*>(_contextMenuLink.get());
|
auto lnkDocument = dynamic_cast<DocumentClickHandler*>(_contextMenuLink.get());
|
||||||
auto lnkPeer = dynamic_cast<PeerClickHandler*>(_contextMenuLink.get());
|
auto lnkPeer = dynamic_cast<PeerClickHandler*>(_contextMenuLink.get());
|
||||||
|
@ -767,39 +767,50 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
auto lnkIsAudio = lnkDocument ? lnkDocument->document()->isAudioFile() : false;
|
auto lnkIsAudio = lnkDocument ? lnkDocument->document()->isAudioFile() : false;
|
||||||
if (lnkPhoto || lnkDocument) {
|
if (lnkPhoto || lnkDocument) {
|
||||||
if (isUponSelected > 0) {
|
if (isUponSelected > 0) {
|
||||||
_menu->addAction(lang(lng_context_copy_selected), [this] { copySelectedText(); })->setEnabled(true);
|
_menu->addAction(lang(lng_context_copy_selected), [=] {
|
||||||
|
copySelectedText();
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
if (lnkPhoto) {
|
if (lnkPhoto) {
|
||||||
_menu->addAction(lang(lng_context_save_image), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, photo = lnkPhoto->photo()] {
|
const auto photo = lnkPhoto->photo();
|
||||||
|
_menu->addAction(lang(lng_context_save_image), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [=] {
|
||||||
savePhotoToFile(photo);
|
savePhotoToFile(photo);
|
||||||
}))->setEnabled(true);
|
}))->setEnabled(true);
|
||||||
_menu->addAction(lang(lng_context_copy_image), [this, photo = lnkPhoto->photo()] {
|
_menu->addAction(lang(lng_context_copy_image), [=] {
|
||||||
copyContextImage(photo);
|
copyContextImage(photo);
|
||||||
})->setEnabled(true);
|
})->setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
auto document = lnkDocument->document();
|
auto document = lnkDocument->document();
|
||||||
if (document->loading()) {
|
if (document->loading()) {
|
||||||
_menu->addAction(lang(lng_context_cancel_download), [this] { cancelContextDownload(); })->setEnabled(true);
|
_menu->addAction(lang(lng_context_cancel_download), [=] {
|
||||||
|
cancelContextDownload(document);
|
||||||
|
})->setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
if (document->loaded() && document->isGifv()) {
|
if (document->loaded() && document->isGifv()) {
|
||||||
if (!cAutoPlayGif()) {
|
if (!cAutoPlayGif()) {
|
||||||
_menu->addAction(lang(lng_context_open_gif), [this] { openContextGif(); })->setEnabled(true);
|
const auto itemId = view
|
||||||
|
? view->data()->fullId()
|
||||||
|
: FullMsgId();
|
||||||
|
_menu->addAction(lang(lng_context_open_gif), [=] {
|
||||||
|
openContextGif(itemId);
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!document->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
|
if (!document->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
|
||||||
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), [this] { showContextInFolder(); })->setEnabled(true);
|
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), [=] {
|
||||||
|
showContextInFolder(document);
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
_menu->addAction(lang(lnkIsVideo ? lng_context_save_video : (lnkIsVoice ? lng_context_save_audio : (lnkIsAudio ? lng_context_save_audio_file : lng_context_save_file))), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
_menu->addAction(lang(lnkIsVideo ? lng_context_save_video : (lnkIsVoice ? lng_context_save_audio : (lnkIsAudio ? lng_context_save_audio_file : lng_context_save_file))), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
||||||
saveDocumentToFile(document);
|
saveDocumentToFile(document);
|
||||||
}))->setEnabled(true);
|
}))->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (App::hoveredLinkItem()) {
|
|
||||||
App::contextItem(App::hoveredLinkItem());
|
|
||||||
}
|
|
||||||
} else if (lnkPeer) { // suggest to block
|
} else if (lnkPeer) { // suggest to block
|
||||||
// #TODO suggest restrict peer
|
// #TODO suggest restrict peer
|
||||||
} else { // maybe cursor on some text history item?
|
} else { // maybe cursor on some text history item?
|
||||||
|
const auto item = view ? view->data().get() : nullptr;
|
||||||
|
const auto itemId = item ? item->fullId() : FullMsgId();
|
||||||
bool canDelete = item && item->canDelete() && (item->id > 0 || !item->serviceMsg());
|
bool canDelete = item && item->canDelete() && (item->id > 0 || !item->serviceMsg());
|
||||||
bool canForward = item && item->canForward();
|
bool canForward = item && item->canForward();
|
||||||
|
|
||||||
|
@ -817,7 +828,9 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
if (media->type() == MediaTypeSticker) {
|
if (media->type() == MediaTypeSticker) {
|
||||||
if (auto document = media->getDocument()) {
|
if (auto document = media->getDocument()) {
|
||||||
if (document->sticker() && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
if (document->sticker() && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
||||||
_menu->addAction(lang(document->sticker()->setInstalled() ? lng_context_pack_info : lng_context_pack_add), [this] { showStickerPackInfo(); });
|
_menu->addAction(lang(document->sticker()->setInstalled() ? lng_context_pack_info : lng_context_pack_add), [=] {
|
||||||
|
showStickerPackInfo(document);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
_menu->addAction(lang(lng_context_save_image), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
_menu->addAction(lang(lng_context_save_image), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
||||||
saveDocumentToFile(document);
|
saveDocumentToFile(document);
|
||||||
|
@ -826,15 +839,21 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
} else if (media->type() == MediaTypeGif && !_contextMenuLink) {
|
} else if (media->type() == MediaTypeGif && !_contextMenuLink) {
|
||||||
if (auto document = media->getDocument()) {
|
if (auto document = media->getDocument()) {
|
||||||
if (document->loading()) {
|
if (document->loading()) {
|
||||||
_menu->addAction(lang(lng_context_cancel_download), [this] { cancelContextDownload(); })->setEnabled(true);
|
_menu->addAction(lang(lng_context_cancel_download), [=] {
|
||||||
|
cancelContextDownload(document);
|
||||||
|
})->setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
if (document->isGifv()) {
|
if (document->isGifv()) {
|
||||||
if (!cAutoPlayGif()) {
|
if (!cAutoPlayGif()) {
|
||||||
_menu->addAction(lang(lng_context_open_gif), [this] { openContextGif(); })->setEnabled(true);
|
_menu->addAction(lang(lng_context_open_gif), [=] {
|
||||||
|
openContextGif(itemId);
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!document->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
|
if (!document->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
|
||||||
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), [this] { showContextInFolder(); })->setEnabled(true);
|
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), [=] {
|
||||||
|
showContextInFolder(document);
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
_menu->addAction(lang(lng_context_save_file), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
_menu->addAction(lang(lng_context_save_file), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] {
|
||||||
saveDocumentToFile(document);
|
saveDocumentToFile(document);
|
||||||
|
@ -844,7 +863,9 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msg && !_contextMenuLink && (!msg->emptyText() || mediaHasTextForCopy)) {
|
if (msg && !_contextMenuLink && (!msg->emptyText() || mediaHasTextForCopy)) {
|
||||||
_menu->addAction(lang(lng_context_copy_text), [this] { copyContextText(); })->setEnabled(true);
|
_menu->addAction(lang(lng_context_copy_text), [=] {
|
||||||
|
copyContextText(itemId);
|
||||||
|
})->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -853,17 +874,11 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
if (!linkCopyToClipboardText.isEmpty()) {
|
if (!linkCopyToClipboardText.isEmpty()) {
|
||||||
_menu->addAction(linkCopyToClipboardText, [this] { copyContextUrl(); })->setEnabled(true);
|
_menu->addAction(linkCopyToClipboardText, [this] { copyContextUrl(); })->setEnabled(true);
|
||||||
}
|
}
|
||||||
App::contextItem(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_menu->actions().isEmpty()) {
|
if (_menu->actions().isEmpty()) {
|
||||||
delete base::take(_menu);
|
_menu = nullptr;
|
||||||
} else {
|
} else {
|
||||||
connect(_menu, &QObject::destroyed, this, [this](QObject *object) {
|
|
||||||
if (_menu == object) {
|
|
||||||
_menu = nullptr;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
_menu->popup(e->globalPos());
|
_menu->popup(e->globalPos());
|
||||||
e->accept();
|
e->accept();
|
||||||
}
|
}
|
||||||
|
@ -873,11 +888,15 @@ void ListWidget::savePhotoToFile(PhotoData *photo) {
|
||||||
if (!photo || !photo->date || !photo->loaded()) return;
|
if (!photo || !photo->date || !photo->loaded()) return;
|
||||||
|
|
||||||
auto filter = qsl("JPEG Image (*.jpg);;") + FileDialog::AllFilesFilter();
|
auto filter = qsl("JPEG Image (*.jpg);;") + FileDialog::AllFilesFilter();
|
||||||
FileDialog::GetWritePath(lang(lng_save_photo), filter, filedialogDefaultName(qsl("photo"), qsl(".jpg")), base::lambda_guarded(this, [this, photo](const QString &result) {
|
FileDialog::GetWritePath(
|
||||||
if (!result.isEmpty()) {
|
lang(lng_save_photo),
|
||||||
photo->full->pix().toImage().save(result, "JPG");
|
filter,
|
||||||
}
|
filedialogDefaultName(qsl("photo"), qsl(".jpg")),
|
||||||
}));
|
base::lambda_guarded(this, [this, photo](const QString &result) {
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
photo->full->pix().toImage().save(result, "JPG");
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::saveDocumentToFile(DocumentData *document) {
|
void ListWidget::saveDocumentToFile(DocumentData *document) {
|
||||||
|
@ -900,50 +919,28 @@ void ListWidget::copyContextUrl() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::showStickerPackInfo() {
|
void ListWidget::showStickerPackInfo(not_null<DocumentData*> document) {
|
||||||
if (!App::contextItem()) return;
|
if (auto sticker = document->sticker()) {
|
||||||
|
if (sticker->set.type() != mtpc_inputStickerSetEmpty) {
|
||||||
if (auto media = App::contextItem()->getMedia()) {
|
App::main()->stickersBox(sticker->set);
|
||||||
if (auto doc = media->getDocument()) {
|
|
||||||
if (auto sticker = doc->sticker()) {
|
|
||||||
if (sticker->set.type() != mtpc_inputStickerSetEmpty) {
|
|
||||||
App::main()->stickersBox(sticker->set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::cancelContextDownload() {
|
void ListWidget::cancelContextDownload(not_null<DocumentData*> document) {
|
||||||
if (auto lnkDocument = dynamic_cast<DocumentClickHandler*>(_contextMenuLink.get())) {
|
document->cancel();
|
||||||
lnkDocument->document()->cancel();
|
|
||||||
} else if (auto item = App::contextItem()) {
|
|
||||||
if (auto media = item->getMedia()) {
|
|
||||||
if (auto doc = media->getDocument()) {
|
|
||||||
doc->cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::showContextInFolder() {
|
void ListWidget::showContextInFolder(not_null<DocumentData*> document) {
|
||||||
QString filepath;
|
const auto filepath = document->filepath(
|
||||||
if (auto lnkDocument = dynamic_cast<DocumentClickHandler*>(_contextMenuLink.get())) {
|
DocumentData::FilePathResolveChecked);
|
||||||
filepath = lnkDocument->document()->filepath(DocumentData::FilePathResolveChecked);
|
|
||||||
} else if (auto item = App::contextItem()) {
|
|
||||||
if (auto media = item->getMedia()) {
|
|
||||||
if (auto doc = media->getDocument()) {
|
|
||||||
filepath = doc->filepath(DocumentData::FilePathResolveChecked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!filepath.isEmpty()) {
|
if (!filepath.isEmpty()) {
|
||||||
File::ShowInFolder(filepath);
|
File::ShowInFolder(filepath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::openContextGif() {
|
void ListWidget::openContextGif(FullMsgId itemId) {
|
||||||
if (auto item = App::contextItem()) {
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
if (auto media = item->getMedia()) {
|
if (auto media = item->getMedia()) {
|
||||||
if (auto document = media->getDocument()) {
|
if (auto document = media->getDocument()) {
|
||||||
Messenger::Instance().showDocument(document, item);
|
Messenger::Instance().showDocument(document, item);
|
||||||
|
@ -952,16 +949,20 @@ void ListWidget::openContextGif() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::copyContextText() {
|
void ListWidget::copyContextText(FullMsgId itemId) {
|
||||||
auto item = App::contextItem();
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
if (!item || (item->getMedia() && item->getMedia()->type() == MediaTypeSticker)) {
|
if (const auto media = item->getMedia()) {
|
||||||
return;
|
if (media->type() == MediaTypeSticker) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setToClipboard(item->selectedText(FullSelection));
|
||||||
}
|
}
|
||||||
|
|
||||||
setToClipboard(item->selectedText(FullSelection));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::setToClipboard(const TextWithEntities &forClipboard, QClipboard::Mode mode) {
|
void ListWidget::setToClipboard(
|
||||||
|
const TextWithEntities &forClipboard,
|
||||||
|
QClipboard::Mode mode) {
|
||||||
if (auto data = MimeDataFromTextWithEntities(forClipboard)) {
|
if (auto data = MimeDataFromTextWithEntities(forClipboard)) {
|
||||||
QApplication::clipboard()->setMimeData(data.release(), mode);
|
QApplication::clipboard()->setMimeData(data.release(), mode);
|
||||||
}
|
}
|
||||||
|
@ -996,8 +997,8 @@ void ListWidget::enterEventHook(QEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::leaveEventHook(QEvent *e) {
|
void ListWidget::leaveEventHook(QEvent *e) {
|
||||||
if (auto item = App::hoveredItem()) {
|
if (const auto view = App::hoveredItem()) {
|
||||||
repaintItem(viewForItem(item));
|
repaintItem(view);
|
||||||
App::hoveredItem(nullptr);
|
App::hoveredItem(nullptr);
|
||||||
}
|
}
|
||||||
ClickHandler::clearActive();
|
ClickHandler::clearActive();
|
||||||
|
@ -1015,13 +1016,13 @@ void ListWidget::mouseActionStart(const QPoint &screenPos, Qt::MouseButton butto
|
||||||
|
|
||||||
ClickHandler::pressed();
|
ClickHandler::pressed();
|
||||||
if (App::pressedItem() != App::hoveredItem()) {
|
if (App::pressedItem() != App::hoveredItem()) {
|
||||||
repaintItem(viewForItem(App::pressedItem()));
|
repaintItem(App::pressedItem());
|
||||||
App::pressedItem(App::hoveredItem());
|
App::pressedItem(App::hoveredItem());
|
||||||
repaintItem(viewForItem(App::pressedItem()));
|
repaintItem(App::pressedItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
_mouseAction = MouseAction::None;
|
_mouseAction = MouseAction::None;
|
||||||
_mouseActionItem = viewForItem(App::mousedItem());
|
_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);
|
||||||
|
@ -1102,8 +1103,8 @@ void ListWidget::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton butt
|
||||||
if (_mouseAction == MouseAction::Dragging) {
|
if (_mouseAction == MouseAction::Dragging) {
|
||||||
activated = nullptr;
|
activated = nullptr;
|
||||||
}
|
}
|
||||||
if (App::pressedItem()) {
|
if (const auto view = App::pressedItem()) {
|
||||||
repaintItem(viewForItem(App::pressedItem()));
|
repaintItem(view);
|
||||||
App::pressedItem(nullptr);
|
App::pressedItem(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1144,23 +1145,25 @@ void ListWidget::updateSelected() {
|
||||||
const auto view = strictFindItemByY(point.y());
|
const auto view = strictFindItemByY(point.y());
|
||||||
const auto item = view ? view->data().get() : nullptr;
|
const auto item = view ? view->data().get() : nullptr;
|
||||||
if (view) {
|
if (view) {
|
||||||
App::mousedItem(item);
|
App::mousedItem(view);
|
||||||
itemPoint = mapPointToItem(point, view);
|
itemPoint = mapPointToItem(point, view);
|
||||||
if (item->hasPoint(itemPoint)) {
|
if (item->hasPoint(itemPoint)) {
|
||||||
if (App::hoveredItem() != item) {
|
if (App::hoveredItem() != view) {
|
||||||
repaintItem(viewForItem(App::hoveredItem()));
|
repaintItem(App::hoveredItem());
|
||||||
App::hoveredItem(item);
|
App::hoveredItem(view);
|
||||||
repaintItem(view);
|
repaintItem(view);
|
||||||
}
|
}
|
||||||
} else if (App::hoveredItem()) {
|
} else if (const auto view = App::hoveredItem()) {
|
||||||
repaintItem(viewForItem(App::hoveredItem()));
|
repaintItem(view);
|
||||||
App::hoveredItem(nullptr);
|
App::hoveredItem(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryTextState dragState;
|
HistoryTextState dragState;
|
||||||
ClickHandlerHost *lnkhost = nullptr;
|
ClickHandlerHost *lnkhost = nullptr;
|
||||||
auto selectingText = (view == _mouseActionItem && item == App::hoveredItem() && _selectedItem);
|
auto selectingText = _selectedItem
|
||||||
|
&& (view == _mouseActionItem)
|
||||||
|
&& (view == App::hoveredItem());
|
||||||
if (view) {
|
if (view) {
|
||||||
if (view != _mouseActionItem || (itemPoint - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
|
if (view != _mouseActionItem || (itemPoint - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
|
||||||
if (_mouseAction == MouseAction::PrepareDrag) {
|
if (_mouseAction == MouseAction::PrepareDrag) {
|
||||||
|
@ -1246,14 +1249,9 @@ void ListWidget::updateSelected() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Voice message seek support.
|
// Voice message seek support.
|
||||||
if (auto pressedItem = App::pressedLinkItem()) {
|
if (const auto pressedView = App::pressedLinkItem()) {
|
||||||
if (!pressedItem->detached()) {
|
auto adjustedPoint = mapPointToItem(point, pressedView);
|
||||||
// #TODO seek support
|
pressedView->data()->updatePressed(adjustedPoint);
|
||||||
//if (pressedItem->history() == _history) {
|
|
||||||
// auto adjustedPoint = mapPointToItem(point, pressedItem);
|
|
||||||
// pressedItem->updatePressed(adjustedPoint);
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (_mouseAction == MouseAction::Selecting) {
|
//if (_mouseAction == MouseAction::Selecting) {
|
||||||
|
|
|
@ -160,12 +160,12 @@ private:
|
||||||
void savePhotoToFile(PhotoData *photo);
|
void savePhotoToFile(PhotoData *photo);
|
||||||
void saveDocumentToFile(DocumentData *document);
|
void saveDocumentToFile(DocumentData *document);
|
||||||
void copyContextImage(PhotoData *photo);
|
void copyContextImage(PhotoData *photo);
|
||||||
void showStickerPackInfo();
|
void showStickerPackInfo(not_null<DocumentData*> document);
|
||||||
void copyContextUrl();
|
void copyContextUrl();
|
||||||
void cancelContextDownload();
|
void cancelContextDownload(not_null<DocumentData*> document);
|
||||||
void showContextInFolder();
|
void showContextInFolder(not_null<DocumentData*> document);
|
||||||
void openContextGif();
|
void openContextGif(FullMsgId itemId);
|
||||||
void copyContextText();
|
void copyContextText(FullMsgId itemId);
|
||||||
void copySelectedText();
|
void copySelectedText();
|
||||||
TextWithEntities getSelectedText() const;
|
TextWithEntities getSelectedText() const;
|
||||||
void setToClipboard(
|
void setToClipboard(
|
||||||
|
@ -254,8 +254,7 @@ private:
|
||||||
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;
|
||||||
|
|
||||||
// context menu
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
Ui::PopupMenu *_menu = nullptr;
|
|
||||||
|
|
||||||
QPoint _trippleClickPoint;
|
QPoint _trippleClickPoint;
|
||||||
base::Timer _trippleClickTimer;
|
base::Timer _trippleClickTimer;
|
||||||
|
|
|
@ -14,12 +14,56 @@ Message::Message(not_null<HistoryItem*> data, Context context)
|
||||||
, _context(context) {
|
, _context(context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgId Message::id() const {
|
|
||||||
return _data->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
not_null<HistoryItem*> Message::data() const {
|
not_null<HistoryItem*> Message::data() const {
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Message::attachToBlock(not_null<HistoryBlock*> block, int index) {
|
||||||
|
Expects(!_data->isLogEntry());
|
||||||
|
Expects(_block == nullptr);
|
||||||
|
Expects(_indexInBlock < 0);
|
||||||
|
Expects(index >= 0);
|
||||||
|
|
||||||
|
_block = block;
|
||||||
|
_indexInBlock = index;
|
||||||
|
_data->setMainView(this);
|
||||||
|
_data->setPendingResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Message::removeFromBlock() {
|
||||||
|
Expects(_block != nullptr);
|
||||||
|
|
||||||
|
_block->remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Message *Message::previousInBlocks() const {
|
||||||
|
if (_block && _indexInBlock >= 0) {
|
||||||
|
if (_indexInBlock > 0) {
|
||||||
|
return _block->messages[_indexInBlock - 1].get();
|
||||||
|
}
|
||||||
|
if (auto previous = _block->previousBlock()) {
|
||||||
|
Assert(!previous->messages.empty());
|
||||||
|
return previous->messages.back().get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Message *Message::nextInBlocks() const {
|
||||||
|
if (_block && _indexInBlock >= 0) {
|
||||||
|
if (_indexInBlock + 1 < _block->messages.size()) {
|
||||||
|
return _block->messages[_indexInBlock + 1].get();
|
||||||
|
}
|
||||||
|
if (auto next = _block->nextBlock()) {
|
||||||
|
Assert(!next->messages.empty());
|
||||||
|
return next->messages.front().get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::~Message() {
|
||||||
|
App::messageViewDestroyed(this);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
@ -23,7 +23,6 @@ class Message
|
||||||
public:
|
public:
|
||||||
Message(not_null<HistoryItem*> data, Context context);
|
Message(not_null<HistoryItem*> data, Context context);
|
||||||
|
|
||||||
MsgId id() const;
|
|
||||||
not_null<HistoryItem*> data() const;
|
not_null<HistoryItem*> data() const;
|
||||||
|
|
||||||
int y() const {
|
int y() const {
|
||||||
|
@ -33,11 +32,39 @@ public:
|
||||||
_y = y;
|
_y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HistoryBlock *block() {
|
||||||
|
return _block;
|
||||||
|
}
|
||||||
|
const HistoryBlock *block() const {
|
||||||
|
return _block;
|
||||||
|
}
|
||||||
|
void attachToBlock(not_null<HistoryBlock*> block, int index);
|
||||||
|
void removeFromBlock();
|
||||||
|
void setIndexInBlock(int index) {
|
||||||
|
Expects(_block != nullptr);
|
||||||
|
Expects(index >= 0);
|
||||||
|
|
||||||
|
_indexInBlock = index;
|
||||||
|
}
|
||||||
|
int indexInBlock() const {
|
||||||
|
Expects((_indexInBlock >= 0) == (_block != nullptr));
|
||||||
|
Expects((_block == nullptr) || (_block->messages[_indexInBlock].get() == this));
|
||||||
|
|
||||||
|
return _indexInBlock;
|
||||||
|
}
|
||||||
|
Message *previousInBlocks() const;
|
||||||
|
Message *nextInBlocks() const;
|
||||||
|
|
||||||
|
~Message();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const not_null<HistoryItem*> _data;
|
const not_null<HistoryItem*> _data;
|
||||||
int _y = 0;
|
int _y = 0;
|
||||||
Context _context;
|
Context _context;
|
||||||
|
|
||||||
|
HistoryBlock *_block = nullptr;
|
||||||
|
int _indexInBlock = -1;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
@ -596,17 +596,19 @@ bool MainWidget::setForwardDraft(PeerId peerId, ForwardWhatMessages what) {
|
||||||
return _history->getSelectedItems();
|
return _history->getSelectedItems();
|
||||||
}
|
}
|
||||||
auto item = (HistoryItem*)nullptr;
|
auto item = (HistoryItem*)nullptr;
|
||||||
if (what == ForwardContextMessage) {
|
if (what == ForwardPressedMessage) {
|
||||||
item = App::contextItem();
|
item = App::pressedItem()
|
||||||
} else if (what == ForwardPressedMessage) {
|
? App::pressedItem()->data().get()
|
||||||
item = App::pressedItem();
|
: nullptr;
|
||||||
if (const auto group = item ? item->getFullGroup() : nullptr) {
|
if (const auto group = item ? item->getFullGroup() : nullptr) {
|
||||||
if (item->id > 0) {
|
if (item->id > 0) {
|
||||||
return Auth().data().groupToIds(group);
|
return Auth().data().groupToIds(group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (what == ForwardPressedLinkMessage) {
|
} else if (what == ForwardPressedLinkMessage) {
|
||||||
item = App::pressedLinkItem();
|
item = App::pressedLinkItem()
|
||||||
|
? App::pressedLinkItem()->data().get()
|
||||||
|
: nullptr;
|
||||||
}
|
}
|
||||||
if (item && item->toHistoryMessage() && item->id > 0) {
|
if (item && item->toHistoryMessage() && item->id > 0) {
|
||||||
return { 1, item->fullId() };
|
return { 1, item->fullId() };
|
||||||
|
@ -677,8 +679,7 @@ bool MainWidget::shareUrl(
|
||||||
void MainWidget::replyToItem(not_null<HistoryItem*> item) {
|
void MainWidget::replyToItem(not_null<HistoryItem*> item) {
|
||||||
if (_history->peer() == item->history()->peer
|
if (_history->peer() == item->history()->peer
|
||||||
|| _history->peer() == item->history()->peer->migrateTo()) {
|
|| _history->peer() == item->history()->peer->migrateTo()) {
|
||||||
App::contextItem(item);
|
_history->replyToMessage(item);
|
||||||
_history->onReplyToMessage();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -932,24 +933,20 @@ void MainWidget::showSendPathsLayer() {
|
||||||
hiderLayer(object_ptr<HistoryHider>(this));
|
hiderLayer(object_ptr<HistoryHider>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::deleteLayer(int selectedCount) {
|
void MainWidget::deleteLayer(MessageIdsList &&items) {
|
||||||
if (selectedCount) {
|
if (!items.empty()) {
|
||||||
auto selected = _history->getSelectedItems();
|
Ui::show(Box<DeleteMessagesBox>(std::move(items)));
|
||||||
if (!selected.empty()) {
|
}
|
||||||
Ui::show(Box<DeleteMessagesBox>(std::move(selected)));
|
}
|
||||||
}
|
|
||||||
} else if (const auto item = App::contextItem()) {
|
void MainWidget::deleteLayer(FullMsgId itemId) {
|
||||||
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
const auto suggestModerateActions = true;
|
const auto suggestModerateActions = true;
|
||||||
Ui::show(Box<DeleteMessagesBox>(item, suggestModerateActions));
|
Ui::show(Box<DeleteMessagesBox>(item, suggestModerateActions));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::cancelUploadLayer() {
|
void MainWidget::cancelUploadLayer(not_null<HistoryItem*> item) {
|
||||||
auto item = App::contextItem();
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto itemId = item->fullId();
|
const auto itemId = item->fullId();
|
||||||
Auth().uploader().pause(itemId);
|
Auth().uploader().pause(itemId);
|
||||||
Ui::show(Box<ConfirmBox>(lang(lng_selected_cancel_sure_this), lang(lng_selected_upload_stop), lang(lng_continue), base::lambda_guarded(this, [=] {
|
Ui::show(Box<ConfirmBox>(lang(lng_selected_cancel_sure_this), lang(lng_selected_upload_stop), lang(lng_continue), base::lambda_guarded(this, [=] {
|
||||||
|
@ -2111,7 +2108,7 @@ void MainWidget::updateBotKeyboard(History *h) {
|
||||||
_history->updateBotKeyboard(h);
|
_history->updateBotKeyboard(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::pushReplyReturn(HistoryItem *item) {
|
void MainWidget::pushReplyReturn(not_null<HistoryItem*> item) {
|
||||||
_history->pushReplyReturn(item);
|
_history->pushReplyReturn(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4931,7 +4928,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||||
const auto newId = d.vid.v;
|
const auto newId = d.vid.v;
|
||||||
if (const auto local = App::histItemById(fullId)) {
|
if (const auto local = App::histItemById(fullId)) {
|
||||||
const auto existing = App::histItemById(channel, newId);
|
const auto existing = App::histItemById(channel, newId);
|
||||||
if (existing && local->detached()) {
|
if (existing && !local->mainView()) {
|
||||||
const auto history = local->history();
|
const auto history = local->history();
|
||||||
const auto wasLast = (history->lastMsg == local);
|
const auto wasLast = (history->lastMsg == local);
|
||||||
local->destroy();
|
local->destroy();
|
||||||
|
|
|
@ -168,8 +168,9 @@ public:
|
||||||
|
|
||||||
void showForwardLayer(MessageIdsList &&items);
|
void showForwardLayer(MessageIdsList &&items);
|
||||||
void showSendPathsLayer();
|
void showSendPathsLayer();
|
||||||
void deleteLayer(int selectedCount = 0); // 0 - context item
|
void deleteLayer(MessageIdsList &&items);
|
||||||
void cancelUploadLayer();
|
void deleteLayer(FullMsgId itemId);
|
||||||
|
void cancelUploadLayer(not_null<HistoryItem*> item);
|
||||||
void shareUrlLayer(const QString &url, const QString &text);
|
void shareUrlLayer(const QString &url, const QString &text);
|
||||||
void inlineSwitchLayer(const QString &botAndQuery);
|
void inlineSwitchLayer(const QString &botAndQuery);
|
||||||
void hiderLayer(object_ptr<HistoryHider> h);
|
void hiderLayer(object_ptr<HistoryHider> h);
|
||||||
|
@ -272,7 +273,7 @@ public:
|
||||||
void messageDataReceived(ChannelData *channel, MsgId msgId);
|
void messageDataReceived(ChannelData *channel, MsgId msgId);
|
||||||
void updateBotKeyboard(History *h);
|
void updateBotKeyboard(History *h);
|
||||||
|
|
||||||
void pushReplyReturn(HistoryItem *item);
|
void pushReplyReturn(not_null<HistoryItem*> item);
|
||||||
|
|
||||||
void cancelForwarding(not_null<History*> history);
|
void cancelForwarding(not_null<History*> history);
|
||||||
void finishForwarding(not_null<History*> history);
|
void finishForwarding(not_null<History*> history);
|
||||||
|
|
|
@ -1003,8 +1003,10 @@ void MediaView::onForward() {
|
||||||
|
|
||||||
void MediaView::onDelete() {
|
void MediaView::onDelete() {
|
||||||
close();
|
close();
|
||||||
auto deletingPeerPhoto = [this]() {
|
const auto deletingPeerPhoto = [this] {
|
||||||
if (!_msgid) return true;
|
if (!_msgid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (_photo && _history) {
|
if (_photo && _history) {
|
||||||
if (_history->peer->userpicPhotoId() == _photo->id) {
|
if (_history->peer->userpicPhotoId() == _photo->id) {
|
||||||
return _firstOpenedPeerPhoto;
|
return _firstOpenedPeerPhoto;
|
||||||
|
@ -1015,9 +1017,8 @@ void MediaView::onDelete() {
|
||||||
|
|
||||||
if (deletingPeerPhoto()) {
|
if (deletingPeerPhoto()) {
|
||||||
App::main()->deletePhotoLayer(_photo);
|
App::main()->deletePhotoLayer(_photo);
|
||||||
} else if (auto item = App::histItemById(_msgid)) {
|
} else {
|
||||||
App::contextItem(item);
|
App::main()->deleteLayer(_msgid);
|
||||||
App::main()->deleteLayer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,8 @@ ItemBase::ItemBase(not_null<HistoryItem*> parent) : _parent(parent) {
|
||||||
void ItemBase::clickHandlerActiveChanged(
|
void ItemBase::clickHandlerActiveChanged(
|
||||||
const ClickHandlerPtr &action,
|
const ClickHandlerPtr &action,
|
||||||
bool active) {
|
bool active) {
|
||||||
App::hoveredLinkItem(active ? _parent.get() : nullptr);
|
// #TODO hoveredLinkItem
|
||||||
|
// App::hoveredLinkItem(active ? _parent.get() : nullptr);
|
||||||
Auth().data().requestItemRepaint(_parent);
|
Auth().data().requestItemRepaint(_parent);
|
||||||
if (_check) {
|
if (_check) {
|
||||||
_check->setActive(active);
|
_check->setActive(active);
|
||||||
|
@ -130,7 +131,8 @@ void ItemBase::clickHandlerActiveChanged(
|
||||||
void ItemBase::clickHandlerPressedChanged(
|
void ItemBase::clickHandlerPressedChanged(
|
||||||
const ClickHandlerPtr &action,
|
const ClickHandlerPtr &action,
|
||||||
bool pressed) {
|
bool pressed) {
|
||||||
App::pressedLinkItem(pressed ? _parent.get() : nullptr);
|
// #TODO pressedLinkItem
|
||||||
|
// App::pressedLinkItem(pressed ? _parent.get() : nullptr);
|
||||||
Auth().data().requestItemRepaint(_parent);
|
Auth().data().requestItemRepaint(_parent);
|
||||||
if (_check) {
|
if (_check) {
|
||||||
_check->setPressed(pressed);
|
_check->setPressed(pressed);
|
||||||
|
@ -172,18 +174,25 @@ ItemBase::~ItemBase() = default;
|
||||||
|
|
||||||
void RadialProgressItem::setDocumentLinks(
|
void RadialProgressItem::setDocumentLinks(
|
||||||
not_null<DocumentData*> document) {
|
not_null<DocumentData*> document) {
|
||||||
auto createSaveHandler = [](
|
const auto context = parent()->fullId();
|
||||||
not_null<DocumentData*> document
|
const auto createSaveHandler = [&]() -> ClickHandlerPtr {
|
||||||
) -> ClickHandlerPtr {
|
|
||||||
if (document->isVoiceMessage()) {
|
if (document->isVoiceMessage()) {
|
||||||
return std::make_shared<DocumentOpenClickHandler>(document);
|
return std::make_shared<DocumentOpenClickHandler>(
|
||||||
|
document,
|
||||||
|
context);
|
||||||
}
|
}
|
||||||
return std::make_shared<DocumentSaveClickHandler>(document);
|
return std::make_shared<DocumentSaveClickHandler>(
|
||||||
|
document,
|
||||||
|
context);
|
||||||
};
|
};
|
||||||
setLinks(
|
setLinks(
|
||||||
std::make_shared<DocumentOpenClickHandler>(document),
|
std::make_shared<DocumentOpenClickHandler>(
|
||||||
createSaveHandler(document),
|
document,
|
||||||
std::make_shared<DocumentCancelClickHandler>(document));
|
context),
|
||||||
|
createSaveHandler(),
|
||||||
|
std::make_shared<DocumentCancelClickHandler>(
|
||||||
|
document,
|
||||||
|
context));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RadialProgressItem::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
void RadialProgressItem::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
||||||
|
@ -539,7 +548,7 @@ Voice::Voice(
|
||||||
const style::OverviewFileLayout &st)
|
const style::OverviewFileLayout &st)
|
||||||
: RadialProgressItem(parent)
|
: RadialProgressItem(parent)
|
||||||
, _data(voice)
|
, _data(voice)
|
||||||
, _namel(std::make_shared<DocumentOpenClickHandler>(_data))
|
, _namel(std::make_shared<DocumentOpenClickHandler>(_data, parent->fullId()))
|
||||||
, _st(st) {
|
, _st(st) {
|
||||||
AddComponents(Info::Bit());
|
AddComponents(Info::Bit());
|
||||||
|
|
||||||
|
@ -784,7 +793,7 @@ Document::Document(
|
||||||
: RadialProgressItem(parent)
|
: RadialProgressItem(parent)
|
||||||
, _data(document)
|
, _data(document)
|
||||||
, _msgl(goToMessageClickHandler(parent))
|
, _msgl(goToMessageClickHandler(parent))
|
||||||
, _namel(std::make_shared<DocumentOpenClickHandler>(_data))
|
, _namel(std::make_shared<DocumentOpenClickHandler>(_data, parent->fullId()))
|
||||||
, _st(st)
|
, _st(st)
|
||||||
, _date(langDateTime(date(_data->date)))
|
, _date(langDateTime(date(_data->date)))
|
||||||
, _datew(st::normalFont->width(_date))
|
, _datew(st::normalFont->width(_date))
|
||||||
|
@ -1205,7 +1214,9 @@ Link::Link(
|
||||||
if (_page) {
|
if (_page) {
|
||||||
mainUrl = _page->url;
|
mainUrl = _page->url;
|
||||||
if (_page->document) {
|
if (_page->document) {
|
||||||
_photol = std::make_shared<DocumentOpenClickHandler>(_page->document);
|
_photol = std::make_shared<DocumentOpenClickHandler>(
|
||||||
|
_page->document,
|
||||||
|
parent->fullId());
|
||||||
} else if (_page->photo) {
|
} else if (_page->photo) {
|
||||||
if (_page->type == WebPageProfile || _page->type == WebPageVideo) {
|
if (_page->type == WebPageProfile || _page->type == WebPageVideo) {
|
||||||
_photol = std::make_shared<UrlClickHandler>(_page->url);
|
_photol = std::make_shared<UrlClickHandler>(_page->url);
|
||||||
|
|
Loading…
Reference in New Issue