diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 9d4166233..b09259c5f 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3976,7 +3976,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_stories_recent_button" = "Recent Stories"; "lng_stories_archive_title" = "Stories Archive"; "lng_stories_archive_about" = "Only you can see archived stories unless you choose to save them to your profile."; -"lng_stories_channel_archive_about" = "Only admins of the channel can see archived stories unless you choose to save them to the channel page."; +"lng_stories_channel_archive_about" = "Only admins of the channel can see archived stories unless they are saved to the channel page."; "lng_stories_reply_sent" = "Message Sent"; "lng_stories_hidden_to_contacts" = "Stories from {user} will now be shown in **Archived Chats**."; "lng_stories_shown_in_chats" = "Stories from {user} will now be shown in the **Chats List**."; @@ -3996,6 +3996,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_stories_archive_done" = "This story is hidden from your profile."; "lng_stories_archive_done_many#one" = "{count} story is hidden from your profile."; "lng_stories_archive_done_many#other" = "{count} stories are hidden from your profile."; +"lng_stories_channel_save_sure" = "Do you want to save this story to the channel page?"; +"lng_stories_channel_save_sure_many#one" = "Do you want to save {count} story to the channel page?"; +"lng_stories_channel_save_sure_many#other" = "Do you want to save {count} stories to the channel page?"; +"lng_stories_channel_save_done" = "This story is saved to the channel page."; +"lng_stories_channel_save_done_many#one" = "{count} story is saved to the channel page."; +"lng_stories_channel_save_done_many#other" = "{count} stories are saved to the channel page."; +"lng_stories_channel_save_done_about" = "Saved stories can be viewed by others on the channel page until they are removed."; +"lng_stories_channel_archive_sure" = "Do you want to hide this story from the channel page?"; +"lng_stories_channel_archive_sure_many#one" = "Do you want to hide {count} story from the channel page?"; +"lng_stories_channel_archive_sure_many#other" = "Do you want to hide {count} stories from the channel page?"; +"lng_stories_channel_archive_done" = "This story is hidden from the channel page."; +"lng_stories_channel_archive_done_many#one" = "{count} story is hidden from the channel page."; +"lng_stories_channel_archive_done_many#other" = "{count} stories are hidden from the channel page."; "lng_stories_save_promo" = "Subscribe to {link} to download other people's unprotected stories to disk."; "lng_stealth_mode_menu_item" = "Stealth Mode"; diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 5757fd8c1..cf266c5a2 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -547,16 +547,25 @@ bool ChannelData::canDeleteMessages() const { } bool ChannelData::canPostStories() const { + if (!isBroadcast()) { + return false; + } return amCreator() || (adminRights() & AdminRight::PostStories); } bool ChannelData::canEditStories() const { + if (!isBroadcast()) { + return false; + } return amCreator() || (adminRights() & AdminRight::EditStories); } bool ChannelData::canDeleteStories() const { + if (!isBroadcast()) { + return false; + } return amCreator() || (adminRights() & AdminRight::DeleteStories); } diff --git a/Telegram/SourceFiles/data/data_stories.cpp b/Telegram/SourceFiles/data/data_stories.cpp index 1f9b721d1..e21a6dfa5 100644 --- a/Telegram/SourceFiles/data/data_stories.cpp +++ b/Telegram/SourceFiles/data/data_stories.cpp @@ -1536,35 +1536,39 @@ void Stories::savedLoadMore(PeerId peerId) { } void Stories::deleteList(const std::vector &ids) { + if (ids.empty()) { + return; + } + const auto peer = session().data().peer(ids.front().peer); auto list = QVector(); list.reserve(ids.size()); - const auto selfId = session().userPeerId(); for (const auto &id : ids) { - if (id.peer == selfId) { + if (id.peer == peer->id) { list.push_back(MTP_int(id.story)); } } - if (!list.empty()) { - const auto api = &_owner->session().api(); - api->request(MTPstories_DeleteStories( - MTP_inputPeerSelf(), - MTP_vector(list) - )).done([=](const MTPVector &result) { - for (const auto &id : result.v) { - applyDeleted(_owner->session().user(), id.v); - } - }).send(); - } + const auto api = &_owner->session().api(); + api->request(MTPstories_DeleteStories( + peer->input, + MTP_vector(list) + )).done([=](const MTPVector &result) { + for (const auto &id : result.v) { + applyDeleted(peer, id.v); + } + }).send(); } void Stories::togglePinnedList( const std::vector &ids, bool pinned) { + if (ids.empty()) { + return; + } + const auto peer = session().data().peer(ids.front().peer); auto list = QVector(); list.reserve(ids.size()); - const auto selfId = session().userPeerId(); for (const auto &id : ids) { - if (id.peer == selfId) { + if (id.peer == peer->id) { list.push_back(MTP_int(id.story)); } } @@ -1573,11 +1577,12 @@ void Stories::togglePinnedList( } const auto api = &_owner->session().api(); api->request(MTPstories_TogglePinned( - MTP_inputPeerSelf(), + peer->input, MTP_vector(list), MTP_bool(pinned) )).done([=](const MTPVector &result) { - auto &saved = _saved[selfId]; + const auto peerId = peer->id; + auto &saved = _saved[peerId]; const auto loaded = saved.loaded; const auto lastId = !saved.ids.list.empty() ? saved.ids.list.back() @@ -1586,7 +1591,7 @@ void Stories::togglePinnedList( : std::numeric_limits::max(); auto dirty = false; for (const auto &id : result.v) { - if (const auto maybeStory = lookup({ selfId, id.v })) { + if (const auto maybeStory = lookup({ peerId, id.v })) { const auto story = *maybeStory; story->setPinned(pinned); if (pinned) { @@ -1610,9 +1615,9 @@ void Stories::togglePinnedList( } } if (dirty) { - savedLoadMore(selfId); + savedLoadMore(peerId); } else { - _savedChanged.fire_copy(selfId); + _savedChanged.fire_copy(peerId); } }).send(); } diff --git a/Telegram/SourceFiles/data/data_story.cpp b/Telegram/SourceFiles/data/data_story.cpp index 70a2c9ee5..dc142bbd6 100644 --- a/Telegram/SourceFiles/data/data_story.cpp +++ b/Telegram/SourceFiles/data/data_story.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_text_entities.h" #include "data/data_document.h" #include "data/data_changes.h" +#include "data/data_channel.h" #include "data/data_file_origin.h" #include "data/data_photo.h" #include "data/data_photo_media.h" @@ -354,6 +355,10 @@ bool Story::canShare() const { } bool Story::canDelete() const { + if (const auto channel = _peer->asChannel()) { + return channel->canDeleteStories() + || (out() && channel->canPostStories()); + } return _peer->isSelf(); } diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index 5bc2155cb..1a42e6379 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -1208,24 +1208,37 @@ void ListWidget::toggleStoryPin( list.push_back({ id.peer, StoryIdFromMsgId(id.msg) }); } } + if (list.empty()) { + return; + } + const auto channel = peerIsChannel(list.front().peer); const auto count = int(list.size()); const auto pin = (_controller->storiesTab() == Stories::Tab::Archive); const auto controller = _controller; const auto sure = [=](Fn close) { + using namespace ::Media::Stories; controller->session().data().stories().togglePinnedList(list, pin); controller->showToast( - ::Media::Stories::PrepareTogglePinnedToast(count, pin)); + PrepareTogglePinnedToast(channel, count, pin)); close(); if (confirmed) { confirmed(); } }; const auto onePhrase = pin - ? tr::lng_stories_save_sure - : tr::lng_stories_archive_sure; + ? (channel + ? tr::lng_stories_channel_save_sure + : tr::lng_stories_save_sure) + : (channel + ? tr::lng_stories_channel_archive_sure + : tr::lng_stories_archive_sure); const auto manyPhrase = pin - ? tr::lng_stories_save_sure_many - : tr::lng_stories_archive_sure_many; + ? (channel + ? tr::lng_stories_channel_save_sure_many + : tr::lng_stories_save_sure_many) + : (channel + ? tr::lng_stories_channel_archive_sure_many + : tr::lng_stories_archive_sure_many); _controller->parentController()->show(Ui::MakeConfirmBox({ .text = (count == 1 ? onePhrase() diff --git a/Telegram/SourceFiles/info/stories/info_stories_provider.cpp b/Telegram/SourceFiles/info/stories/info_stories_provider.cpp index 20048a3e4..abfe9ebb4 100644 --- a/Telegram/SourceFiles/info/stories/info_stories_provider.cpp +++ b/Telegram/SourceFiles/info/stories/info_stories_provider.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/media/info_media_list_section.h" #include "info/info_controller.h" #include "data/data_changes.h" +#include "data/data_channel.h" #include "data/data_document.h" #include "data/data_media_types.h" #include "data/data_session.h" @@ -74,6 +75,9 @@ Type Provider::type() { } bool Provider::hasSelectRestriction() { + if (const auto channel = _peer->asChannel()) { + return !channel->canEditStories() && !channel->canDeleteStories(); + } return !_peer->isSelf(); } @@ -346,24 +350,21 @@ ListItemSelectionData Provider::computeSelectionData( not_null item, TextSelection selection) { auto result = ListItemSelectionData(selection); + const auto id = item->id; + if (!IsStoryMsgId(id)) { + return result; + } const auto peer = item->history()->peer; - result.canDelete = 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(); + const auto channel = peer->asChannel(); + const auto maybeStory = peer->owner().stories().lookup( + { peer->id, StoryIdFromMsgId(id) }); + if (maybeStory) { + const auto story = *maybeStory; + result.canForward = peer->isSelf() && story->canShare(); + result.canDelete = story->canDelete(); + } + result.canToggleStoryPin = peer->isSelf() + || (channel && channel->canEditStories()); return result; } diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp index 8de78f2fe..e0fc61089 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp @@ -1546,7 +1546,8 @@ void Controller::togglePinnedRequested(bool pinned) { moveFromShown(); } story->owner().stories().togglePinnedList({ story->fullId() }, pinned); - uiShow()->showToast(PrepareTogglePinnedToast(1, pinned)); + const auto channel = story->peer()->isChannel(); + uiShow()->showToast(PrepareTogglePinnedToast(channel, 1, pinned)); } void Controller::moveFromShown() { @@ -1597,29 +1598,41 @@ void Controller::updatePowerSaveBlocker(const Player::TrackState &state) { [=] { return _wrap->window()->windowHandle(); }); } -Ui::Toast::Config PrepareTogglePinnedToast(int count, bool pinned) { +Ui::Toast::Config PrepareTogglePinnedToast( + bool channel, + int count, + bool pinned) { return { .text = (pinned ? (count == 1 - ? tr::lng_stories_save_done( - tr::now, - Ui::Text::Bold) - : tr::lng_stories_save_done_many( - tr::now, - lt_count, - count, - Ui::Text::Bold)).append( - '\n').append( - tr::lng_stories_save_done_about(tr::now)) + ? (channel + ? tr::lng_stories_channel_save_done + : tr::lng_stories_save_done)( + tr::now, + Ui::Text::Bold) + : (channel + ? tr::lng_stories_channel_save_done_many + : tr::lng_stories_save_done_many)( + tr::now, + lt_count, + count, + Ui::Text::Bold)).append( + '\n').append((channel + ? tr::lng_stories_channel_save_done_about + : tr::lng_stories_save_done_about)(tr::now)) : (count == 1 - ? tr::lng_stories_archive_done( - tr::now, - Ui::Text::WithEntities) - : tr::lng_stories_archive_done_many( - tr::now, - lt_count, - count, - Ui::Text::WithEntities))), + ? (channel + ? tr::lng_stories_channel_archive_done + : tr::lng_stories_archive_done)( + tr::now, + Ui::Text::WithEntities) + : (channel + ? tr::lng_stories_channel_archive_done_many + : tr::lng_stories_archive_done_many)( + tr::now, + lt_count, + count, + Ui::Text::WithEntities))), .st = &st::storiesActionToast, .duration = (pinned ? Data::Stories::kPinnedToastDuration diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.h b/Telegram/SourceFiles/media/stories/media_stories_controller.h index cd0750fc7..8110785b7 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.h +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.h @@ -313,6 +313,7 @@ private: }; [[nodiscard]] Ui::Toast::Config PrepareTogglePinnedToast( + bool channel, int count, bool pinned); void ReportRequested( diff --git a/Telegram/SourceFiles/settings/settings_chat.cpp b/Telegram/SourceFiles/settings/settings_chat.cpp index 3ef6104b8..01b6437f3 100644 --- a/Telegram/SourceFiles/settings/settings_chat.cpp +++ b/Telegram/SourceFiles/settings/settings_chat.cpp @@ -1016,6 +1016,23 @@ void SetupMessages( AddSkip(inner, st::settingsCheckboxesSkip); } +void SetupArchive( + not_null controller, + not_null container) { + AddDivider(container); + AddSkip(container); + + PreloadArchiveSettings(&controller->session()); + AddButton( + container, + tr::lng_context_archive_settings(), + st::settingsButton, + { &st::menuIconArchive } + )->addClickHandler([=] { + controller->show(Box(Settings::ArchiveSettingsBox, controller)); + }); +} + void SetupExport( not_null controller, not_null container, @@ -1737,6 +1754,7 @@ void Chat::setupContent(not_null controller) { SetupChatBackground(controller, content); SetupStickersEmoji(controller, content); SetupMessages(controller, content); + SetupArchive(controller, content); Ui::ResizeFitChild(this, content); } diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 4fad69570..bef94d663 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -1237,6 +1237,7 @@ void Filler::fillProfileActions() { addGiftPremium(); addBotToGroup(); addNewMembers(); + addStoryArchive(); addManageChat(); addTopicLink(); addManageTopic();