diff --git a/Telegram/SourceFiles/ayu/data/ayu_database.cpp b/Telegram/SourceFiles/ayu/data/ayu_database.cpp index 541d5e5be..aba6ede3d 100644 --- a/Telegram/SourceFiles/ayu/data/ayu_database.cpp +++ b/Telegram/SourceFiles/ayu/data/ayu_database.cpp @@ -234,10 +234,12 @@ void addDeletedMessage(const DeletedMessage &message) { } } -std::vector getDeletedMessages(ID dialogId, ID minId, ID maxId, int totalLimit) { +std::vector getDeletedMessages(ID userId, ID dialogId, ID topicId, ID minId, ID maxId, int totalLimit) { return storage.get_all( where( + column(&DeletedMessage::userId) == userId and column(&DeletedMessage::dialogId) == dialogId and + (column(&DeletedMessage::topicId) == topicId or topicId == 0) and (column(&DeletedMessage::messageId) > minId or minId == 0) and (column(&DeletedMessage::messageId) < maxId or maxId == 0) ), @@ -246,11 +248,13 @@ std::vector getDeletedMessages(ID dialogId, ID minId, ID maxId, ); } -bool hasDeletedMessages(ID dialogId) { +bool hasDeletedMessages(ID userId, ID dialogId, ID topicId) { try { return storage.count( where( - column(&DeletedMessage::dialogId) == dialogId + column(&DeletedMessage::userId) == userId and + column(&DeletedMessage::dialogId) == dialogId and + (column(&DeletedMessage::topicId) == topicId or topicId == 0) ) ) > 0; } catch (std::exception &ex) { diff --git a/Telegram/SourceFiles/ayu/data/ayu_database.h b/Telegram/SourceFiles/ayu/data/ayu_database.h index f67bc4104..d78fa7d40 100644 --- a/Telegram/SourceFiles/ayu/data/ayu_database.h +++ b/Telegram/SourceFiles/ayu/data/ayu_database.h @@ -17,7 +17,7 @@ std::vector getEditedMessages(ID userId, ID dialogId, ID messageI bool hasRevisions(ID userId, ID dialogId, ID messageId); void addDeletedMessage(const DeletedMessage &message); -std::vector getDeletedMessages(ID dialogId, ID minId, ID maxId, int totalLimit); -bool hasDeletedMessages(ID dialogId); +std::vector getDeletedMessages(ID userId, ID dialogId, ID topicId, ID minId, ID maxId, int totalLimit); +bool hasDeletedMessages(ID userId, ID dialogId, ID topicId); } diff --git a/Telegram/SourceFiles/ayu/data/entities.h b/Telegram/SourceFiles/ayu/data/entities.h index c1f073089..06d4dee04 100644 --- a/Telegram/SourceFiles/ayu/data/entities.h +++ b/Telegram/SourceFiles/ayu/data/entities.h @@ -30,12 +30,14 @@ public: std::string fwdName; int fwdDate; std::string fwdPostAuthor; + std::string postAuthor; int replyFlags; int replyMessageId; ID replyPeerId; int replyTopId; bool replyForumTopic; std::vector replySerialized; + std::vector replyMarkupSerialized; int entityCreateDate; std::string text; std::vector textEntities; diff --git a/Telegram/SourceFiles/ayu/data/messages_storage.cpp b/Telegram/SourceFiles/ayu/data/messages_storage.cpp index 01c96ea45..8e9ab9fed 100644 --- a/Telegram/SourceFiles/ayu/data/messages_storage.cpp +++ b/Telegram/SourceFiles/ayu/data/messages_storage.cpp @@ -35,26 +35,42 @@ std::vector convertToBase(const std::vector &mes } void map(not_null item, AyuMessageBase &message) { - message.userId = item->history()->owner().session().userId().bare; + const ID userId = item->history()->owner().session().userId().bare & PeerId::kChatTypeMask; + + message.userId = userId; message.dialogId = getDialogIdFromPeer(item->history()->peer); - message.groupedId = item->groupId().value; - message.peerId = item->from()->id.value; // todo: ??? - message.fromId = item->from()->id.value; - if (auto topic = item->history()->asTopic()) { - message.topicId = topic->rootId().bare; + message.groupedId = item->groupId().raw(); + message.peerId = item->history()->peer->id.value & PeerId::kChatTypeMask; + message.fromId = item->from()->id.value & PeerId::kChatTypeMask; + if (item->topic()) { + message.topicId = item->topicRootId().bare; } message.messageId = item->id.bare; message.date = item->date(); message.flags = AyuMapper::mapItemFlagsToMTPFlags(item); - if (auto edited = item->Get()) { + if (const auto edited = item->Get()) { message.editDate = edited->date; } else { message.editDate = base::unixtime::now(); } message.views = item->viewsCount(); - message.entityCreateDate = base::unixtime::now(); // todo: rework + message.fwdFlags = 0; + message.fwdFromId = 0; + // message.fwdName + // message.fwdPostAuthor + if (const auto msgsigned = item->Get()) { + message.postAuthor = msgsigned->author.toStdString(); + } + message.replyFlags = 0; + message.replyMessageId = 0; + message.replyPeerId = 0; + message.replyTopId = 0; + message.replyForumTopic = 0; + // message.replySerialized + // message.replyMarkupSerialized + message.entityCreateDate = base::unixtime::now(); auto serializedText = AyuMapper::serializeTextWithEntities(item); message.text = serializedText.first; @@ -62,12 +78,12 @@ void map(not_null item, AyuMessageBase &message) { // todo: implement mapping message.mediaPath = "/"; + // message.hqThumbPath message.documentType = DOCUMENT_TYPE_NONE; - - // message.documentSerialized; - // message.thumbsSerialized; - // message.documentAttributesSerialized; - // message.mimeType; + // message.documentSerialized + // message.thumbsSerialized + // message.documentAttributesSerialized + // message.mimeType } void addEditedMessage(HistoryMessageEdition &edition, not_null item) { @@ -82,17 +98,17 @@ void addEditedMessage(HistoryMessageEdition &edition, not_null ite } std::vector getEditedMessages(not_null item, ID minId, ID maxId, int totalLimit) { - auto userId = item->history()->owner().session().userId().bare; - auto dialogId = getDialogIdFromPeer(item->history()->peer); - auto msgId = item->id.bare; + const ID userId = item->history()->owner().session().userId().bare & PeerId::kChatTypeMask; + const auto dialogId = getDialogIdFromPeer(item->history()->peer); + const auto msgId = item->id.bare; return convertToBase(AyuDatabase::getEditedMessages(userId, dialogId, msgId, minId, maxId, totalLimit)); } bool hasRevisions(not_null item) { - auto userId = item->history()->owner().session().userId().bare; - auto dialogId = getDialogIdFromPeer(item->history()->peer); - auto msgId = item->id.bare; + const ID userId = item->history()->owner().session().userId().bare & PeerId::kChatTypeMask; + const auto dialogId = getDialogIdFromPeer(item->history()->peer); + const auto msgId = item->id.bare; return AyuDatabase::hasRevisions(userId, dialogId, msgId); } @@ -108,12 +124,16 @@ void addDeletedMessage(not_null item) { AyuDatabase::addDeletedMessage(message); } -std::vector getDeletedMessages(not_null peer, ID minId, ID maxId, int totalLimit) { - return convertToBase(AyuDatabase::getDeletedMessages(getDialogIdFromPeer(peer), minId, maxId, totalLimit)); +std::vector +getDeletedMessages(not_null peer, ID topicId, ID minId, ID maxId, int totalLimit) { + const ID userId = peer->session().userId().bare & PeerId::kChatTypeMask; + return convertToBase( + AyuDatabase::getDeletedMessages(userId, getDialogIdFromPeer(peer), topicId, minId, maxId, totalLimit)); } -bool hasDeletedMessages(not_null peer) { - return AyuDatabase::hasDeletedMessages(getDialogIdFromPeer(peer)); +bool hasDeletedMessages(not_null peer, ID topicId) { + const ID userId = peer->session().userId().bare & PeerId::kChatTypeMask; + return AyuDatabase::hasDeletedMessages(userId, getDialogIdFromPeer(peer), topicId); } } diff --git a/Telegram/SourceFiles/ayu/data/messages_storage.h b/Telegram/SourceFiles/ayu/data/messages_storage.h index 9c85e2592..dd04afb3d 100644 --- a/Telegram/SourceFiles/ayu/data/messages_storage.h +++ b/Telegram/SourceFiles/ayu/data/messages_storage.h @@ -17,7 +17,7 @@ std::vector getEditedMessages(not_null item, ID mi bool hasRevisions(not_null item); void addDeletedMessage(not_null item); -std::vector getDeletedMessages(not_null peer, ID minId, ID maxId, int totalLimit); -bool hasDeletedMessages(not_null peer); +std::vector getDeletedMessages(not_null peer, ID topicId, ID minId, ID maxId, int totalLimit); +bool hasDeletedMessages(not_null peer, ID topicId); } diff --git a/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.cpp b/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.cpp index 7e3027019..f2353b37c 100644 --- a/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.cpp +++ b/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.cpp @@ -6,6 +6,7 @@ // Copyright @Radolyn, 2024 #include "ayu/ui/context_menu/context_menu.h" +#include "apiwrap.h" #include "lang_auto.h" #include "mainwidget.h" #include "mainwindow.h" @@ -26,6 +27,11 @@ #include "ayu/ui/message_history/history_section.h" #include "ayu/utils/telegram_helpers.h" #include "base/unixtime.h" +#include "data/data_channel.h" +#include "data/data_user.h" +#include "data/data_chat.h" +#include "data/data_forum_topic.h" +#include "data/data_session.h" #include "history/view/history_view_context_menu.h" #include "history/view/history_view_element.h" #include "window/window_session_controller.h" @@ -37,14 +43,17 @@ bool needToShowItem(int state) { } void AddDeletedMessagesActions(PeerData *peerData, + Data::Thread *thread, not_null sessionController, - const Dialogs::EntryState &entryState, const Window::PeerMenuCallback &addCallback) { if (!peerData) { return; } - const auto has = AyuMessages::hasDeletedMessages(peerData); + const auto topic = peerData->isForum() ? thread->asTopic() : nullptr; + const auto topicId = topic ? topic->rootId().bare : 0; + + const auto has = AyuMessages::hasDeletedMessages(peerData, topicId); if (!has) { return; } @@ -53,11 +62,91 @@ void AddDeletedMessagesActions(PeerData *peerData, [=] { sessionController->session().tryResolveWindow() - ->showSection(std::make_shared(peerData)); + ->showSection(std::make_shared(peerData, nullptr, topicId)); }, &st::menuIconArchive); } +void AddJumpToBeginningAction(PeerData *peerData, + Data::Thread *thread, + not_null sessionController, + const Window::PeerMenuCallback &addCallback) { + const auto user = peerData->asUser(); + const auto group = peerData->isChat() ? peerData->asChat() : nullptr; + const auto chat = peerData->isMegagroup() + ? peerData->asMegagroup() + : peerData->isChannel() + ? peerData->asChannel() + : nullptr; + const auto topic = peerData->isForum() ? thread->asTopic() : nullptr; + if (!user && !group && !chat && !topic) { + return; + } + if (topic && topic->creating()) { + return; + } + + const auto controller = sessionController; + const auto jumpToDate = [=](auto history, auto callback) + { + const auto weak = base::make_weak(controller); + controller->session().api().resolveJumpToDate( + history, + QDate(2013, 8, 1), + [=](not_null peer, MsgId id) + { + if (const auto strong = weak.get()) { + callback(peer, id); + } + }); + }; + + const auto showPeerHistory = [=](auto peer, MsgId id) + { + controller->showPeerHistory( + peer, + Window::SectionShow::Way::Forward, + id); + }; + + const auto showTopic = [=](auto topic, MsgId id) + { + controller->showTopic( + topic, + id, + Window::SectionShow::Way::Forward); + }; + + addCallback( + tr::ayu_JumpToBeginning(tr::now), + [=] + { + if (user) { + jumpToDate(controller->session().data().history(user), showPeerHistory); + } else if (group && !chat) { + jumpToDate(controller->session().data().history(group), showPeerHistory); + } else if (chat && !topic) { + if (!chat->migrateFrom() && chat->availableMinId() == 1) { + showPeerHistory(chat, 1); + } else { + jumpToDate(controller->session().data().history(chat), showPeerHistory); + } + } else if (topic) { + if (topic->isGeneral()) { + showTopic(topic, 1); + } else { + jumpToDate( + topic, + [=](not_null, MsgId id) + { + showTopic(topic, id); + }); + } + } + }, + &st::ayuMenuIconToBeginning); +} + void AddHistoryAction(not_null menu, HistoryItem *item) { if (AyuMessages::hasRevisions(item)) { menu->addAction(tr::ayu_EditsHistoryMenuText(tr::now), @@ -65,7 +154,7 @@ void AddHistoryAction(not_null menu, HistoryItem *item) { { item->history()->session().tryResolveWindow() ->showSection( - std::make_shared(item->history()->peer, item)); + std::make_shared(item->history()->peer, item, 0)); }, &st::ayuEditsHistoryIcon); } @@ -332,7 +421,7 @@ void AddMessageDetailsAction(not_null menu, HistoryItem *item) { } void AddReadUntilAction(not_null menu, HistoryItem *item) { - if (item->isLocal() || item->isService() || item->out()) { + if (item->isLocal() || item->isService() || item->out() || item->isDeleted()) { return; } diff --git a/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.h b/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.h index 8c9e43f47..91bdad3e3 100644 --- a/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.h +++ b/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.h @@ -16,10 +16,15 @@ namespace AyuUi { bool needToShowItem(int state); void AddDeletedMessagesActions(PeerData *peerData, + Data::Thread *thread, not_null sessionController, - const Dialogs::EntryState &entryState, const Window::PeerMenuCallback &addCallback); +void AddJumpToBeginningAction(PeerData *peerData, + Data::Thread *thread, + not_null sessionController, + const Window::PeerMenuCallback &addCallback); + void AddHistoryAction(not_null menu, HistoryItem *item); void AddHideMessageAction(not_null menu, HistoryItem *item); void AddUserMessagesAction(not_null menu, HistoryItem *item); diff --git a/Telegram/SourceFiles/ayu/ui/message_history/history_inner.cpp b/Telegram/SourceFiles/ayu/ui/message_history/history_inner.cpp index b8aa21f6d..837f5487c 100644 --- a/Telegram/SourceFiles/ayu/ui/message_history/history_inner.cpp +++ b/Telegram/SourceFiles/ayu/ui/message_history/history_inner.cpp @@ -246,11 +246,13 @@ InnerWidget::InnerWidget( QWidget *parent, not_null controller, not_null peer, - HistoryItem *item) + HistoryItem *item, + ID topicId) : RpWidget(parent), _controller(controller), _peer(peer), _item(item), + _topicId(topicId), _history(peer->owner().history(peer)), _api(&_peer->session().mtp()), _pathGradient( @@ -668,7 +670,7 @@ void InnerWidget::preloadMore(Direction direction) { messages = AyuMessages::getEditedMessages(_item, minId, maxId, perPage); } else { // viewing deleted messages - messages = AyuMessages::getDeletedMessages(_peer, minId, maxId, perPage); + messages = AyuMessages::getDeletedMessages(_peer, _topicId, minId, maxId, perPage); } crl::on_main([=] diff --git a/Telegram/SourceFiles/ayu/ui/message_history/history_inner.h b/Telegram/SourceFiles/ayu/ui/message_history/history_inner.h index 694d10b74..8cd6bb4b8 100644 --- a/Telegram/SourceFiles/ayu/ui/message_history/history_inner.h +++ b/Telegram/SourceFiles/ayu/ui/message_history/history_inner.h @@ -52,7 +52,8 @@ public: QWidget *parent, not_null controller, not_null peer, - HistoryItem *item); + HistoryItem *item, + ID topicId); [[nodiscard]] Main::Session &session() const; @@ -251,6 +252,7 @@ private: const not_null _controller; const not_null _peer; HistoryItem *_item; + ID _topicId; const not_null _history; MTP::Sender _api; @@ -283,8 +285,8 @@ private: int _scrollDateLastItemTop = 0; // Up - max, Down - min. - uint64 _maxId = 0; - uint64 _minId = 0; + ID _maxId = 0; + ID _minId = 0; // Don't load anything until the memento was read. bool _upLoaded = true; diff --git a/Telegram/SourceFiles/ayu/ui/message_history/history_section.cpp b/Telegram/SourceFiles/ayu/ui/message_history/history_section.cpp index 2f53d8fda..6d8a59789 100644 --- a/Telegram/SourceFiles/ayu/ui/message_history/history_section.cpp +++ b/Telegram/SourceFiles/ayu/ui/message_history/history_section.cpp @@ -63,7 +63,7 @@ object_ptr SectionMemento::createWidget( if (column == Window::Column::Third) { return nullptr; } - auto result = object_ptr(parent, controller, _peer, _item); + auto result = object_ptr(parent, controller, _peer, _item, _topicId); result->setInternalState(geometry, this); return result; } @@ -142,12 +142,14 @@ Widget::Widget( QWidget *parent, not_null controller, not_null peer, - HistoryItem *item) + HistoryItem *item, + ID topicId) : Window::SectionWidget(parent, controller, rpl::single(peer)), _scroll(this, st::historyScroll, false), _fixedBar(this, controller, peer), _fixedBarShadow(this), - _item(item) { + _item(item), + _topicId(topicId) { _fixedBar->move(0, 0); _fixedBar->resizeToWidth(width()); _fixedBar->show(); @@ -161,7 +163,7 @@ Widget::Widget( }, lifetime()); - _inner = _scroll->setOwnedWidget(object_ptr(this, controller, peer, item)); + _inner = _scroll->setOwnedWidget(object_ptr(this, controller, peer, item, topicId)); _inner->scrollToSignal( ) | rpl::start_with_next([=](int top) { @@ -234,7 +236,7 @@ void Widget::setupShortcuts() { } std::shared_ptr Widget::createMemento() { - auto result = std::make_shared(channel(), _item); + auto result = std::make_shared(channel(), _item, _topicId); saveState(result.get()); return result; } diff --git a/Telegram/SourceFiles/ayu/ui/message_history/history_section.h b/Telegram/SourceFiles/ayu/ui/message_history/history_section.h index 45585e178..b4ffc24dc 100644 --- a/Telegram/SourceFiles/ayu/ui/message_history/history_section.h +++ b/Telegram/SourceFiles/ayu/ui/message_history/history_section.h @@ -35,7 +35,8 @@ public: QWidget *parent, not_null controller, not_null peer, - HistoryItem *item); + HistoryItem *item, + ID topicId); not_null channel() const; Dialogs::RowDescriptor activeChat() const override; @@ -78,6 +79,7 @@ private: object_ptr _fixedBar; object_ptr _fixedBarShadow; HistoryItem *_item; + ID _topicId; }; @@ -86,14 +88,10 @@ class SectionMemento : public Window::SectionMemento public: using Element = HistoryView::Element; - SectionMemento(not_null peer, not_null item) + SectionMemento(not_null peer, HistoryItem *item, ID topicId) : _peer(peer), - _item(item) { - } - - SectionMemento(not_null peer) - : _peer(peer), - _item(nullptr) { + _item(item), + _topicId(topicId) { } object_ptr createWidget( @@ -120,7 +118,7 @@ public: bool upLoaded, bool downLoaded) { _items = std::move(items); - _eventIds = std::move(eventIds); + _messageIds = std::move(eventIds); _upLoaded = upLoaded; _downLoaded = downLoaded; } @@ -130,7 +128,7 @@ public: } std::set takeMessageIds() { - return std::move(_eventIds); + return std::move(_messageIds); } bool upLoaded() const { @@ -144,9 +142,10 @@ public: private: not_null _peer; HistoryItem *_item; + ID _topicId; int _scrollTop = 0; std::vector _items; - std::set _eventIds; + std::set _messageIds; bool _upLoaded = false; bool _downLoaded = true; }; diff --git a/Telegram/SourceFiles/ayu/utils/ayu_mapper.cpp b/Telegram/SourceFiles/ayu/utils/ayu_mapper.cpp index b1bc2e2ea..4bf8783ab 100644 --- a/Telegram/SourceFiles/ayu/utils/ayu_mapper.cpp +++ b/Telegram/SourceFiles/ayu/utils/ayu_mapper.cpp @@ -12,6 +12,33 @@ namespace AyuMapper { +constexpr auto kMessageFlagUnread = 0x00000001; +constexpr auto kMessageFlagOut = 0x00000002; +constexpr auto kMessageFlagForwarded = 0x00000004; +constexpr auto kMessageFlagReply = 0x00000008; +constexpr auto kMessageFlagMention = 0x00000010; +constexpr auto kMessageFlagContentUnread = 0x00000020; +constexpr auto kMessageFlagHasMarkup = 0x00000040; +constexpr auto kMessageFlagHasEntities = 0x00000080; +constexpr auto kMessageFlagHasFromId = 0x00000100; +constexpr auto kMessageFlagHasMedia = 0x00000200; +constexpr auto kMessageFlagHasViews = 0x00000400; +constexpr auto kMessageFlagHasBotId = 0x00000800; +constexpr auto kMessageFlagIsSilent = 0x00001000; +constexpr auto kMessageFlagIsPost = 0x00004000; +constexpr auto kMessageFlagEdited = 0x00008000; +constexpr auto kMessageFlagHasPostAuthor = 0x00010000; +constexpr auto kMessageFlagIsGrouped = 0x00020000; +constexpr auto kMessageFlagFromScheduled = 0x00040000; +constexpr auto kMessageFlagHasReactions = 0x00100000; +constexpr auto kMessageFlagHideEdit = 0x00200000; +constexpr auto kMessageFlagRestricted = 0x00400000; +constexpr auto kMessageFlagHasReplies = 0x00800000; +constexpr auto kMessageFlagIsPinned = 0x01000000; +constexpr auto kMessageFlagHasTTL = 0x02000000; +constexpr auto kMessageFlagInvertMedia = 0x08000000; +constexpr auto kMessageFlagHasSavedPeer = 0x10000000; + std::pair> serializeTextWithEntities(not_null item) { if (item->emptyText()) { return std::make_pair("", std::vector()); @@ -27,64 +54,112 @@ int mapItemFlagsToMTPFlags(not_null item) { int flags = 0; const auto thread = item->topic() - ? (Data::Thread*) item->topic() + ? reinterpret_cast(item->topic()) : item->history(); - const auto unseen = item->unread(thread); - if (unseen) { - flags |= 1; + if (item->unread(thread)) { + flags |= kMessageFlagUnread; } if (item->out()) { - flags |= 2; + flags |= kMessageFlagOut; } - if (const auto reply = item->Get()) { - flags |= 4; + if (item->Get()) { + flags |= kMessageFlagForwarded; } - if (const auto reply = item->Get()) { - flags |= 8; + if (item->Get()) { + flags |= kMessageFlagReply; } if (item->mentionsMe()) { - flags |= 16; + flags |= kMessageFlagMention; } if (item->isUnreadMedia()) { - flags |= 32; + flags |= kMessageFlagContentUnread; + } + + if (item->definesReplyKeyboard()) { + flags |= kMessageFlagHasMarkup; + } + + if (!item->originalText().entities.empty()) { + flags |= kMessageFlagHasEntities; + } + + if (item->displayFrom()) { + // todo: maybe wrong + flags |= kMessageFlagHasFromId; + } + + if (item->media()) { + flags |= kMessageFlagHasMedia; + } + + if (item->hasViews()) { + flags |= kMessageFlagHasViews; + } + + if (item->viaBot()) { + flags |= kMessageFlagHasBotId; } if (item->isSilent()) { - flags |= 8192; + flags |= kMessageFlagIsSilent; } if (item->isPost()) { - flags |= 16384; + flags |= kMessageFlagIsPost; + } + + if (item->Get()) { + flags |= kMessageFlagEdited; + } + + if (item->Get()) { + flags |= kMessageFlagHasPostAuthor; + } + + if (item->groupId()) { + flags |= kMessageFlagIsGrouped; } if (item->isScheduled()) { - flags |= 262144; + flags |= kMessageFlagFromScheduled; } - // todo: legacy - // if (item->isLegacy()) { - // flags |= 524288; - // } + if (!item->reactions().empty()) { + flags |= kMessageFlagHasReactions; + } if (item->hideEditedBadge()) { - flags |= 2097152; + flags |= kMessageFlagHideEdit; + } + + if (item->hasPossibleRestrictions()) { + flags |= kMessageFlagRestricted; + } + + if (item->repliesCount() > 0) { + flags |= kMessageFlagHasReplies; } if (item->isPinned()) { - flags |= 16777216; + flags |= kMessageFlagIsPinned; } - if (item->forbidsForward()) { - flags |= 67108864; + if (item->ttlDestroyAt() > 0) { + flags |= kMessageFlagHasTTL; } - if (item->topic() && item->topicRootId() == item->id) { - flags |= 134217728; + if (item->invertMedia()) { + flags |= kMessageFlagInvertMedia; + } + + if (item->savedFromSender()) { + // todo: maybe wrong + flags |= kMessageFlagHasSavedPeer; } return flags; diff --git a/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp b/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp index 77faefd83..59f83aeeb 100644 --- a/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp +++ b/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp @@ -53,6 +53,7 @@ std::unordered_set ayugram_devs = { 778327202, // @sharapagorg 238292700, // @MaxPlays 1795176335, // @radolyn_services + 1752394339, // mouse }; // https://github.com/AyuGram/AyuGram4AX/blob/rewrite/TMessagesProj/src/main/java/com/exteragram/messenger/ExteraConfig.java @@ -97,10 +98,6 @@ Main::Session *getSession(ID userId) { return nullptr; } -bool accountExists(ID userId) { - return userId == 0 || getSession(userId) != nullptr; -} - void dispatchToMainThread(std::function callback, int delay) { auto timer = new QTimer(); timer->moveToThread(qApp->thread()); @@ -115,28 +112,8 @@ void dispatchToMainThread(std::function callback, int delay) { QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, delay)); } -not_null getHistoryFromDialogId(ID dialogId, Main::Session *session) { - if (dialogId > 0) { - return session->data().history(peerFromUser(dialogId)); - } - - auto history = session->data().history(peerFromChannel(abs(dialogId))); - if (history->folderKnown()) { - return history; - } - - return session->data().history(peerFromChat(abs(dialogId))); -} - ID getDialogIdFromPeer(not_null peer) { - auto peerId = peerIsUser(peer->id) - ? peerToUser(peer->id).bare - : peerIsChat(peer->id) - ? peerToChat(peer->id).bare - : peerIsChannel(peer->id) - ? peerToChannel(peer->id).bare - : peer->id.value; - + ID peerId = peer->id.value & PeerId::kChatTypeMask; if (peer->isChannel() || peer->isChat()) { peerId = -peerId; } @@ -145,13 +122,7 @@ ID getDialogIdFromPeer(not_null peer) { } ID getBareID(not_null peer) { - return peerIsUser(peer->id) - ? peerToUser(peer->id).bare - : peerIsChat(peer->id) - ? peerToChat(peer->id).bare - : peerIsChannel(peer->id) - ? peerToChannel(peer->id).bare - : peer->id.value; + return peer->id.value & PeerId::kChatTypeMask; } bool isAyuGramRelated(ID peerId) { @@ -596,7 +567,7 @@ void resolveUser(ID userId, const QString &username, Main::Session *session, con const auto peer = session->data().peerLoaded( peerFromMTP(data.vpeer())); if (const auto user = peer ? peer->asUser() : nullptr) { - if (user->id.value == userId) { + if ((user->id.value & PeerId::kChatTypeMask) == userId) { callback(normalized, user); return; } @@ -609,13 +580,13 @@ void resolveUser(ID userId, const QString &username, Main::Session *session, con }).send(); } -void searchUser(ID userId, Main::Session *session, bool searchUserFlag, bool cache, const Callback &callback) { +void searchUser(long long userId, Main::Session *session, bool searchUserFlag, const Callback &callback) { if (!session) { callback(QString(), nullptr); return; } - const auto botId = 1696868284; + constexpr auto botId = 1696868284; const auto bot = session->data().userLoaded(botId); if (!bot) { @@ -625,7 +596,7 @@ void searchUser(ID userId, Main::Session *session, bool searchUserFlag, bool cac session, [=](const QString &title, UserData *data) { - searchUser(userId, session, false, false, callback); + searchUser(userId, session, false, callback); }); } else { callback(QString(), nullptr); @@ -751,8 +722,7 @@ void searchById(ID userId, Main::Session *session, bool retry, const Callback &c return; } - const auto dataLoaded = session->data().userLoaded(userId); - if (dataLoaded) { + if (const auto dataLoaded = session->data().userLoaded(userId)) { callback(dataLoaded->username(), dataLoaded); return; } @@ -760,7 +730,6 @@ void searchById(ID userId, Main::Session *session, bool retry, const Callback &c searchUser(userId, session, true, - true, [=](const QString &title, UserData *data) { if (data && data->accessHash()) { diff --git a/Telegram/SourceFiles/ayu/utils/telegram_helpers.h b/Telegram/SourceFiles/ayu/utils/telegram_helpers.h index e416b1f93..47691c4fc 100644 --- a/Telegram/SourceFiles/ayu/utils/telegram_helpers.h +++ b/Telegram/SourceFiles/ayu/utils/telegram_helpers.h @@ -15,9 +15,7 @@ using Callback = Fn; Main::Session *getSession(ID userId); -bool accountExists(ID userId); void dispatchToMainThread(std::function callback, int delay = 0); -not_null getHistoryFromDialogId(ID dialogId, Main::Session *session); ID getDialogIdFromPeer(not_null peer); ID getBareID(not_null peer); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 63d3a2c1b..7211aa87e 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -2530,7 +2530,7 @@ void Session::checkTTLs() { return pair.second; }) | ranges::views::join; for (auto &item : toBeRemoved) { - item->setAyuHint(settings->deletedMark); + item->setDeleted(); } } else { while (!_ttlMessages.empty() && _ttlMessages.begin()->first <= now) { @@ -2560,7 +2560,7 @@ void Session::processMessagesDeleted( if (!settings->saveDeletedMessages) { i->second->destroy(); } else { - i->second->setAyuHint(settings->deletedMark); + i->second->setDeleted(); AyuMessages::addDeletedMessage(i->second); } @@ -2587,7 +2587,7 @@ void Session::processNonChannelMessagesDeleted(const QVector &data) { if (!settings->saveDeletedMessages) { item->destroy(); } else { - item->setAyuHint(settings->deletedMark); + item->setDeleted(); AyuMessages::addDeletedMessage(item); } diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 796a35049..57deefed1 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -131,6 +131,10 @@ int BinarySearchBlocksOrItems(const T &list, int edge) { } [[nodiscard]] bool CanSendReply(not_null item) { + if (item->isDeleted()) { + return false; + } + const auto peer = item->history()->peer; const auto topic = item->topic(); return topic @@ -664,7 +668,7 @@ void HistoryInner::setupSwipeReply() { } const auto item = view->data(); const auto canSendReply = CanSendReply(item); - const auto canReply = (canSendReply || item->allowsForward()); + const auto canReply = (canSendReply || item->allowsForward() && !item->isDeleted()); if (!canReply) { return true; } @@ -2188,7 +2192,9 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) { mouseActionCancel(); switch (HistoryView::CurrentQuickAction()) { case HistoryView::DoubleClickQuickAction::Reply: { - _widget->replyToMessage(view->data()); + if (!view->data()->isDeleted()) { + _widget->replyToMessage(view->data()); + } } break; case HistoryView::DoubleClickQuickAction::React: { toggleFavoriteReaction(view); @@ -2635,7 +2641,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { return; } const auto canSendReply = CanSendReply(item); - const auto canReply = canSendReply || item->allowsForward(); + const auto canReply = canSendReply || item->allowsForward() && !item->isDeleted(); if (canReply) { const auto selected = selectedQuote(item); auto text = selected @@ -2742,7 +2748,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { const auto itemId = item->fullId(); const auto blockSender = item->history()->peer->isRepliesChat(); if (isUponSelected != -2) { - if (item->allowsForward()) { + if (item->allowsForward() && !item->isDeleted()) { _menu->addAction(tr::lng_context_forward_msg(tr::now), [=] { forwardItem(itemId); }, &st::menuIconForward); @@ -2942,7 +2948,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { }, &st::menuIconSelect); } else if (item && ((isUponSelected != -2 && (canForward || canDelete)) || item->isRegular())) { if (isUponSelected != -2) { - if (canForward) { + if (canForward && !item->isDeleted()) { _menu->addAction(tr::lng_context_forward_msg(tr::now), [=] { forwardAsGroup(itemId); }, &st::menuIconForward); @@ -3828,7 +3834,7 @@ auto HistoryInner::getSelectionState() const if (selected.first->canDelete()) { ++result.canDeleteCount; } - if (selected.first->allowsForward()) { + if (selected.first->allowsForward() && !selected.first->isDeleted()) { ++result.canForwardCount; } } else if (selected.second.from != selected.second.to) { diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 930cbb8e0..050a4c9f8 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -2247,6 +2247,10 @@ void HistoryItem::setRealId(MsgId newId) { } bool HistoryItem::canPin() const { + if (_deleted) { + return false; + } + if (!isRegular() || isService()) { return false; } else if (const auto m = media(); m && m->call()) { @@ -2278,6 +2282,10 @@ bool HistoryItem::isTooOldForEdit(TimeId now) const { } bool HistoryItem::allowsEdit(TimeId now) const { + if (_deleted) { + return false; + } + return !isService() && canBeEdited() && !isTooOldForEdit(now) @@ -2287,6 +2295,10 @@ bool HistoryItem::allowsEdit(TimeId now) const { } bool HistoryItem::canBeEdited() const { + if (_deleted) { + return false; + } + if ((!isRegular() && !isScheduled() && !isBusinessShortcut()) || Has() || Has()) { @@ -2402,6 +2414,10 @@ bool HistoryItem::canDeleteForEveryone(TimeId now) const { } bool HistoryItem::suggestReport() const { + if (_deleted) { + return false; + } + if (out() || isService() || !isRegular()) { return false; } else if (const auto channel = _history->peer->asChannel()) { @@ -2413,6 +2429,10 @@ bool HistoryItem::suggestReport() const { } bool HistoryItem::suggestBanReport() const { + if (_deleted) { + return false; + } + const auto channel = _history->peer->asChannel(); if (!channel || !channel->canRestrictParticipant(from())) { return false; @@ -2421,6 +2441,10 @@ bool HistoryItem::suggestBanReport() const { } bool HistoryItem::suggestDeleteAllReport() const { + if (_deleted) { + return false; + } + auto channel = _history->peer->asChannel(); if (!channel || !channel->canDeleteMessages()) { return false; @@ -2571,6 +2595,10 @@ void HistoryItem::translationDone(LanguageId to, TextWithEntities result) { } bool HistoryItem::canReact() const { + if (_deleted) { + return false; + } + if (!isRegular() || isService()) { return false; } else if (const auto media = this->media()) { @@ -2961,6 +2989,17 @@ void HistoryItem::setPostAuthor(const QString &postAuthor) { history()->owner().requestItemResize(this); } +void HistoryItem::setDeleted() { + _deleted = true; + + const auto settings = &AyuSettings::getInstance(); + setAyuHint(settings->deletedMark); +} + +bool HistoryItem::isDeleted() const { + return _deleted; +} + void HistoryItem::setAyuHint(const QString &hint) { try { if (!(_flags & MessageFlag::HasPostAuthor)) { diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index 72c159e77..0667c44bf 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -415,6 +415,8 @@ public: MsgId replyToTop, bool isForumPost); void setPostAuthor(const QString &author); + void setDeleted(); + bool isDeleted() const; void setAyuHint(const QString &hint); void setRealId(MsgId newId); void incrementReplyToTopCounter(); @@ -671,6 +673,8 @@ private: std::unique_ptr _reactions; crl::time _reactionsLastRefreshed = 0; + bool _deleted = false; + TimeId _date = 0; TimeId _ttlDestroyAt = 0; int _boostsApplied = 0; diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 3bb70eec4..f139423b1 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -410,6 +410,10 @@ bool AddForwardMessageAction( const ContextMenuRequest &request, not_null list) { const auto item = request.item; + if (item->isDeleted()) { + return false; + } + if (!request.selectedItems.empty()) { return false; } else if (!item || !item->allowsForward()) { @@ -632,7 +636,7 @@ bool AddReplyToMessageAction( ? Data::CanSendAnything(topic) : Data::CanSendAnything(peer); const auto canReply = canSendReply || item->allowsForward(); - if (!canReply) { + if (!canReply || item->isDeleted()) { return false; } diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 8856d66c0..c636daa84 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -1295,7 +1295,7 @@ bool ListWidget::addToSelection( return false; } iterator->second.canDelete = item->canDelete(); - iterator->second.canForward = item->allowsForward(); + iterator->second.canForward = item->allowsForward() && !item->isDeleted(); iterator->second.canSendNow = item->allowsSendNow(); return true; } @@ -2653,7 +2653,9 @@ void ListWidget::mouseDoubleClickEvent(QMouseEvent *e) { mouseActionCancel(); switch (CurrentQuickAction()) { case DoubleClickQuickAction::Reply: { - replyToMessageRequestNotify({ _overElement->data()->fullId() }); + if (!_overElement->data()->isDeleted()) { + replyToMessageRequestNotify({ _overElement->data()->fullId() }); + } } break; case DoubleClickQuickAction::React: { toggleFavoriteReaction(_overElement); diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index a58533157..1ef0ce800 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -1330,15 +1330,19 @@ void TopBarWidget::updateMembersShowArea() { } bool TopBarWidget::showSelectedState() const { + const auto settings = &AyuSettings::getInstance(); + return (_selectedCount > 0) - && (_canDelete || _canForward || _canSendNow); + && (_canDelete || _canForward || _canSendNow || settings->showMessageShot); } void TopBarWidget::showSelected(SelectedState state) { + const auto settings = &AyuSettings::getInstance(); + auto canDelete = (state.count > 0 && state.count == state.canDeleteCount); auto canForward = (state.count > 0 && state.count == state.canForwardCount); auto canSendNow = (state.count > 0 && state.count == state.canSendNowCount); - auto count = (!canDelete && !canForward && !canSendNow) ? 0 : state.count; + auto count = (!canDelete && !canForward && !canSendNow && !settings->showMessageShot) ? 0 : state.count; if (_selectedCount == count && _canDelete == canDelete && _canForward == canForward diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 81dc3e9f8..cebf4c63d 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -314,7 +314,6 @@ private: void addVideoChat(); void addViewStatistics(); void addBoostChat(); - void addJumpToBeginning(); not_null _controller; Dialogs::EntryState _request; @@ -1092,80 +1091,6 @@ void Filler::addBoostChat() { } } -void Filler::addJumpToBeginning() { - const auto user = _peer->asUser(); - const auto group = _peer->isChat() ? _peer->asChat() : nullptr; - const auto chat = _peer->isMegagroup() ? _peer->asMegagroup() : _peer->isChannel() ? _peer->asChannel() : nullptr; - const auto topic = _peer->isForum() ? _thread->asTopic() : nullptr; - if (!user && !group && !chat && !topic) { - return; - } - if (topic && topic->creating()) { - return; - } - - const auto controller = _controller; - const auto jumpToDate = [=](auto history, auto callback) - { - const auto weak = base::make_weak(controller); - controller->session().api().resolveJumpToDate( - history, - QDate(2013, 8, 1), - [=](not_null peer, MsgId id) - { - if (const auto strong = weak.get()) { - callback(peer, id); - } - }); - }; - - const auto showPeerHistory = [=](auto peer, MsgId id) - { - controller->showPeerHistory( - peer, - SectionShow::Way::Forward, - id); - }; - - const auto showTopic = [=](auto topic, MsgId id) - { - controller->showTopic( - topic, - id, - SectionShow::Way::Forward); - }; - - _addAction( - tr::ayu_JumpToBeginning(tr::now), - [=] - { - if (user) { - jumpToDate(controller->session().data().history(user), showPeerHistory); - } else if (group && !chat) { - jumpToDate(controller->session().data().history(group), showPeerHistory); - } else if (chat && !topic) { - if (!chat->migrateFrom() && chat->availableMinId() == 1) { - showPeerHistory(chat, 1); - } else { - jumpToDate(controller->session().data().history(chat), showPeerHistory); - } - } else if (topic) { - if (topic->isGeneral()) { - showTopic(topic, 1); - } else { - jumpToDate( - topic, - [=](not_null, MsgId id) - { - showTopic(topic, id); - }); - } - } - }, - &st::ayuMenuIconToBeginning); -} - - void Filler::addViewStatistics() { if (const auto channel = _peer->asChannel()) { const auto controller = _controller; @@ -1494,7 +1419,7 @@ void Filler::fillContextMenuActions() { void Filler::fillHistoryActions() { addToggleMuteSubmenu(true); addInfo(); - addJumpToBeginning(); + AyuUi::AddJumpToBeginningAction(_peer, _thread, _controller, _addAction); addViewAsTopics(); addStoryArchive(); addSupportInfo(); @@ -1506,7 +1431,7 @@ void Filler::fillHistoryActions() { addExportChat(); addTranslate(); addReport(); - AyuUi::AddDeletedMessagesActions(_peer, _controller, _request, _addAction); + AyuUi::AddDeletedMessagesActions(_peer, _topic ? _topic : _thread, _controller, _addAction); addClearHistory(); addDeleteChat(); addLeaveChat(); @@ -1539,12 +1464,13 @@ void Filler::fillProfileActions() { void Filler::fillRepliesActions() { if (_topic) { addInfo(); - addJumpToBeginning(); + AyuUi::AddJumpToBeginningAction(_peer, _thread, _controller, _addAction); addManageTopic(); } addCreatePoll(); addToggleTopicClosed(); addDeleteTopic(); + AyuUi::AddDeletedMessagesActions(_peer, _topic ? _topic : _thread, _controller, _addAction); } void Filler::fillScheduledActions() {