mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Enable story actions in channels.
This commit is contained in:
parent
29c5f6b706
commit
39f8394f98
10 changed files with 142 additions and 63 deletions
|
@ -3976,7 +3976,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_stories_recent_button" = "Recent Stories";
|
"lng_stories_recent_button" = "Recent Stories";
|
||||||
"lng_stories_archive_title" = "Stories Archive";
|
"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_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_reply_sent" = "Message Sent";
|
||||||
"lng_stories_hidden_to_contacts" = "Stories from {user} will now be shown in **Archived Chats**.";
|
"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**.";
|
"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" = "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#one" = "{count} story is hidden from your profile.";
|
||||||
"lng_stories_archive_done_many#other" = "{count} stories are 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_stories_save_promo" = "Subscribe to {link} to download other people's unprotected stories to disk.";
|
||||||
|
|
||||||
"lng_stealth_mode_menu_item" = "Stealth Mode";
|
"lng_stealth_mode_menu_item" = "Stealth Mode";
|
||||||
|
|
|
@ -547,16 +547,25 @@ bool ChannelData::canDeleteMessages() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChannelData::canPostStories() const {
|
bool ChannelData::canPostStories() const {
|
||||||
|
if (!isBroadcast()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return amCreator()
|
return amCreator()
|
||||||
|| (adminRights() & AdminRight::PostStories);
|
|| (adminRights() & AdminRight::PostStories);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChannelData::canEditStories() const {
|
bool ChannelData::canEditStories() const {
|
||||||
|
if (!isBroadcast()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return amCreator()
|
return amCreator()
|
||||||
|| (adminRights() & AdminRight::EditStories);
|
|| (adminRights() & AdminRight::EditStories);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChannelData::canDeleteStories() const {
|
bool ChannelData::canDeleteStories() const {
|
||||||
|
if (!isBroadcast()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return amCreator()
|
return amCreator()
|
||||||
|| (adminRights() & AdminRight::DeleteStories);
|
|| (adminRights() & AdminRight::DeleteStories);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1536,35 +1536,39 @@ void Stories::savedLoadMore(PeerId peerId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stories::deleteList(const std::vector<FullStoryId> &ids) {
|
void Stories::deleteList(const std::vector<FullStoryId> &ids) {
|
||||||
|
if (ids.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto peer = session().data().peer(ids.front().peer);
|
||||||
auto list = QVector<MTPint>();
|
auto list = QVector<MTPint>();
|
||||||
list.reserve(ids.size());
|
list.reserve(ids.size());
|
||||||
const auto selfId = session().userPeerId();
|
|
||||||
for (const auto &id : ids) {
|
for (const auto &id : ids) {
|
||||||
if (id.peer == selfId) {
|
if (id.peer == peer->id) {
|
||||||
list.push_back(MTP_int(id.story));
|
list.push_back(MTP_int(id.story));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!list.empty()) {
|
const auto api = &_owner->session().api();
|
||||||
const auto api = &_owner->session().api();
|
api->request(MTPstories_DeleteStories(
|
||||||
api->request(MTPstories_DeleteStories(
|
peer->input,
|
||||||
MTP_inputPeerSelf(),
|
MTP_vector<MTPint>(list)
|
||||||
MTP_vector<MTPint>(list)
|
)).done([=](const MTPVector<MTPint> &result) {
|
||||||
)).done([=](const MTPVector<MTPint> &result) {
|
for (const auto &id : result.v) {
|
||||||
for (const auto &id : result.v) {
|
applyDeleted(peer, id.v);
|
||||||
applyDeleted(_owner->session().user(), id.v);
|
}
|
||||||
}
|
}).send();
|
||||||
}).send();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stories::togglePinnedList(
|
void Stories::togglePinnedList(
|
||||||
const std::vector<FullStoryId> &ids,
|
const std::vector<FullStoryId> &ids,
|
||||||
bool pinned) {
|
bool pinned) {
|
||||||
|
if (ids.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto peer = session().data().peer(ids.front().peer);
|
||||||
auto list = QVector<MTPint>();
|
auto list = QVector<MTPint>();
|
||||||
list.reserve(ids.size());
|
list.reserve(ids.size());
|
||||||
const auto selfId = session().userPeerId();
|
|
||||||
for (const auto &id : ids) {
|
for (const auto &id : ids) {
|
||||||
if (id.peer == selfId) {
|
if (id.peer == peer->id) {
|
||||||
list.push_back(MTP_int(id.story));
|
list.push_back(MTP_int(id.story));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1573,11 +1577,12 @@ void Stories::togglePinnedList(
|
||||||
}
|
}
|
||||||
const auto api = &_owner->session().api();
|
const auto api = &_owner->session().api();
|
||||||
api->request(MTPstories_TogglePinned(
|
api->request(MTPstories_TogglePinned(
|
||||||
MTP_inputPeerSelf(),
|
peer->input,
|
||||||
MTP_vector<MTPint>(list),
|
MTP_vector<MTPint>(list),
|
||||||
MTP_bool(pinned)
|
MTP_bool(pinned)
|
||||||
)).done([=](const MTPVector<MTPint> &result) {
|
)).done([=](const MTPVector<MTPint> &result) {
|
||||||
auto &saved = _saved[selfId];
|
const auto peerId = peer->id;
|
||||||
|
auto &saved = _saved[peerId];
|
||||||
const auto loaded = saved.loaded;
|
const auto loaded = saved.loaded;
|
||||||
const auto lastId = !saved.ids.list.empty()
|
const auto lastId = !saved.ids.list.empty()
|
||||||
? saved.ids.list.back()
|
? saved.ids.list.back()
|
||||||
|
@ -1586,7 +1591,7 @@ void Stories::togglePinnedList(
|
||||||
: std::numeric_limits<StoryId>::max();
|
: std::numeric_limits<StoryId>::max();
|
||||||
auto dirty = false;
|
auto dirty = false;
|
||||||
for (const auto &id : result.v) {
|
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;
|
const auto story = *maybeStory;
|
||||||
story->setPinned(pinned);
|
story->setPinned(pinned);
|
||||||
if (pinned) {
|
if (pinned) {
|
||||||
|
@ -1610,9 +1615,9 @@ void Stories::togglePinnedList(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
savedLoadMore(selfId);
|
savedLoadMore(peerId);
|
||||||
} else {
|
} else {
|
||||||
_savedChanged.fire_copy(selfId);
|
_savedChanged.fire_copy(peerId);
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "api/api_text_entities.h"
|
#include "api/api_text_entities.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
#include "data/data_photo_media.h"
|
#include "data/data_photo_media.h"
|
||||||
|
@ -354,6 +355,10 @@ bool Story::canShare() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Story::canDelete() const {
|
bool Story::canDelete() const {
|
||||||
|
if (const auto channel = _peer->asChannel()) {
|
||||||
|
return channel->canDeleteStories()
|
||||||
|
|| (out() && channel->canPostStories());
|
||||||
|
}
|
||||||
return _peer->isSelf();
|
return _peer->isSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1208,24 +1208,37 @@ void ListWidget::toggleStoryPin(
|
||||||
list.push_back({ id.peer, StoryIdFromMsgId(id.msg) });
|
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 count = int(list.size());
|
||||||
const auto pin = (_controller->storiesTab() == Stories::Tab::Archive);
|
const auto pin = (_controller->storiesTab() == Stories::Tab::Archive);
|
||||||
const auto controller = _controller;
|
const auto controller = _controller;
|
||||||
const auto sure = [=](Fn<void()> close) {
|
const auto sure = [=](Fn<void()> close) {
|
||||||
|
using namespace ::Media::Stories;
|
||||||
controller->session().data().stories().togglePinnedList(list, pin);
|
controller->session().data().stories().togglePinnedList(list, pin);
|
||||||
controller->showToast(
|
controller->showToast(
|
||||||
::Media::Stories::PrepareTogglePinnedToast(count, pin));
|
PrepareTogglePinnedToast(channel, count, pin));
|
||||||
close();
|
close();
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
confirmed();
|
confirmed();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const auto onePhrase = pin
|
const auto onePhrase = pin
|
||||||
? tr::lng_stories_save_sure
|
? (channel
|
||||||
: tr::lng_stories_archive_sure;
|
? 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
|
const auto manyPhrase = pin
|
||||||
? tr::lng_stories_save_sure_many
|
? (channel
|
||||||
: tr::lng_stories_archive_sure_many;
|
? 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({
|
_controller->parentController()->show(Ui::MakeConfirmBox({
|
||||||
.text = (count == 1
|
.text = (count == 1
|
||||||
? onePhrase()
|
? onePhrase()
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "info/media/info_media_list_section.h"
|
#include "info/media/info_media_list_section.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_media_types.h"
|
#include "data/data_media_types.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
@ -74,6 +75,9 @@ Type Provider::type() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Provider::hasSelectRestriction() {
|
bool Provider::hasSelectRestriction() {
|
||||||
|
if (const auto channel = _peer->asChannel()) {
|
||||||
|
return !channel->canEditStories() && !channel->canDeleteStories();
|
||||||
|
}
|
||||||
return !_peer->isSelf();
|
return !_peer->isSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,24 +350,21 @@ ListItemSelectionData Provider::computeSelectionData(
|
||||||
not_null<const HistoryItem*> item,
|
not_null<const HistoryItem*> item,
|
||||||
TextSelection selection) {
|
TextSelection selection) {
|
||||||
auto result = ListItemSelectionData(selection);
|
auto result = ListItemSelectionData(selection);
|
||||||
|
const auto id = item->id;
|
||||||
|
if (!IsStoryMsgId(id)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
const auto peer = item->history()->peer;
|
const auto peer = item->history()->peer;
|
||||||
result.canDelete = peer->isSelf();
|
const auto channel = peer->asChannel();
|
||||||
result.canForward = [&] {
|
const auto maybeStory = peer->owner().stories().lookup(
|
||||||
if (!peer->isSelf()) {
|
{ peer->id, StoryIdFromMsgId(id) });
|
||||||
return false;
|
if (maybeStory) {
|
||||||
}
|
const auto story = *maybeStory;
|
||||||
const auto id = item->id;
|
result.canForward = peer->isSelf() && story->canShare();
|
||||||
if (!IsStoryMsgId(id)) {
|
result.canDelete = story->canDelete();
|
||||||
return false;
|
}
|
||||||
}
|
result.canToggleStoryPin = peer->isSelf()
|
||||||
const auto maybeStory = peer->owner().stories().lookup(
|
|| (channel && channel->canEditStories());
|
||||||
{ peer->id, StoryIdFromMsgId(id) });
|
|
||||||
if (!maybeStory) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (*maybeStory)->canShare();
|
|
||||||
}();
|
|
||||||
result.canToggleStoryPin = peer->isSelf();
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1546,7 +1546,8 @@ void Controller::togglePinnedRequested(bool pinned) {
|
||||||
moveFromShown();
|
moveFromShown();
|
||||||
}
|
}
|
||||||
story->owner().stories().togglePinnedList({ story->fullId() }, pinned);
|
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() {
|
void Controller::moveFromShown() {
|
||||||
|
@ -1597,29 +1598,41 @@ void Controller::updatePowerSaveBlocker(const Player::TrackState &state) {
|
||||||
[=] { return _wrap->window()->windowHandle(); });
|
[=] { return _wrap->window()->windowHandle(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
Ui::Toast::Config PrepareTogglePinnedToast(int count, bool pinned) {
|
Ui::Toast::Config PrepareTogglePinnedToast(
|
||||||
|
bool channel,
|
||||||
|
int count,
|
||||||
|
bool pinned) {
|
||||||
return {
|
return {
|
||||||
.text = (pinned
|
.text = (pinned
|
||||||
? (count == 1
|
? (count == 1
|
||||||
? tr::lng_stories_save_done(
|
? (channel
|
||||||
tr::now,
|
? tr::lng_stories_channel_save_done
|
||||||
Ui::Text::Bold)
|
: tr::lng_stories_save_done)(
|
||||||
: tr::lng_stories_save_done_many(
|
tr::now,
|
||||||
tr::now,
|
Ui::Text::Bold)
|
||||||
lt_count,
|
: (channel
|
||||||
count,
|
? tr::lng_stories_channel_save_done_many
|
||||||
Ui::Text::Bold)).append(
|
: tr::lng_stories_save_done_many)(
|
||||||
'\n').append(
|
tr::now,
|
||||||
tr::lng_stories_save_done_about(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
|
: (count == 1
|
||||||
? tr::lng_stories_archive_done(
|
? (channel
|
||||||
tr::now,
|
? tr::lng_stories_channel_archive_done
|
||||||
Ui::Text::WithEntities)
|
: tr::lng_stories_archive_done)(
|
||||||
: tr::lng_stories_archive_done_many(
|
tr::now,
|
||||||
tr::now,
|
Ui::Text::WithEntities)
|
||||||
lt_count,
|
: (channel
|
||||||
count,
|
? tr::lng_stories_channel_archive_done_many
|
||||||
Ui::Text::WithEntities))),
|
: tr::lng_stories_archive_done_many)(
|
||||||
|
tr::now,
|
||||||
|
lt_count,
|
||||||
|
count,
|
||||||
|
Ui::Text::WithEntities))),
|
||||||
.st = &st::storiesActionToast,
|
.st = &st::storiesActionToast,
|
||||||
.duration = (pinned
|
.duration = (pinned
|
||||||
? Data::Stories::kPinnedToastDuration
|
? Data::Stories::kPinnedToastDuration
|
||||||
|
|
|
@ -313,6 +313,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] Ui::Toast::Config PrepareTogglePinnedToast(
|
[[nodiscard]] Ui::Toast::Config PrepareTogglePinnedToast(
|
||||||
|
bool channel,
|
||||||
int count,
|
int count,
|
||||||
bool pinned);
|
bool pinned);
|
||||||
void ReportRequested(
|
void ReportRequested(
|
||||||
|
|
|
@ -1016,6 +1016,23 @@ void SetupMessages(
|
||||||
AddSkip(inner, st::settingsCheckboxesSkip);
|
AddSkip(inner, st::settingsCheckboxesSkip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetupArchive(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<Ui::VerticalLayout*> 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(
|
void SetupExport(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<Ui::VerticalLayout*> container,
|
not_null<Ui::VerticalLayout*> container,
|
||||||
|
@ -1737,6 +1754,7 @@ void Chat::setupContent(not_null<Window::SessionController*> controller) {
|
||||||
SetupChatBackground(controller, content);
|
SetupChatBackground(controller, content);
|
||||||
SetupStickersEmoji(controller, content);
|
SetupStickersEmoji(controller, content);
|
||||||
SetupMessages(controller, content);
|
SetupMessages(controller, content);
|
||||||
|
SetupArchive(controller, content);
|
||||||
|
|
||||||
Ui::ResizeFitChild(this, content);
|
Ui::ResizeFitChild(this, content);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1237,6 +1237,7 @@ void Filler::fillProfileActions() {
|
||||||
addGiftPremium();
|
addGiftPremium();
|
||||||
addBotToGroup();
|
addBotToGroup();
|
||||||
addNewMembers();
|
addNewMembers();
|
||||||
|
addStoryArchive();
|
||||||
addManageChat();
|
addManageChat();
|
||||||
addTopicLink();
|
addTopicLink();
|
||||||
addManageTopic();
|
addManageTopic();
|
||||||
|
|
Loading…
Add table
Reference in a new issue