Implement context menu actions in stories list.

This commit is contained in:
John Preston 2023-06-30 17:56:54 +04:00
parent a733b83642
commit ac534780cc
5 changed files with 116 additions and 45 deletions

View File

@ -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<FullStoryId>();
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<void()> confirmed) {
auto list = std::vector<FullStoryId>();
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

View File

@ -192,6 +192,9 @@ private:
void toggleStoryPinSelected();
void deleteItem(GlobalMsgId globalId);
void deleteItems(SelectedItems &&items, Fn<void()> confirmed = nullptr);
void toggleStoryPin(
MessageIdsList &&items,
Fn<void()> confirmed = nullptr);
void applyItemSelection(
HistoryItem *item,
TextSelection selection);

View File

@ -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;
}

View File

@ -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<void()> 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<Main::SessionShow> 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

View File

@ -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<Main::SessionShow> show,
FullStoryId id,
const style::ReportBox *stOverride = nullptr);
} // namespace Media::Stories