mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/telegramdesktop/tdesktop
synced 2026-09-20 08:03:45 +08:00
[chat] Fix parity gaps found by legacy chat view audit.
This commit is contained in:
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "history/view/history_view_chat_section.h"
|
||||
|
||||
#include "history/admin_log/history_admin_log_section.h"
|
||||
#include "history/view/controls/history_view_top_controls.h"
|
||||
#include "history/view/controls/history_view_bottom_controls.h"
|
||||
#include "history/view/controls/history_view_compose_controls.h"
|
||||
@@ -188,6 +189,18 @@ constexpr auto kPsaAboutPrefix = "cloud_lng_about_psa_";
|
||||
|| (id == ShowForChooseMessagesMsgId);
|
||||
}
|
||||
|
||||
[[nodiscard]] FullMsgId ResolveHighlightId(
|
||||
not_null<History*> history,
|
||||
MsgId highlightId) {
|
||||
if (highlightId < 0) {
|
||||
const auto migrated = history->migrateFrom();
|
||||
if (migrated && IsServerMsgId(-highlightId)) {
|
||||
return FullMsgId(migrated->peer->id, -highlightId);
|
||||
}
|
||||
}
|
||||
return FullMsgId(history->peer->id, highlightId);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ChatMemento::ChatMemento(
|
||||
@@ -206,7 +219,7 @@ ChatMemento::ChatMemento(
|
||||
_list.setAroundPosition(Data::MaxMessagePosition);
|
||||
} else if (_highlightId || _id.sublist) {
|
||||
_list.setAroundPosition({
|
||||
.fullId = FullMsgId(_id.history->peer->id, _highlightId),
|
||||
.fullId = ResolveHighlightId(_id.history, _highlightId),
|
||||
.date = TimeId(0),
|
||||
});
|
||||
}
|
||||
@@ -412,7 +425,13 @@ ChatWidget::ChatWidget(
|
||||
) | rpl::map([=] {
|
||||
return session().scheduledMessages().hasFor(_topic);
|
||||
}) | rpl::type_erased
|
||||
: rpl::single(false),
|
||||
: (_repliesRootId || _sublist)
|
||||
? (rpl::single(false) | rpl::type_erased)
|
||||
: rpl::single(rpl::empty_value()) | rpl::then(
|
||||
session().scheduledMessages().updates(_history)
|
||||
) | rpl::map([=] {
|
||||
return session().scheduledMessages().count(_history) > 0;
|
||||
}) | rpl::type_erased,
|
||||
.currentSuggest = [=] { return suggestOptions(); },
|
||||
.processShortcut = [=](QString shortcut) {
|
||||
const auto messages = &_peer->owner().shortcutMessages();
|
||||
@@ -905,6 +924,33 @@ ChatWidget::ChatWidget(
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
if ((mode() == Mode::History) && !_topic) {
|
||||
session().data().sentToScheduled(
|
||||
) | rpl::filter([=](const Data::SentToScheduled &value) {
|
||||
return (value.history == _history);
|
||||
}) | rpl::on_next([=](const Data::SentToScheduled &value) {
|
||||
const auto id = value.scheduledId;
|
||||
crl::on_main(this, [=] {
|
||||
controller->showSection(
|
||||
std::make_shared<HistoryView::ScheduledMemento>(
|
||||
_history,
|
||||
id));
|
||||
});
|
||||
}, lifetime());
|
||||
|
||||
session().data().sentFromScheduled(
|
||||
) | rpl::on_next([=](const Data::SentFromScheduled &value) {
|
||||
if (value.item->awaitingVideoProcessing()
|
||||
&& !_sentFromScheduledTip
|
||||
&& HistoryView::ShowScheduledVideoPublished(
|
||||
controller,
|
||||
value,
|
||||
crl::guard(this, [=] { _sentFromScheduledTip = false; }))) {
|
||||
_sentFromScheduledTip = true;
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
if (mode() == Mode::History) {
|
||||
using HistoryUpdateFlag = Data::HistoryUpdate::Flag;
|
||||
session().changes().historyUpdates(
|
||||
@@ -1721,6 +1767,9 @@ void ChatWidget::setupSwipeReplyAndBack() {
|
||||
return result;
|
||||
}
|
||||
if (data.direction == Qt::RightToLeft) {
|
||||
if (_inner->hasVisibleSimilarChannels()) {
|
||||
return result;
|
||||
}
|
||||
return Ui::Controls::DefaultSwipeBackHandlerFinishData([=] {
|
||||
controller()->showBackFromStack();
|
||||
});
|
||||
@@ -1733,6 +1782,7 @@ void ChatWidget::setupSwipeReplyAndBack() {
|
||||
|| (!view->data()->isRegular()
|
||||
&& (!view->data()->isEphemeral()
|
||||
|| view->data()->out()))
|
||||
|| view->data()->showSimilarChannels()
|
||||
|| view->data()->isService()) {
|
||||
return result;
|
||||
}
|
||||
@@ -3922,6 +3972,13 @@ void ChatWidget::subscribeToSublist() {
|
||||
|
||||
void ChatWidget::unreadCountUpdated() {
|
||||
if (mode() == Mode::History) {
|
||||
const auto migrated = _history->migrateFrom();
|
||||
if (_history->unreadMark() || (migrated && migrated->unreadMark())) {
|
||||
crl::on_main(this, [=] {
|
||||
closeCurrent();
|
||||
});
|
||||
return;
|
||||
}
|
||||
const auto hideCounter = _history->isForum()
|
||||
|| !_history->trackUnreadMessages();
|
||||
refreshUnreadCountBadge(hideCounter
|
||||
@@ -3984,7 +4041,7 @@ void ChatWidget::restoreState(not_null<ChatMemento*> memento) {
|
||||
anim::type::instant);
|
||||
params.highlight = memento->highlight();
|
||||
showAtPosition(Data::MessagePosition{
|
||||
.fullId = FullMsgId(_peer->id, highlight),
|
||||
.fullId = ResolveHighlightId(_history, highlight),
|
||||
.date = TimeId(0),
|
||||
}, memento->originId(), params);
|
||||
}
|
||||
@@ -4313,6 +4370,8 @@ void ChatWidget::showFinishedHook() {
|
||||
_topic->saveMeAsActiveSubsectionThread();
|
||||
} else if (_sublist) {
|
||||
_sublist->saveMeAsActiveSubsectionThread();
|
||||
} else if (mode() == Mode::History) {
|
||||
_history->saveMeAsActiveSubsectionThread();
|
||||
}
|
||||
|
||||
updateControlsVisibility();
|
||||
@@ -5722,6 +5781,18 @@ void ChatWidget::setupShortcuts() {
|
||||
_history));
|
||||
return true;
|
||||
});
|
||||
if (mode() == Mode::History) {
|
||||
const auto channel = _peer->asChannel();
|
||||
const auto hasRecentActions = channel
|
||||
&& (channel->hasAdminRights() || channel->amCreator());
|
||||
if (hasRecentActions) {
|
||||
request->check(Command::ShowAdminLog, 1) && request->handle([=] {
|
||||
controller()->showSection(
|
||||
std::make_shared<AdminLog::SectionMemento>(channel));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
if ((mode() == Mode::History) && session().supportMode()) {
|
||||
request->check(Command::SupportToggleMuted)
|
||||
&& request->handle([=] {
|
||||
|
||||
@@ -609,6 +609,7 @@ private:
|
||||
|
||||
bool _loaded = false;
|
||||
bool _maybeSendStart = false;
|
||||
bool _sentFromScheduledTip = false;
|
||||
History *_supportPreloadHistory = nullptr;
|
||||
int _supportPreloadRequest = 0;
|
||||
|
||||
|
||||
@@ -929,7 +929,18 @@ bool AddEditMessageAction(
|
||||
if (!HasEditMessageAction(request, list)) {
|
||||
return false;
|
||||
}
|
||||
const auto item = request.item;
|
||||
const auto item = [&]() -> HistoryItem* {
|
||||
const auto base = request.item;
|
||||
const auto view = base->groupId() ? request.view : nullptr;
|
||||
if (!view) {
|
||||
return base;
|
||||
} else if (const auto quoteItem = request.quote.item) {
|
||||
return quoteItem;
|
||||
} else if (const auto textItem = view->textItem()) {
|
||||
return textItem;
|
||||
}
|
||||
return base;
|
||||
}();
|
||||
if (!item->allowsEdit(base::unixtime::now())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2030,6 +2030,24 @@ bool ListWidget::canConsumeHorizontalScroll(QPoint position, int delta) const {
|
||||
delta);
|
||||
}
|
||||
|
||||
bool ListWidget::hasVisibleSimilarChannels() const {
|
||||
const auto from = std::lower_bound(
|
||||
begin(_items),
|
||||
end(_items),
|
||||
_visibleTop,
|
||||
[this](auto &elem, int top) {
|
||||
return this->itemTop(elem) + elem->height() <= top;
|
||||
});
|
||||
for (auto i = from; i != end(_items); ++i) {
|
||||
if (itemTop(*i) >= _visibleBottom) {
|
||||
break;
|
||||
} else if ((*i)->data()->showSimilarChannels()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ListWidget::consumeScrollAction(
|
||||
QPoint delta,
|
||||
Qt::ScrollPhase phase,
|
||||
@@ -3257,9 +3275,16 @@ SelectedItems ListWidget::getSelectedItems() const {
|
||||
|
||||
TextSelection ListWidget::getSelectedTextRange(
|
||||
not_null<HistoryItem*> item) const {
|
||||
return (_selectedTextItem == item)
|
||||
? _selectedTextSelection.flatRangeForEdit()
|
||||
: TextSelection();
|
||||
if (!hasSelectedText()) {
|
||||
return TextSelection();
|
||||
} else if (_selectedTextItem == item) {
|
||||
return _selectedTextSelection.flatRangeForEdit();
|
||||
} else if (const auto view = viewForItem(_selectedTextItem)) {
|
||||
if (view->textItem() == item) {
|
||||
return _selectedTextSelection.flatRangeForEdit();
|
||||
}
|
||||
}
|
||||
return TextSelection();
|
||||
}
|
||||
|
||||
MessageSelection ListWidget::getSelectedTextSelection(
|
||||
@@ -5045,6 +5070,9 @@ void ListWidget::performDrag() {
|
||||
if (_reactionsManager) {
|
||||
_reactionsManager->updateButton({});
|
||||
}
|
||||
if (_replyButtonManager) {
|
||||
_replyButtonManager->updateButton({});
|
||||
}
|
||||
_delegate->listLaunchDrag(
|
||||
std::move(mimeData),
|
||||
crl::guard(this, [=] { mouseActionUpdate(QCursor::pos()); }));
|
||||
@@ -5466,6 +5494,9 @@ auto ListWidget::replyToMessageRequested() const
|
||||
void ListWidget::replyToMessageRequestNotify(
|
||||
FullReplyTo to,
|
||||
bool forceAnotherChat) {
|
||||
if (!to.quote.empty()) {
|
||||
clearTextSelection();
|
||||
}
|
||||
_requestedToReplyToMessage.fire({ std::move(to), forceAnotherChat });
|
||||
}
|
||||
|
||||
|
||||
@@ -414,6 +414,7 @@ public:
|
||||
[[nodiscard]] bool canConsumeHorizontalScroll(
|
||||
QPoint position,
|
||||
int delta) const;
|
||||
[[nodiscard]] bool hasVisibleSimilarChannels() const;
|
||||
bool consumeScrollAction(
|
||||
QPoint delta,
|
||||
Qt::ScrollPhase phase,
|
||||
|
||||
@@ -1527,6 +1527,15 @@ void MainWidget::showHistory(
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto wasActivePeer = _controller->activeChatCurrent().peer();
|
||||
if (wasActivePeer
|
||||
&& (wasActivePeer != history->peer)
|
||||
&& (way != Way::Forward)) {
|
||||
ClearBotStartToken(wasActivePeer);
|
||||
}
|
||||
if (wasActivePeer != history->peer) {
|
||||
session().api().views().removeIncremented(history->peer);
|
||||
}
|
||||
auto memento = std::make_shared<ChatMemento>(
|
||||
ChatViewId{ .history = history },
|
||||
showAtMsgId,
|
||||
@@ -1543,6 +1552,14 @@ void MainWidget::showHistory(
|
||||
auto showParams = params;
|
||||
showParams.way = way;
|
||||
showSection(std::move(memento), showParams);
|
||||
if (_dialogs && !_dialogs->isHidden()) {
|
||||
if (way != Way::Backward) {
|
||||
_dialogs->scrollToEntry(Dialogs::RowDescriptor(
|
||||
history,
|
||||
FullMsgId(history->peer->id, showAtMsgId)));
|
||||
}
|
||||
_dialogs->update();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2348,7 +2365,10 @@ bool MainWidget::showBackFromStack(const SectionShow ¶ms) {
|
||||
|
||||
auto item = std::move(_stack.back());
|
||||
_stack.pop_back();
|
||||
if (const auto currentHistoryPeer = _history->peer()) {
|
||||
const auto currentHistoryPeer = _history->peer()
|
||||
? _history->peer()
|
||||
: _controller->activeChatCurrent().peer();
|
||||
if (currentHistoryPeer) {
|
||||
ClearBotStartToken(currentHistoryPeer);
|
||||
}
|
||||
_thirdSectionFromStack = item->takeThirdSectionMemento();
|
||||
|
||||
Reference in New Issue
Block a user