From 0f443da75896cf7ddd7bff8aee75654593052434 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 25 Nov 2021 18:33:53 +0400 Subject: [PATCH] Track noforwards flag in specific messages. --- Telegram/SourceFiles/data/data_document.cpp | 2 +- Telegram/SourceFiles/data/data_peer.cpp | 3 +- Telegram/SourceFiles/data/data_types.h | 31 +++--- .../history/history_inner_widget.cpp | 94 ++++++++++++------- .../history/history_inner_widget.h | 8 +- Telegram/SourceFiles/history/history_item.cpp | 7 +- Telegram/SourceFiles/history/history_item.h | 1 + .../SourceFiles/history/history_message.cpp | 1 + .../view/history_view_context_menu.cpp | 42 +++++---- .../history/view/history_view_list_widget.cpp | 45 +++++++-- .../history/view/history_view_list_widget.h | 15 ++- .../history/view/history_view_message.cpp | 2 +- .../view/history_view_pinned_section.cpp | 5 +- .../view/history_view_pinned_section.h | 2 +- .../view/history_view_replies_section.cpp | 5 +- .../view/history_view_replies_section.h | 2 +- .../view/history_view_scheduled_section.cpp | 3 +- .../view/history_view_scheduled_section.h | 2 +- .../view/media/history_view_document.cpp | 5 +- .../history/view/media/history_view_gif.cpp | 5 +- .../media/view/media_view_overlay_widget.cpp | 3 +- .../SourceFiles/overview/overview_layout.cpp | 5 +- 22 files changed, 179 insertions(+), 109 deletions(-) diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index c7849e800c..d29c99828e 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -1165,7 +1165,7 @@ bool DocumentData::canBeStreamed(HistoryItem *item) const { && supportsStreaming() && (!isVideoFile() || !cUseExternalVideoPlayer() - || (item && !item->history()->peer->allowsForwarding())); + || (item && !item->allowsForward())); } void DocumentData::setInappPlaybackFailed() { diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index a99105659b..c8abcbb6ed 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -521,8 +521,7 @@ bool PeerData::canEditMessagesIndefinitely() const { bool PeerData::canExportChatHistory() const { if (isRepliesChat() || !allowsForwarding()) { return false; - } - if (const auto channel = asChannel()) { + } else if (const auto channel = asChannel()) { if (!channel->amIn() && channel->invitePeekExpires()) { return false; } diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h index d1bdb5b8e9..1bb5f0db63 100644 --- a/Telegram/SourceFiles/data/data_types.h +++ b/Telegram/SourceFiles/data/data_types.h @@ -236,52 +236,53 @@ enum class MessageFlag : uint32 { MediaIsUnread = (1U << 13), MentionsMe = (1U << 14), IsOrWasScheduled = (1U << 15), + NoForwards = (1U << 16), // Needs to return back to inline mode. - HasSwitchInlineButton = (1U << 16), + HasSwitchInlineButton = (1U << 17), // For "shared links" indexing. - HasTextLinks = (1U << 17), + HasTextLinks = (1U << 18), // Group / channel create or migrate service message. - IsGroupEssential = (1U << 18), + IsGroupEssential = (1U << 19), // Edited media is generated on the client // and should not update media from server. - IsLocalUpdateMedia = (1U << 19), + IsLocalUpdateMedia = (1U << 20), // Sent from inline bot, need to re-set media when sent. - FromInlineBot = (1U << 20), + FromInlineBot = (1U << 21), // Generated on the client side and should be unread. - ClientSideUnread = (1U << 21), + ClientSideUnread = (1U << 22), // In a supergroup. - HasAdminBadge = (1U << 22), + HasAdminBadge = (1U << 23), // Outgoing message that is being sent. - BeingSent = (1U << 23), + BeingSent = (1U << 24), // Outgoing message and failed to be sent. - SendingFailed = (1U << 24), + SendingFailed = (1U << 25), // No media and only a several emoji text. - IsolatedEmoji = (1U << 25), + IsolatedEmoji = (1U << 26), // Message existing in the message history. - HistoryEntry = (1U << 26), + HistoryEntry = (1U << 27), // Local message, not existing on the server. - Local = (1U << 27), + Local = (1U << 28), // Fake message for some UI element. - FakeHistoryItem = (1U << 28), + FakeHistoryItem = (1U << 29), // Contact sign-up message, notification should be skipped for Silent. - IsContactSignUp = (1U << 29), + IsContactSignUp = (1U << 30), // In channels. - IsSponsored = (1U << 30), + IsSponsored = (1U << 31), }; inline constexpr bool is_flag_type(MessageFlag) { return true; } using MessageFlags = base::flags; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index f61bd23743..96e3607f79 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -1546,7 +1546,7 @@ void HistoryInner::mouseActionFinish( if (QGuiApplication::clipboard()->supportsSelection() && !_selected.empty() && _selected.cbegin()->second != FullSelection - && !hasCopyRestriction()) { + && !hasCopyRestriction(_selected.cbegin()->first)) { const auto [item, selection] = *_selected.cbegin(); if (const auto view = item->mainView()) { TextUtilities::SetClipboardText( @@ -1723,14 +1723,15 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { })); } }; - const auto addPhotoActions = [&](not_null photo) { + const auto addPhotoActions = [&](not_null photo, HistoryItem *item) { const auto media = photo->activeMediaView(); - if (!photo->isNull() && media && media->loaded() && !hasCopyRestriction()) { + const auto itemId = item ? item->fullId() : FullMsgId(); + if (!photo->isNull() && media && media->loaded() && !hasCopyRestriction(item)) { _menu->addAction(tr::lng_context_save_image(tr::now), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [=] { savePhotoToFile(photo); })); _menu->addAction(tr::lng_context_copy_image(tr::now), [=] { - copyContextImage(photo); + copyContextImage(photo, itemId); }); } if (photo->hasAttachedStickers()) { @@ -1741,14 +1742,13 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { }); } }; - const auto addDocumentActions = [&](not_null document) { + const auto addDocumentActions = [&](not_null document, HistoryItem *item) { if (document->loading()) { _menu->addAction(tr::lng_context_cancel_download(tr::now), [=] { cancelContextDownload(document); }); return; } - const auto item = _dragStateItem; const auto itemId = item ? item->fullId() : FullMsgId(); const auto lnkIsVideo = document->isVideoFile(); const auto lnkIsVoice = document->isVoiceMessage(); @@ -1767,7 +1767,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { openContextGif(itemId); }); } - if (!hasCopyRestriction()) { + if (!hasCopyRestriction(item)) { _menu->addAction(tr::lng_context_save_gif(tr::now), [=] { saveContextGif(itemId); }); @@ -1778,7 +1778,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { showContextInFolder(document); }); } - if (!hasCopyRestriction()) { + if (!hasCopyRestriction(item)) { _menu->addAction(lnkIsVideo ? tr::lng_context_save_video(tr::now) : (lnkIsVoice ? tr::lng_context_save_audio(tr::now) : (lnkIsAudio ? tr::lng_context_save_audio_file(tr::now) : tr::lng_context_save_file(tr::now))), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [=] { saveDocumentToFile(itemId, document); })); @@ -1832,7 +1832,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { if (lnkPhoto || lnkDocument) { const auto item = _dragStateItem; const auto itemId = item ? item->fullId() : FullMsgId(); - if (isUponSelected > 0 && !hasCopyRestriction()) { + if (isUponSelected > 0 && !hasCopyRestrictionForSelected()) { _menu->addAction( (isUponSelected > 1 ? tr::lng_context_copy_selected_items(tr::now) @@ -1841,9 +1841,9 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { } addItemActions(item, item); if (lnkPhoto) { - addPhotoActions(lnkPhoto->photo()); + addPhotoActions(lnkPhoto->photo(), item); } else { - addDocumentActions(lnkDocument->document()); + addDocumentActions(lnkDocument->document(), item); } if (item && item->hasDirectLink() && isUponSelected != 2 && isUponSelected != -2) { _menu->addAction(item->history()->peer->isMegagroup() ? tr::lng_context_copy_message_link(tr::now) : tr::lng_context_copy_post_link(tr::now), [=] { @@ -1913,7 +1913,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { const auto view = item ? item->mainView() : nullptr; if (isUponSelected > 0) { - if (!hasCopyRestriction()) { + if (!hasCopyRestrictionForSelected()) { _menu->addAction( ((isUponSelected > 1) ? tr::lng_context_copy_selected_items(tr::now) @@ -1936,7 +1936,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { Api::ToggleFavedSticker(document, itemId); }); } - if (!hasCopyRestriction()) { + if (!hasCopyRestriction(item)) { _menu->addAction(tr::lng_context_save_image(tr::now), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [=] { saveDocumentToFile(itemId, document); })); @@ -1965,7 +1965,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { if (!item->isService() && view && !link - && !hasCopyRestriction() + && !hasCopyRestriction(item) && (view->hasVisibleText() || mediaHasTextForCopy)) { _menu->addAction(tr::lng_context_copy_text(tr::now), [=] { copyContextText(itemId); @@ -2048,12 +2048,12 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { } } -bool HistoryInner::hasCopyRestriction() const { - return !_peer->allowsForwarding(); +bool HistoryInner::hasCopyRestriction(HistoryItem *item) const { + return !_peer->allowsForwarding() || (item && item->forbidsForward()); } -bool HistoryInner::showCopyRestriction() { - if (!hasCopyRestriction()) { +bool HistoryInner::showCopyRestriction(HistoryItem *item) { + if (!hasCopyRestriction(item)) { return false; } Ui::ShowMultilineToast({ @@ -2064,8 +2064,29 @@ bool HistoryInner::showCopyRestriction() { return true; } +bool HistoryInner::hasCopyRestrictionForSelected() const { + if (hasCopyRestriction()) { + return true; + } + for (const auto &[item, selection] : _selected) { + if (item && item->forbidsForward()) { + return true; + } + } + return false; +} + +bool HistoryInner::showCopyRestrictionForSelected() { + for (const auto &[item, selection] : _selected) { + if (showCopyRestriction(item)) { + return true; + } + } + return false; +} + void HistoryInner::copySelectedText() { - if (!showCopyRestriction()) { + if (!showCopyRestrictionForSelected()) { TextUtilities::SetClipboardText(getSelectedText()); } } @@ -2092,11 +2113,14 @@ void HistoryInner::savePhotoToFile(not_null photo) { })); } -void HistoryInner::copyContextImage(not_null photo) { +void HistoryInner::copyContextImage( + not_null photo, + FullMsgId itemId) { + const auto item = session().data().message(itemId); const auto media = photo->activeMediaView(); if (photo->isNull() || !media || !media->loaded()) { return; - } else if (!showCopyRestriction()) { + } else if (!showCopyRestriction(item)) { const auto image = media->image(Data::PhotoSize::Large)->original(); QGuiApplication::clipboard()->setImage(image); } @@ -2137,25 +2161,25 @@ void HistoryInner::openContextGif(FullMsgId itemId) { } void HistoryInner::saveContextGif(FullMsgId itemId) { - if (hasCopyRestriction()) { - return; - } else if (const auto item = session().data().message(itemId)) { - if (const auto media = item->media()) { - if (const auto document = media->document()) { - Api::ToggleSavedGif(document, item->fullId(), true); + if (const auto item = session().data().message(itemId)) { + if (!hasCopyRestriction(item)) { + if (const auto media = item->media()) { + if (const auto document = media->document()) { + Api::ToggleSavedGif(document, item->fullId(), true); + } } } } } void HistoryInner::copyContextText(FullMsgId itemId) { - if (showCopyRestriction()) { - return; - } else if (const auto item = session().data().message(itemId)) { - if (const auto group = session().data().groups().find(item)) { - TextUtilities::SetClipboardText(HistoryGroupText(group)); - } else { - TextUtilities::SetClipboardText(HistoryItemText(item)); + if (const auto item = session().data().message(itemId)) { + if (!showCopyRestriction(item)) { + if (const auto group = session().data().groups().find(item)) { + TextUtilities::SetClipboardText(HistoryGroupText(group)); + } else { + TextUtilities::SetClipboardText(HistoryItemText(item)); + } } } } @@ -2248,7 +2272,7 @@ void HistoryInner::keyPressEvent(QKeyEvent *e) { #ifdef Q_OS_MAC } else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier) - && !showCopyRestriction()) { + && !showCopyRestrictionForSelected()) { TextUtilities::SetClipboardText(getSelectedText(), QClipboard::FindBuffer); #endif // Q_OS_MAC } else if (e == QKeySequence::Delete) { diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index c7e28ca60d..8e03022233 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -265,7 +265,7 @@ private: void saveDocumentToFile( FullMsgId contextId, not_null document); - void copyContextImage(not_null photo); + void copyContextImage(not_null photo, FullMsgId itemId); void showStickerPackInfo(not_null document); void itemRemoved(not_null item); @@ -343,8 +343,10 @@ private: void copySelectedText(); void setupSharingDisallowed(); - [[nodiscard]] bool hasCopyRestriction() const; - bool showCopyRestriction(); + [[nodiscard]] bool hasCopyRestriction(HistoryItem *item = nullptr) const; + bool showCopyRestriction(HistoryItem *item = nullptr); + [[nodiscard]] bool hasCopyRestrictionForSelected() const; + bool showCopyRestrictionForSelected(); [[nodiscard]] bool hasSelectRestriction() const; // Does any of the shown histories has this flag set. diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 386efa4306..93ab1cd463 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -645,6 +645,10 @@ bool HistoryItem::canStopPoll() const { return canBeEdited() && isRegular(); } +bool HistoryItem::forbidsForward() const { + return (_flags & MessageFlag::NoForwards); +} + bool HistoryItem::canDelete() const { if (isSponsored()) { return false; @@ -1088,7 +1092,8 @@ MessageFlags FlagsFromMTP( | ((flags & MTP::f_reply_to) ? Flag::HasReplyInfo : Flag()) | ((flags & MTP::f_reply_markup) ? Flag::HasReplyMarkup : Flag()) | ((flags & MTP::f_from_scheduled) ? Flag::IsOrWasScheduled : Flag()) - | ((flags & MTP::f_views) ? Flag::HasViews : Flag()); + | ((flags & MTP::f_views) ? Flag::HasViews : Flag()) + | ((flags & MTP::f_noforwards) ? Flag::NoForwards : Flag()); } MessageFlags FlagsFromMTP( diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index 585be30482..7ff64716bb 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -375,6 +375,7 @@ public: [[nodiscard]] bool canPin() const; [[nodiscard]] bool canBeEdited() const; [[nodiscard]] bool canStopPoll() const; + [[nodiscard]] bool forbidsForward() const; [[nodiscard]] virtual bool allowsSendNow() const; [[nodiscard]] virtual bool allowsForward() const; [[nodiscard]] virtual bool allowsEdit(TimeId now) const; diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 2fccf51b71..601133d0b9 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -1039,6 +1039,7 @@ void HistoryMessage::applySentMessage( bool HistoryMessage::allowsForward() const { return isRegular() + && !forbidsForward() && history()->peer->allowsForwarding() && (!_media || _media->allowsForward()); } diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 3b0b9bb279..a4767536d8 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -128,8 +128,10 @@ void ToggleFavedSticker( void AddPhotoActions( not_null menu, not_null photo, + HistoryItem *item, not_null list) { - if (!list->hasCopyRestriction()) { + const auto contextId = item ? item->fullId() : FullMsgId(); + if (!list->hasCopyRestriction(item)) { menu->addAction( tr::lng_context_save_image(tr::now), App::LambdaDelayed( @@ -137,7 +139,8 @@ void AddPhotoActions( &photo->session(), [=] { SavePhotoToFile(photo); })); menu->addAction(tr::lng_context_copy_image(tr::now), [=] { - if (!list->showCopyRestriction()) { + const auto item = photo->owner().message(contextId); + if (!list->showCopyRestriction(item)) { CopyImage(photo); } }); @@ -187,12 +190,14 @@ void ShowInFolder(not_null document) { void AddSaveDocumentAction( not_null menu, - Data::FileOrigin origin, + HistoryItem *item, not_null document, not_null list) { - if (list->hasCopyRestriction()) { + if (list->hasCopyRestriction(item)) { return; } + const auto origin = Data::FileOrigin( + item ? item->fullId() : FullMsgId()); const auto save = [=] { DocumentSaveClickHandler::Save( origin, @@ -219,7 +224,7 @@ void AddSaveDocumentAction( void AddDocumentActions( not_null menu, not_null document, - FullMsgId contextId, + HistoryItem *item, not_null list) { if (document->loading()) { menu->addAction(tr::lng_context_cancel_download(tr::now), [=] { @@ -227,8 +232,9 @@ void AddDocumentActions( }); return; } + const auto contextId = item ? item->fullId() : FullMsgId(); const auto session = &document->session(); - if (const auto item = session->data().message(contextId)) { + if (item) { const auto notAutoplayedGif = [&] { return document->isGifv() && !Data::AutoDownload::ShouldAutoPlay( @@ -241,7 +247,7 @@ void AddDocumentActions( OpenGif(list->controller(), contextId); }); } - if (document->isGifv() && !list->hasCopyRestriction()) { + if (document->isGifv() && !list->hasCopyRestriction(item)) { menu->addAction(tr::lng_context_save_gif(tr::now), [=] { SaveGif(list->controller(), contextId); }); @@ -276,7 +282,7 @@ void AddDocumentActions( tr::lng_context_attached_stickers(tr::now), std::move(callback)); } - AddSaveDocumentAction(menu, contextId, document, list); + AddSaveDocumentAction(menu, item, document, list); } void AddPostLinkAction( @@ -911,12 +917,12 @@ base::unique_qptr FillContextMenu( const auto hasSelection = !request.selectedItems.empty() || !request.selectedText.empty(); - if (request.overSelection && !list->hasCopyRestriction()) { + if (request.overSelection && !list->hasCopyRestrictionForSelected()) { const auto text = request.selectedItems.empty() ? tr::lng_context_copy_selected(tr::now) : tr::lng_context_copy_selected_items(tr::now); result->addAction(text, [=] { - if (!list->showCopyRestriction()) { + if (!list->showCopyRestrictionForSelected()) { TextUtilities::SetClipboardText(list->getSelectedText()); } }); @@ -924,9 +930,9 @@ base::unique_qptr FillContextMenu( AddTopMessageActions(result, request, list); if (linkPhoto) { - AddPhotoActions(result, photo, list); + AddPhotoActions(result, photo, item, list); } else if (linkDocument) { - AddDocumentActions(result, document, itemId, list); + AddDocumentActions(result, document, item, list); } else if (poll) { AddPollActions(result, poll, item, list->elementContext()); } else if (!request.overSelection && view && !hasSelection) { @@ -934,19 +940,15 @@ base::unique_qptr FillContextMenu( const auto media = view->media(); const auto mediaHasTextForCopy = media && media->hasTextForCopy(); if (const auto document = media ? media->getDocument() : nullptr) { - AddDocumentActions( - result, - document, - view->data()->fullId(), - list); + AddDocumentActions(result, document, view->data(), list); } if (!link && (view->hasVisibleText() || mediaHasTextForCopy) - && !list->hasCopyRestriction()) { + && !list->hasCopyRestriction(view->data())) { const auto asGroup = (request.pointState != PointState::GroupPart); result->addAction(tr::lng_context_copy_text(tr::now), [=] { - if (!list->showCopyRestriction()) { - if (const auto item = owner->message(itemId)) { + if (const auto item = owner->message(itemId)) { + if (!list->showCopyRestriction(item)) { if (asGroup) { if (const auto group = owner->groups().find(item)) { TextUtilities::SetClipboardText(HistoryGroupText(group)); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index e7f3c17574..e0316f99f8 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -1169,12 +1169,13 @@ bool ListWidget::isEmpty() const { && (_itemsHeight + _itemsRevealHeight == 0); } -bool ListWidget::hasCopyRestriction() const { - return _delegate->listCopyRestrictionType() != CopyRestrictionType::None; +bool ListWidget::hasCopyRestriction(HistoryItem *item) const { + return _delegate->listCopyRestrictionType(item) + != CopyRestrictionType::None; } -bool ListWidget::showCopyRestriction() { - const auto type = _delegate->listCopyRestrictionType(); +bool ListWidget::showCopyRestriction(HistoryItem *item) { + const auto type = _delegate->listCopyRestrictionType(item); if (type == CopyRestrictionType::None) { return false; } @@ -1186,6 +1187,29 @@ bool ListWidget::showCopyRestriction() { return true; } +bool ListWidget::hasCopyRestrictionForSelected() const { + if (hasCopyRestriction()) { + return true; + } + for (const auto [itemId, selection] : _selected) { + if (const auto item = session().data().message(itemId)) { + if (item->forbidsForward()) { + return true; + } + } + } + return false; +} + +bool ListWidget::showCopyRestrictionForSelected() { + for (const auto [itemId, selection] : _selected) { + if (showCopyRestriction(session().data().message(itemId))) { + return true; + } + } + return false; +} + bool ListWidget::hasSelectRestriction() const { return _delegate->listSelectRestrictionType() != CopyRestrictionType::None; @@ -1922,12 +1946,14 @@ void ListWidget::keyPressEvent(QKeyEvent *e) { } } else if (e == QKeySequence::Copy && (hasSelectedText() || hasSelectedItems()) - && !showCopyRestriction()) { + && !showCopyRestriction() + && !hasCopyRestrictionForSelected()) { TextUtilities::SetClipboardText(getSelectedText()); #ifdef Q_OS_MAC } else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier) - && !showCopyRestriction()) { + && !showCopyRestriction() + && !hasCopyRestrictionForSelected()) { TextUtilities::SetClipboardText(getSelectedText(), QClipboard::FindBuffer); #endif // Q_OS_MAC } else if (e == QKeySequence::Delete) { @@ -2451,7 +2477,7 @@ void ListWidget::mouseActionFinish( if (QGuiApplication::clipboard()->supportsSelection() && _selectedTextItem && _selectedTextRange.from != _selectedTextRange.to - && !hasCopyRestriction()) { + && !hasCopyRestriction(_selectedTextItem)) { if (const auto view = viewForItem(_selectedTextItem)) { TextUtilities::SetClipboardText( view->selectedText(_selectedTextRange), @@ -3091,8 +3117,9 @@ void ConfirmSendNowSelectedItems(not_null widget) { } CopyRestrictionType CopyRestrictionTypeFor( - not_null peer) { - return peer->allowsForwarding() + not_null peer, + HistoryItem *item) { + return (peer->allowsForwarding() && (!item || !item->forbidsForward())) ? CopyRestrictionType::None : peer->isBroadcast() ? CopyRestrictionType::Channel diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index 2ced1f8b92..f12a1436c4 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -100,7 +100,11 @@ public: const FullMsgId &context) = 0; virtual void listHandleViaClick(not_null bot) = 0; virtual not_null listChatTheme() = 0; - virtual CopyRestrictionType listCopyRestrictionType() = 0; + virtual CopyRestrictionType listCopyRestrictionType( + HistoryItem *item) = 0; + CopyRestrictionType listCopyRestrictionType() { + return listCopyRestrictionType(nullptr); + } virtual CopyRestrictionType listSelectRestrictionType() = 0; }; @@ -212,8 +216,10 @@ public: [[nodiscard]] bool loadedAtBottom() const; [[nodiscard]] bool isEmpty() const; - [[nodiscard]] bool hasCopyRestriction() const; - [[nodiscard]] bool showCopyRestriction(); + [[nodiscard]] bool hasCopyRestriction(HistoryItem *item = nullptr) const; + [[nodiscard]] bool showCopyRestriction(HistoryItem *item = nullptr); + [[nodiscard]] bool hasCopyRestrictionForSelected() const; + [[nodiscard]] bool showCopyRestrictionForSelected(); [[nodiscard]] bool hasSelectRestriction() const; // AbstractTooltipShower interface @@ -617,7 +623,8 @@ void ConfirmForwardSelectedItems(not_null widget); void ConfirmSendNowSelectedItems(not_null widget); [[nodiscard]] CopyRestrictionType CopyRestrictionTypeFor( - not_null peer); + not_null peer, + HistoryItem *item = nullptr); [[nodiscard]] CopyRestrictionType SelectRestrictionTypeFor( not_null peer); diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 2840cd3856..bf73a6ea2f 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -2217,7 +2217,7 @@ std::optional Message::rightActionSize() const { bool Message::displayFastShare() const { const auto item = message(); const auto peer = item->history()->peer; - if (!item->isRegular() || !peer->allowsForwarding()) { + if (!item->allowsForward()) { return false; } else if (peer->isChannel()) { return !peer->isMegagroup(); diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp index cd07eafad4..3115e0e1f1 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp @@ -676,8 +676,9 @@ not_null PinnedWidget::listChatTheme() { return _theme.get(); } -CopyRestrictionType PinnedWidget::listCopyRestrictionType() { - return CopyRestrictionTypeFor(_history->peer); +CopyRestrictionType PinnedWidget::listCopyRestrictionType( + HistoryItem *item) { + return CopyRestrictionTypeFor(_history->peer, item); } CopyRestrictionType PinnedWidget::listSelectRestrictionType() { diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.h b/Telegram/SourceFiles/history/view/history_view_pinned_section.h index e36afffeee..0021fdc24e 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.h +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.h @@ -103,7 +103,7 @@ public: const FullMsgId &context) override; void listHandleViaClick(not_null bot) override; not_null listChatTheme() override; - CopyRestrictionType listCopyRestrictionType() override; + CopyRestrictionType listCopyRestrictionType(HistoryItem *item) override; CopyRestrictionType listSelectRestrictionType() override; protected: diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index e993acd31a..bee37c0e4f 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -1921,8 +1921,9 @@ not_null RepliesWidget::listChatTheme() { return _theme.get(); } -CopyRestrictionType RepliesWidget::listCopyRestrictionType() { - return CopyRestrictionTypeFor(_history->peer); +CopyRestrictionType RepliesWidget::listCopyRestrictionType( + HistoryItem *item) { + return CopyRestrictionTypeFor(_history->peer, item); } CopyRestrictionType RepliesWidget::listSelectRestrictionType() { diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.h b/Telegram/SourceFiles/history/view/history_view_replies_section.h index f2700f3641..b9c7172026 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.h +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.h @@ -139,7 +139,7 @@ public: const FullMsgId &context) override; void listHandleViaClick(not_null bot) override; not_null listChatTheme() override; - CopyRestrictionType listCopyRestrictionType() override; + CopyRestrictionType listCopyRestrictionType(HistoryItem *item) override; CopyRestrictionType listSelectRestrictionType() override; protected: diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index e829664064..f7907e3918 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -1232,7 +1232,8 @@ not_null ScheduledWidget::listChatTheme() { return _theme.get(); } -CopyRestrictionType ScheduledWidget::listCopyRestrictionType() { +CopyRestrictionType ScheduledWidget::listCopyRestrictionType( + HistoryItem *item) { return CopyRestrictionType::None; } diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h index 2352eb0c13..ae2e8bb57d 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h @@ -120,7 +120,7 @@ public: const FullMsgId &context) override; void listHandleViaClick(not_null bot) override; not_null listChatTheme() override; - CopyRestrictionType listCopyRestrictionType() override; + CopyRestrictionType listCopyRestrictionType(HistoryItem *item) override; CopyRestrictionType listSelectRestrictionType() override; protected: diff --git a/Telegram/SourceFiles/history/view/media/history_view_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_document.cpp index 5ef488dbba..93b1bdd8d9 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_document.cpp @@ -593,10 +593,9 @@ void Document::ensureDataMediaCreated() const { bool Document::downloadInCorner() const { return _data->isAudioFile() - && _realParent->history()->peer->allowsForwarding() + && _realParent->allowsForward() && _data->canBeStreamed(_realParent) - && !_data->inappPlaybackFailed() - && _realParent->isRegular(); + && !_data->inappPlaybackFailed(); } void Document::drawCornerDownload( diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 6b5d07b9a5..8d8d7119b2 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -264,10 +264,9 @@ QSize Gif::videoSize() const { bool Gif::downloadInCorner() const { return _data->isVideoFile() && (_data->loading() || !autoplayEnabled()) - && _realParent->history()->peer->allowsForwarding() + && _realParent->allowsForward() && _data->canBeStreamed(_realParent) - && !_data->inappPlaybackFailed() - && !_parent->data()->isSending(); + && !_data->inappPlaybackFailed(); } bool Gif::autoplayEnabled() const { diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index b6e36b2688..8cc5cfa2b4 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -556,7 +556,8 @@ QSize OverlayWidget::flipSizeByRotation(QSize size) const { } bool OverlayWidget::hasCopyRestriction() const { - return _history && !_history->peer->allowsForwarding(); + return (_history && !_history->peer->allowsForwarding()) + || (_message && _message->forbidsForward()); } bool OverlayWidget::showCopyRestriction() { diff --git a/Telegram/SourceFiles/overview/overview_layout.cpp b/Telegram/SourceFiles/overview/overview_layout.cpp index e20eff9369..b0a6834f60 100644 --- a/Telegram/SourceFiles/overview/overview_layout.cpp +++ b/Telegram/SourceFiles/overview/overview_layout.cpp @@ -969,10 +969,9 @@ Document::Document( bool Document::downloadInCorner() const { return _data->isAudioFile() - && parent()->history()->peer->allowsForwarding() + && parent()->allowsForward() && _data->canBeStreamed(parent()) - && !_data->inappPlaybackFailed() - && parent()->isRegular(); + && !_data->inappPlaybackFailed(); } void Document::initDimensions() {