mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-08 08:04:08 +02:00
Show reply info in scheduled forwards.
This commit is contained in:
parent
45857fe208
commit
5478a8c014
7 changed files with 144 additions and 12 deletions
|
@ -93,6 +93,11 @@ constexpr auto kRequestTimeLimit = 60 * crl::time(1000);
|
|||
|
||||
} // namespace
|
||||
|
||||
bool IsScheduledMsgId(MsgId id) {
|
||||
return (id > ServerMaxMsgId)
|
||||
&& (id < ServerMaxMsgId + ScheduledMsgIdsRange);
|
||||
}
|
||||
|
||||
ScheduledMessages::ScheduledMessages(not_null<Session*> owner)
|
||||
: _session(&owner->session())
|
||||
, _clearTimer([=] { clearOldRequests(); }) {
|
||||
|
|
|
@ -21,6 +21,8 @@ namespace Data {
|
|||
class Session;
|
||||
struct MessagesSlice;
|
||||
|
||||
[[nodiscard]] bool IsScheduledMsgId(MsgId id);
|
||||
|
||||
class ScheduledMessages final {
|
||||
public:
|
||||
explicit ScheduledMessages(not_null<Session*> owner);
|
||||
|
@ -32,6 +34,7 @@ public:
|
|||
[[nodiscard]] HistoryItem *lookupItem(PeerId peer, MsgId msg) const;
|
||||
[[nodiscard]] HistoryItem *lookupItem(FullMsgId itemId) const;
|
||||
[[nodiscard]] int count(not_null<History*> history) const;
|
||||
[[nodiscard]] MsgId localMessageId(MsgId remoteId) const;
|
||||
|
||||
void checkEntitiesAndUpdate(const MTPDmessage &data);
|
||||
void apply(const MTPDupdateNewScheduledMessage &update);
|
||||
|
@ -81,8 +84,6 @@ private:
|
|||
[[nodiscard]] uint64 countListHash(const List &list) const;
|
||||
void clearOldRequests();
|
||||
|
||||
[[nodiscard]] MsgId localMessageId(MsgId remoteId) const;
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
|
||||
base::Timer _clearTimer;
|
||||
|
|
|
@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_user.h"
|
||||
#include "data/data_web_page.h"
|
||||
#include "data/data_sponsored_messages.h"
|
||||
#include "data/data_scheduled_messages.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
@ -307,7 +308,10 @@ HistoryMessage::HistoryMessage(
|
|||
config.replyToPeer = 0;
|
||||
}
|
||||
}
|
||||
config.replyTo = data.vreply_to_msg_id().v;
|
||||
const auto id = data.vreply_to_msg_id().v;
|
||||
config.replyTo = data.is_reply_to_scheduled()
|
||||
? history->owner().scheduledMessages().localMessageId(id)
|
||||
: id;
|
||||
config.replyToTop = data.vreply_to_top_id().value_or(
|
||||
data.vreply_to_msg_id().v);
|
||||
});
|
||||
|
|
|
@ -1585,9 +1585,7 @@ bool RepliesWidget::showMessage(
|
|||
}
|
||||
return nullptr;
|
||||
}();
|
||||
showAtPosition(
|
||||
Data::MessagePosition{ .fullId = id, .date = message->date() },
|
||||
originItem);
|
||||
showAtPosition(message->position(), originItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,10 +41,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "window/window_peer_menu.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "base/call_delayed.h"
|
||||
#include "base/qt/qt_key_modifiers.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_chat_participant_status.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_scheduled_messages.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_message_reactions.h"
|
||||
|
@ -188,6 +190,14 @@ ScheduledWidget::ScheduledWidget(
|
|||
_inner->setEmptyInfoWidget(std::move(emptyInfo));
|
||||
}
|
||||
|
||||
_history->session().changes().messageUpdates(
|
||||
Data::MessageUpdate::Flag::Destroyed
|
||||
) | rpl::start_with_next([=](const Data::MessageUpdate &update) {
|
||||
while (update.item == _replyReturn) {
|
||||
calculateNextReplyReturn();
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
setupScrollDownButton();
|
||||
setupComposeControls();
|
||||
}
|
||||
|
@ -473,6 +483,47 @@ bool ScheduledWidget::confirmSendingFiles(
|
|||
return confirmSendingFiles(std::move(list), insertTextOnCancel);
|
||||
}
|
||||
|
||||
void ScheduledWidget::pushReplyReturn(not_null<HistoryItem*> item) {
|
||||
if (_inner->viewByPosition(item->position())) {
|
||||
_replyReturns.push_back(item->id);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
_replyReturn = item;
|
||||
updateScrollDownVisibility();
|
||||
}
|
||||
|
||||
void ScheduledWidget::computeCurrentReplyReturn() {
|
||||
_replyReturn = _replyReturns.empty()
|
||||
? nullptr
|
||||
: _history->owner().message(_history->peer, _replyReturns.back());
|
||||
}
|
||||
|
||||
void ScheduledWidget::calculateNextReplyReturn() {
|
||||
_replyReturn = nullptr;
|
||||
while (!_replyReturns.empty() && !_replyReturn) {
|
||||
_replyReturns.pop_back();
|
||||
computeCurrentReplyReturn();
|
||||
}
|
||||
if (!_replyReturn) {
|
||||
updateScrollDownVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduledWidget::checkReplyReturns() {
|
||||
const auto currentTop = _scroll->scrollTop();
|
||||
for (; _replyReturn != nullptr; calculateNextReplyReturn()) {
|
||||
const auto position = _replyReturn->position();
|
||||
const auto scrollTop = _inner->scrollTopForPosition(position);
|
||||
const auto scrolledBelow = scrollTop
|
||||
? (currentTop >= std::min(*scrollTop, _scroll->scrollTopMax()))
|
||||
: _inner->isBelowPosition(position);
|
||||
if (!scrolledBelow) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduledWidget::uploadFile(
|
||||
const QByteArray &fileContent,
|
||||
SendMediaType type) {
|
||||
|
@ -803,11 +854,23 @@ void ScheduledWidget::setupScrollDownButton() {
|
|||
}
|
||||
|
||||
void ScheduledWidget::scrollDownClicked() {
|
||||
if (base::IsCtrlPressed()) {
|
||||
showAtEnd();
|
||||
} else if (_replyReturn) {
|
||||
showAtPosition(_replyReturn->position());
|
||||
} else {
|
||||
showAtEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduledWidget::showAtEnd() {
|
||||
showAtPosition(Data::MaxMessagePosition);
|
||||
}
|
||||
|
||||
void ScheduledWidget::showAtPosition(Data::MessagePosition position) {
|
||||
if (showAtPositionNow(position)) {
|
||||
void ScheduledWidget::showAtPosition(
|
||||
Data::MessagePosition position,
|
||||
HistoryItem *originItem) {
|
||||
if (showAtPositionNow(position, originItem)) {
|
||||
if (const auto highlight = base::take(_highlightMessageId)) {
|
||||
_inner->highlightMessage(highlight);
|
||||
}
|
||||
|
@ -823,8 +886,13 @@ void ScheduledWidget::showAtPosition(Data::MessagePosition position) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ScheduledWidget::showAtPositionNow(Data::MessagePosition position) {
|
||||
bool ScheduledWidget::showAtPositionNow(
|
||||
Data::MessagePosition position,
|
||||
HistoryItem *originItem) {
|
||||
if (const auto scrollTop = _inner->scrollTopForPosition(position)) {
|
||||
while (_replyReturn && position.fullId.msg == _replyReturn->id) {
|
||||
calculateNextReplyReturn();
|
||||
}
|
||||
const auto currentScrollTop = _scroll->scrollTop();
|
||||
const auto wanted = std::clamp(
|
||||
*scrollTop,
|
||||
|
@ -840,6 +908,13 @@ bool ScheduledWidget::showAtPositionNow(Data::MessagePosition position) {
|
|||
(std::abs(fullDelta) > limit
|
||||
? HistoryView::ListWidget::AnimatedScroll::Part
|
||||
: HistoryView::ListWidget::AnimatedScroll::Full));
|
||||
if (position != Data::MaxMessagePosition
|
||||
&& position != Data::UnreadMessagePosition) {
|
||||
_inner->highlightMessage(position.fullId);
|
||||
}
|
||||
if (originItem) {
|
||||
pushReplyReturn(originItem);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1040,6 +1115,9 @@ void ScheduledWidget::onScroll() {
|
|||
}
|
||||
|
||||
void ScheduledWidget::updateInnerVisibleArea() {
|
||||
if (!_inner->animatedScrolling()) {
|
||||
checkReplyReturns();
|
||||
}
|
||||
const auto scrollTop = _scroll->scrollTop();
|
||||
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
|
||||
updateScrollDownVisibility();
|
||||
|
@ -1200,6 +1278,35 @@ bool ScheduledWidget::listIsGoodForAroundPosition(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ScheduledWidget::showMessage(
|
||||
PeerId peerId,
|
||||
const Window::SectionShow ¶ms,
|
||||
MsgId messageId) {
|
||||
if (peerId != _history->peer->id) {
|
||||
return false;
|
||||
}
|
||||
const auto id = FullMsgId(_history->peer->id, messageId);
|
||||
const auto message = _history->owner().message(id);
|
||||
if (!message || !_inner->viewByPosition(message->position())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto originItem = [&]() -> HistoryItem* {
|
||||
using OriginMessage = Window::SectionShow::OriginMessage;
|
||||
if (const auto origin = std::get_if<OriginMessage>(¶ms.origin)) {
|
||||
if (const auto returnTo = session().data().message(origin->id)) {
|
||||
if (_inner->viewByPosition(returnTo->position())
|
||||
&& _replyReturn != returnTo) {
|
||||
return returnTo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}();
|
||||
showAtPosition(message->position(), originItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
Window::SectionActionResult ScheduledWidget::sendBotCommand(
|
||||
Bot::SendCommandRequest request) {
|
||||
if (request.peer != _history->peer) {
|
||||
|
|
|
@ -74,6 +74,10 @@ public:
|
|||
not_null<Window::SectionMemento*> memento,
|
||||
const Window::SectionShow ¶ms) override;
|
||||
std::shared_ptr<Window::SectionMemento> createMemento() override;
|
||||
bool showMessage(
|
||||
PeerId peerId,
|
||||
const Window::SectionShow ¶ms,
|
||||
MsgId messageId) override;
|
||||
|
||||
Window::SectionActionResult sendBotCommand(
|
||||
Bot::SendCommandRequest request) override;
|
||||
|
@ -141,8 +145,12 @@ private:
|
|||
void updateAdaptiveLayout();
|
||||
void saveState(not_null<ScheduledMemento*> memento);
|
||||
void restoreState(not_null<ScheduledMemento*> memento);
|
||||
void showAtPosition(Data::MessagePosition position);
|
||||
bool showAtPositionNow(Data::MessagePosition position);
|
||||
void showAtPosition(
|
||||
Data::MessagePosition position,
|
||||
HistoryItem *originItem = nullptr);
|
||||
bool showAtPositionNow(
|
||||
Data::MessagePosition position,
|
||||
HistoryItem *originItem);
|
||||
|
||||
void setupComposeControls();
|
||||
|
||||
|
@ -153,6 +161,7 @@ private:
|
|||
void scrollDownAnimationFinish();
|
||||
void updateScrollDownVisibility();
|
||||
void updateScrollDownPosition();
|
||||
void showAtEnd();
|
||||
|
||||
void confirmSendNowSelected();
|
||||
void confirmDeleteSelected();
|
||||
|
@ -176,6 +185,11 @@ private:
|
|||
void chooseAttach();
|
||||
[[nodiscard]] SendMenu::Type sendMenuType() const;
|
||||
|
||||
void pushReplyReturn(not_null<HistoryItem*> item);
|
||||
void computeCurrentReplyReturn();
|
||||
void calculateNextReplyReturn();
|
||||
void checkReplyReturns();
|
||||
|
||||
void uploadFile(const QByteArray &fileContent, SendMediaType type);
|
||||
bool confirmSendingFiles(
|
||||
QImage &&image,
|
||||
|
@ -222,6 +236,9 @@ private:
|
|||
std::unique_ptr<ComposeControls> _composeControls;
|
||||
bool _skipScrollEvent = false;
|
||||
|
||||
std::vector<MsgId> _replyReturns;
|
||||
HistoryItem *_replyReturn = nullptr;
|
||||
|
||||
FullMsgId _highlightMessageId;
|
||||
std::optional<Data::MessagePosition> _nextAnimatedScrollPosition;
|
||||
int _nextAnimatedScrollDelta = 0;
|
||||
|
|
|
@ -1307,7 +1307,7 @@ void MainWidget::ui_showPeerHistory(
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (IsServerMsgId(showAtMsgId)
|
||||
if ((IsServerMsgId(showAtMsgId) || Data::IsScheduledMsgId(showAtMsgId))
|
||||
&& _mainSection
|
||||
&& _mainSection->showMessage(peerId, params, showAtMsgId)) {
|
||||
session().data().hideShownSpoilers();
|
||||
|
|
Loading…
Add table
Reference in a new issue