diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index ee7ee0ad3..7fb64b9d2 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -915,6 +915,11 @@ void ListWidget::showContextMenu( auto canForwardAll = [&] { return ranges::none_of(_selected, [](auto &&item) { return !item.second.canForward; + }) && (!_controller->key().storiesPeer() || _selected.size() == 1); + }; + auto canToggleStoryPinAll = [&] { + return ranges::none_of(_selected, [](auto &&item) { + return !item.second.canToggleStoryPin; }); }; @@ -1016,6 +1021,16 @@ void ListWidget::showContextMenu( } } if (overSelected == SelectionState::OverSelectedItems) { + if (canToggleStoryPinAll()) { + const auto tab = _controller->key().storiesTab(); + const auto pin = (tab == Stories::Tab::Archive); + _contextMenu->addAction( + (pin + ? tr::lng_mediaview_save_to_profile + : tr::lng_archived_add)(tr::now), + crl::guard(this, [this] { toggleStoryPinSelected(); }), + (pin ? &st::menuIconStoriesSaved : &st::menuIconArchive)); + } if (canForwardAll()) { _contextMenu->addAction( tr::lng_context_forward_selected(tr::now), @@ -1045,6 +1060,18 @@ void ListWidget::showContextMenu( const auto selectionData = _provider->computeSelectionData( item, FullSelection); + if (selectionData.canToggleStoryPin) { + const auto tab = _controller->key().storiesTab(); + const auto pin = (tab == Stories::Tab::Archive); + _contextMenu->addAction( + (pin + ? tr::lng_mediaview_save_to_profile + : tr::lng_mediaview_archive_story)(tr::now), + crl::guard(this, [=] { + toggleStoryPin({ 1, globalId.itemId }); + }), + (pin ? &st::menuIconStoriesSaved : &st::menuIconArchive)); + } if (selectionData.canForward) { _contextMenu->addAction( tr::lng_context_forward_msg(tr::now), @@ -1066,6 +1093,20 @@ void ListWidget::showContextMenu( } } } + if (const auto peer = _controller->key().storiesPeer()) { + if (!peer->isSelf() && IsStoryMsgId(globalId.itemId.msg)) { + const auto storyId = FullStoryId{ + globalId.itemId.peer, + StoryIdFromMsgId(globalId.itemId.msg), + }; + _contextMenu->addAction( + tr::lng_profile_report(tr::now), + [=] { ::Media::Stories::ReportRequested( + _controller->uiShow(), + storyId); }, + &st::menuIconReport); + } + } if (!_provider->hasSelectRestriction()) { _contextMenu->addAction( tr::lng_context_select_msg(tr::now), @@ -1105,16 +1146,7 @@ void ListWidget::contextMenuEvent(QContextMenuEvent *e) { } void ListWidget::forwardSelected() { - if (_controller->storiesPeer()) { - const auto ids = collectSelectedIds(); - if (ids.size() == 1 && IsStoryMsgId(ids.front().msg)) { - const auto id = ids.front(); - _controller->parentController()->show( - ::Media::Stories::PrepareShareBox( - _controller->parentController()->uiShow(), - { id.peer, StoryIdFromMsgId(id.msg) })); - } - } else if (auto items = collectSelectedIds(); !items.empty()) { + if (auto items = collectSelectedIds(); !items.empty()) { forwardItems(std::move(items)); } } @@ -1129,15 +1161,25 @@ void ListWidget::forwardItem(GlobalMsgId globalId) { } void ListWidget::forwardItems(MessageIdsList &&items) { - auto callback = [weak = Ui::MakeWeak(this)] { - if (const auto strong = weak.data()) { - strong->clearSelected(); + if (_controller->storiesPeer()) { + if (items.size() == 1 && IsStoryMsgId(items.front().msg)) { + const auto id = items.front(); + _controller->parentController()->show( + ::Media::Stories::PrepareShareBox( + _controller->parentController()->uiShow(), + { id.peer, StoryIdFromMsgId(id.msg) })); } - }; - setActionBoxWeak(Window::ShowForwardMessagesBox( - _controller, - std::move(items), - std::move(callback))); + } else { + auto callback = [weak = Ui::MakeWeak(this)] { + if (const auto strong = weak.data()) { + strong->clearSelected(); + } + }; + setActionBoxWeak(Window::ShowForwardMessagesBox( + _controller, + std::move(items), + std::move(callback))); + } } void ListWidget::deleteSelected() { @@ -1147,12 +1189,16 @@ void ListWidget::deleteSelected() { } void ListWidget::toggleStoryPinSelected() { - auto list = std::vector(); - const auto confirmed = crl::guard(this, [=] { + toggleStoryPin(collectSelectedIds(), crl::guard(this, [=] { clearSelected(); - }); - for (const auto &item : collectSelectedItems().list) { - const auto id = item.globalId.itemId; + })); +} + +void ListWidget::toggleStoryPin( + MessageIdsList &&items, + Fn confirmed) { + auto list = std::vector(); + for (const auto &id : items) { if (IsStoryMsgId(id.msg)) { list.push_back({ id.peer, StoryIdFromMsgId(id.msg) }); } @@ -1165,7 +1211,9 @@ void ListWidget::toggleStoryPinSelected() { controller->showToast( ::Media::Stories::PrepareTogglePinnedToast(count, pin)); close(); - confirmed(); + if (confirmed) { + confirmed(); + } }; const auto session = &_controller->session(); const auto onePhrase = pin diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.h b/Telegram/SourceFiles/info/media/info_media_list_widget.h index b518e212e..10984f27e 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.h +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.h @@ -192,6 +192,9 @@ private: void toggleStoryPinSelected(); void deleteItem(GlobalMsgId globalId); void deleteItems(SelectedItems &&items, Fn confirmed = nullptr); + void toggleStoryPin( + MessageIdsList &&items, + Fn confirmed = nullptr); void applyItemSelection( HistoryItem *item, TextSelection selection); diff --git a/Telegram/SourceFiles/info/stories/info_stories_provider.cpp b/Telegram/SourceFiles/info/stories/info_stories_provider.cpp index c42569c8d..b4cf680c6 100644 --- a/Telegram/SourceFiles/info/stories/info_stories_provider.cpp +++ b/Telegram/SourceFiles/info/stories/info_stories_provider.cpp @@ -314,7 +314,21 @@ ListItemSelectionData Provider::computeSelectionData( auto result = ListItemSelectionData(selection); const auto peer = item->history()->peer; result.canDelete = peer->isSelf(); - result.canForward = peer->isSelf(); + result.canForward = [&] { + if (!peer->isSelf()) { + return false; + } + const auto id = item->id; + if (!IsStoryMsgId(id)) { + return false; + } + const auto maybeStory = peer->owner().stories().lookup( + { peer->id, StoryIdFromMsgId(id) }); + if (!maybeStory) { + return false; + } + return (*maybeStory)->canShare(); + }(); result.canToggleStoryPin = peer->isSelf(); return result; } diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp index 555611ea4..e66172ee5 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp @@ -1278,26 +1278,7 @@ void Controller::deleteRequested() { } void Controller::reportRequested() { - const auto story = this->story(); - if (!story) { - return; - } - const auto id = story->fullId(); - const auto owner = &story->owner(); - const auto confirmed = [=](Fn close) { - owner->stories().deleteList({ id }); - close(); - }; - const auto show = uiShow(); - const auto st = &st::storiesReportBox; - show->show(Box(Ui::ReportReasonBox, *st, Ui::ReportSource::Story, [=]( - Ui::ReportReason reason) { - const auto done = [=](const QString &text) { - owner->stories().report(show, id, reason, text); - show->hideLayer(); - }; - show->showBox(Box(Ui::ReportDetailsBox, *st, done)); - })); + ReportRequested(uiShow(), _shown, &st::storiesReportBox); } void Controller::togglePinnedRequested(bool pinned) { @@ -1391,4 +1372,20 @@ Ui::Toast::Config PrepareTogglePinnedToast(int count, bool pinned) { }; } +void ReportRequested( + std::shared_ptr show, + FullStoryId id, + const style::ReportBox *stOverride) { + const auto owner = &show->session().data(); + const auto st = stOverride ? stOverride : &st::defaultReportBox; + show->show(Box(Ui::ReportReasonBox, *st, Ui::ReportSource::Story, [=]( + Ui::ReportReason reason) { + const auto done = [=](const QString &text) { + owner->stories().report(show, id, reason, text); + show->hideLayer(); + }; + show->showBox(Box(Ui::ReportDetailsBox, *st, done)); + })); +} + } // namespace Media::Stories diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.h b/Telegram/SourceFiles/media/stories/media_stories_controller.h index 9bcbe4049..694082a04 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.h +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.h @@ -10,6 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_stories.h" #include "ui/effects/animations.h" +namespace style { +struct ReportBox; +} // namespace style + namespace base { class PowerSaveBlocker; } // namespace base @@ -40,6 +44,7 @@ struct Config; namespace Main { class Session; +class SessionShow; } // namespace Main namespace Media::Player { @@ -260,5 +265,9 @@ private: [[nodiscard]] Ui::Toast::Config PrepareTogglePinnedToast( int count, bool pinned); +void ReportRequested( + std::shared_ptr show, + FullStoryId id, + const style::ReportBox *stOverride = nullptr); } // namespace Media::Stories