mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 15:13:57 +02:00
Support topic closing.
This commit is contained in:
parent
fe41fbd7e9
commit
ad2f9438a2
9 changed files with 132 additions and 17 deletions
|
@ -3517,10 +3517,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_forum_topic_new" = "New Topic";
|
"lng_forum_topic_new" = "New Topic";
|
||||||
"lng_forum_topic_edit" = "Edit Topic";
|
"lng_forum_topic_edit" = "Edit Topic";
|
||||||
"lng_forum_topic_title" = "Topic Title";
|
"lng_forum_topic_title" = "Topic Title";
|
||||||
|
"lng_forum_topic_closed" = "This topic is now closed.";
|
||||||
"lng_forum_topics_switch" = "Topics";
|
"lng_forum_topics_switch" = "Topics";
|
||||||
"lng_forum_no_topics" = "No topics currently created in this forum.";
|
"lng_forum_no_topics" = "No topics currently created in this forum.";
|
||||||
"lng_forum_create_topic" = "Create topic";
|
"lng_forum_create_topic" = "Create topic";
|
||||||
"lng_forum_discard_sure" = "Discard sure?";
|
"lng_forum_discard_sure" = "Are you sure you want to discard this topic?";
|
||||||
"lng_forum_view_as_messages" = "View as Messages";
|
"lng_forum_view_as_messages" = "View as Messages";
|
||||||
|
|
||||||
// Wnd specific
|
// Wnd specific
|
||||||
|
|
|
@ -154,6 +154,7 @@ struct TopicUpdate {
|
||||||
IconId = (1U << 6),
|
IconId = (1U << 6),
|
||||||
ColorId = (1U << 7),
|
ColorId = (1U << 7),
|
||||||
CloudDraft = (1U << 8),
|
CloudDraft = (1U << 8),
|
||||||
|
Closed = (1U << 9),
|
||||||
|
|
||||||
LastUsedBit = (1U << 8),
|
LastUsedBit = (1U << 8),
|
||||||
};
|
};
|
||||||
|
|
|
@ -198,6 +198,14 @@ MsgId ForumTopic::rootId() const {
|
||||||
return _rootId;
|
return _rootId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ForumTopic::canEdit() const {
|
||||||
|
return (_flags & Flag::My) || channel()->canEditTopics();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ForumTopic::canToggleClosed() const {
|
||||||
|
return !creating() && canEdit();
|
||||||
|
}
|
||||||
|
|
||||||
bool ForumTopic::creating() const {
|
bool ForumTopic::creating() const {
|
||||||
return _forum->creating(_rootId);
|
return _forum->creating(_rootId);
|
||||||
}
|
}
|
||||||
|
@ -231,13 +239,11 @@ void ForumTopic::applyTopic(const MTPDforumTopic &data) {
|
||||||
applyColorId(data.vicon_color().v);
|
applyColorId(data.vicon_color().v);
|
||||||
|
|
||||||
const auto pinned = _list->pinned();
|
const auto pinned = _list->pinned();
|
||||||
#if 0 // #TODO forum pinned
|
|
||||||
if (data.is_pinned()) {
|
if (data.is_pinned()) {
|
||||||
pinned->addPinned(Dialogs::Key(this));
|
pinned->addPinned(Dialogs::Key(this));
|
||||||
} else {
|
} else {
|
||||||
pinned->setPinned(Dialogs::Key(this), false);
|
pinned->setPinned(Dialogs::Key(this), false);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
owner().notifySettings().apply(this, data.vnotify_settings());
|
owner().notifySettings().apply(this, data.vnotify_settings());
|
||||||
|
|
||||||
|
@ -249,19 +255,60 @@ void ForumTopic::applyTopic(const MTPDforumTopic &data) {
|
||||||
_rootId,
|
_rootId,
|
||||||
draft->c_draftMessage());
|
draft->c_draftMessage());
|
||||||
}
|
}
|
||||||
|
if (data.is_my()) {
|
||||||
|
_flags |= Flag::My;
|
||||||
|
} else {
|
||||||
|
_flags &= ~Flag::My;
|
||||||
|
}
|
||||||
|
setClosed(data.is_closed());
|
||||||
|
|
||||||
_replies->setInboxReadTill(
|
_replies->setInboxReadTill(
|
||||||
data.vread_inbox_max_id().v,
|
data.vread_inbox_max_id().v,
|
||||||
data.vunread_count().v);
|
data.vunread_count().v);
|
||||||
_replies->setOutboxReadTill(data.vread_outbox_max_id().v);
|
_replies->setOutboxReadTill(data.vread_outbox_max_id().v);
|
||||||
applyTopicTopMessage(data.vtop_message().v);
|
applyTopicTopMessage(data.vtop_message().v);
|
||||||
#if 0 // #TODO forum unread mark
|
|
||||||
setUnreadMark(data.is_unread_mark());
|
|
||||||
#endif
|
|
||||||
unreadMentions().setCount(data.vunread_mentions_count().v);
|
unreadMentions().setCount(data.vunread_mentions_count().v);
|
||||||
unreadReactions().setCount(data.vunread_reactions_count().v);
|
unreadReactions().setCount(data.vunread_reactions_count().v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ForumTopic::closed() const {
|
||||||
|
return _flags & Flag::Closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForumTopic::setClosed(bool closed) {
|
||||||
|
if (this->closed() == closed) {
|
||||||
|
return;
|
||||||
|
} else if (closed) {
|
||||||
|
_flags |= Flag::Closed;
|
||||||
|
} else {
|
||||||
|
_flags &= ~Flag::Closed;
|
||||||
|
}
|
||||||
|
session().changes().topicUpdated(this, UpdateFlag::Closed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForumTopic::setClosedAndSave(bool closed) {
|
||||||
|
setClosed(closed);
|
||||||
|
|
||||||
|
const auto api = &session().api();
|
||||||
|
const auto weak = base::make_weak(this);
|
||||||
|
api->request(MTPchannels_EditForumTopic(
|
||||||
|
MTP_flags(MTPchannels_EditForumTopic::Flag::f_closed),
|
||||||
|
channel()->inputChannel,
|
||||||
|
MTP_int(_rootId),
|
||||||
|
MTPstring(), // title
|
||||||
|
MTPlong(), // icon_emoji_id
|
||||||
|
MTP_bool(closed)
|
||||||
|
)).done([=](const MTPUpdates &result) {
|
||||||
|
api->applyUpdates(result);
|
||||||
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
if (error.type() != u"TOPIC_NOT_MODIFIED") {
|
||||||
|
if (const auto topic = weak.get()) {
|
||||||
|
topic->forum()->requestTopic(topic->rootId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
void ForumTopic::indexTitleParts() {
|
void ForumTopic::indexTitleParts() {
|
||||||
_titleWords.clear();
|
_titleWords.clear();
|
||||||
_titleFirstLetters.clear();
|
_titleFirstLetters.clear();
|
||||||
|
|
|
@ -61,6 +61,13 @@ public:
|
||||||
[[nodiscard]] rpl::producer<> destroyed() const;
|
[[nodiscard]] rpl::producer<> destroyed() const;
|
||||||
[[nodiscard]] MsgId rootId() const;
|
[[nodiscard]] MsgId rootId() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool canEdit() const;
|
||||||
|
[[nodiscard]] bool canToggleClosed() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool closed() const;
|
||||||
|
void setClosed(bool closed);
|
||||||
|
void setClosedAndSave(bool closed);
|
||||||
|
|
||||||
[[nodiscard]] bool creating() const;
|
[[nodiscard]] bool creating() const;
|
||||||
void discard();
|
void discard();
|
||||||
|
|
||||||
|
@ -128,6 +135,13 @@ public:
|
||||||
->not_null<HistoryView::SendActionPainter*> override;
|
->not_null<HistoryView::SendActionPainter*> override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class Flag : uchar {
|
||||||
|
Closed = (1 << 0),
|
||||||
|
My = (1 << 1),
|
||||||
|
};
|
||||||
|
friend inline constexpr bool is_flag_type(Flag) { return true; }
|
||||||
|
using Flags = base::flags<Flag>;
|
||||||
|
|
||||||
void indexTitleParts();
|
void indexTitleParts();
|
||||||
void validateDefaultIcon() const;
|
void validateDefaultIcon() const;
|
||||||
void applyTopicTopMessage(MsgId topMessageId);
|
void applyTopicTopMessage(MsgId topMessageId);
|
||||||
|
@ -158,6 +172,7 @@ private:
|
||||||
base::flat_set<QChar> _titleFirstLetters;
|
base::flat_set<QChar> _titleFirstLetters;
|
||||||
int _titleVersion = 0;
|
int _titleVersion = 0;
|
||||||
int32 _colorId = 0;
|
int32 _colorId = 0;
|
||||||
|
Flags _flags;
|
||||||
|
|
||||||
std::unique_ptr<Ui::Text::CustomEmoji> _icon;
|
std::unique_ptr<Ui::Text::CustomEmoji> _icon;
|
||||||
mutable QImage _defaultIcon; // on-demand
|
mutable QImage _defaultIcon; // on-demand
|
||||||
|
|
|
@ -534,6 +534,15 @@ bool PeerData::canCreateTopics() const {
|
||||||
return isForum() && canPinMessages();
|
return isForum() && canPinMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PeerData::canEditTopics() const {
|
||||||
|
if (const auto channel = asChannel()) {
|
||||||
|
return channel->isForum()
|
||||||
|
&& (channel->amCreator()
|
||||||
|
|| (channel->adminRights() & ChatAdminRight::PinMessages));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool PeerData::canEditMessagesIndefinitely() const {
|
bool PeerData::canEditMessagesIndefinitely() const {
|
||||||
if (const auto user = asUser()) {
|
if (const auto user = asUser()) {
|
||||||
return user->isSelf();
|
return user->isSelf();
|
||||||
|
|
|
@ -340,6 +340,7 @@ public:
|
||||||
[[nodiscard]] bool canPinMessages() const;
|
[[nodiscard]] bool canPinMessages() const;
|
||||||
[[nodiscard]] bool canEditMessagesIndefinitely() const;
|
[[nodiscard]] bool canEditMessagesIndefinitely() const;
|
||||||
[[nodiscard]] bool canCreateTopics() const;
|
[[nodiscard]] bool canCreateTopics() const;
|
||||||
|
[[nodiscard]] bool canEditTopics() const;
|
||||||
[[nodiscard]] bool canExportChatHistory() const;
|
[[nodiscard]] bool canExportChatHistory() const;
|
||||||
|
|
||||||
// Returns true if about text was changed.
|
// Returns true if about text was changed.
|
||||||
|
|
|
@ -638,7 +638,6 @@ void HistoryService::setMessageByAction(const MTPmessageAction &action) {
|
||||||
|
|
||||||
auto prepareTopicCreate = [&](const MTPDmessageActionTopicCreate &action) {
|
auto prepareTopicCreate = [&](const MTPDmessageActionTopicCreate &action) {
|
||||||
auto result = PreparedText{};
|
auto result = PreparedText{};
|
||||||
// #TODO lang-forum
|
|
||||||
result.text = { tr::lng_action_topic_created(tr::now) };
|
result.text = { tr::lng_action_topic_created(tr::now) };
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
|
@ -568,19 +568,34 @@ void RepliesWidget::setupComposeControls() {
|
||||||
std::move(hasSendingMessage),
|
std::move(hasSendingMessage),
|
||||||
_1 && _2);
|
_1 && _2);
|
||||||
|
|
||||||
|
auto topicWriteRestrictions = rpl::single(
|
||||||
|
) | rpl::then(session().changes().topicUpdates(
|
||||||
|
Data::TopicUpdate::Flag::Closed
|
||||||
|
) | rpl::filter([=](const Data::TopicUpdate &update) {
|
||||||
|
return (update.topic->history() == _history)
|
||||||
|
&& (update.topic->rootId() == _rootId);
|
||||||
|
}) | rpl::to_empty) | rpl::map([=] {
|
||||||
|
const auto topic = _topic
|
||||||
|
? _topic
|
||||||
|
: _history->peer->forumTopicFor(_rootId);
|
||||||
|
return (topic->canToggleClosed() || !topic->closed())
|
||||||
|
? std::optional<QString>()
|
||||||
|
: tr::lng_forum_topic_closed(tr::now);
|
||||||
|
});
|
||||||
auto writeRestriction = rpl::combine(
|
auto writeRestriction = rpl::combine(
|
||||||
session().changes().peerFlagsValue(
|
session().changes().peerFlagsValue(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
Data::PeerUpdate::Flag::Rights),
|
Data::PeerUpdate::Flag::Rights),
|
||||||
Data::CanWriteValue(_history->peer)
|
Data::CanWriteValue(_history->peer),
|
||||||
) | rpl::map([=] {
|
std::move(topicWriteRestrictions)
|
||||||
|
) | rpl::map([=](auto, auto, std::optional<QString> topicRestriction) {
|
||||||
const auto restriction = Data::RestrictionError(
|
const auto restriction = Data::RestrictionError(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
ChatRestriction::SendMessages);
|
ChatRestriction::SendMessages);
|
||||||
return restriction
|
return restriction
|
||||||
? restriction
|
? restriction
|
||||||
: _history->peer->canWrite()
|
: _history->peer->canWrite()
|
||||||
? std::optional<QString>()
|
? std::move(topicRestriction)
|
||||||
: tr::lng_group_not_accessible(tr::now);
|
: tr::lng_group_not_accessible(tr::now);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1465,7 +1480,7 @@ bool RepliesWidget::preventsClose(Fn<void()> &&continueCallback) const {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
controller()->show(Ui::MakeConfirmBox({
|
controller()->show(Ui::MakeConfirmBox({
|
||||||
.text = rpl::single(u"Sure discard?"_q), // #TODO lang-forum
|
.text = tr::lng_forum_discard_sure(tr::now),
|
||||||
.confirmed = std::move(sure),
|
.confirmed = std::move(sure),
|
||||||
.confirmText = tr::lng_record_lock_discard(),
|
.confirmText = tr::lng_record_lock_discard(),
|
||||||
.confirmStyle = &st::attentionBoxButton,
|
.confirmStyle = &st::attentionBoxButton,
|
||||||
|
|
|
@ -226,6 +226,7 @@ private:
|
||||||
void addThemeEdit();
|
void addThemeEdit();
|
||||||
void addBlockUser();
|
void addBlockUser();
|
||||||
void addViewDiscussion();
|
void addViewDiscussion();
|
||||||
|
void addToggleTopicClosed();
|
||||||
void addExportChat();
|
void addExportChat();
|
||||||
void addReport();
|
void addReport();
|
||||||
void addNewContact();
|
void addNewContact();
|
||||||
|
@ -239,6 +240,7 @@ private:
|
||||||
void addCreateTopic();
|
void addCreateTopic();
|
||||||
void addViewAsMessages();
|
void addViewAsMessages();
|
||||||
void addSearchTopics();
|
void addSearchTopics();
|
||||||
|
void addDeleteTopic();
|
||||||
|
|
||||||
not_null<SessionController*> _controller;
|
not_null<SessionController*> _controller;
|
||||||
Dialogs::EntryState _request;
|
Dialogs::EntryState _request;
|
||||||
|
@ -386,6 +388,19 @@ void Filler::addHidePromotion() {
|
||||||
}, &st::menuIconRemove);
|
}, &st::menuIconRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Filler::addToggleTopicClosed() {
|
||||||
|
if (!_topic || !_topic->canToggleClosed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto closed = _topic->closed();
|
||||||
|
const auto weak = base::make_weak(_topic);
|
||||||
|
_addAction(closed ? u"Reopen"_q : u"Close"_q, [=] {
|
||||||
|
if (const auto topic = weak.get()) {
|
||||||
|
topic->setClosedAndSave(!closed);
|
||||||
|
}
|
||||||
|
}, closed ? &st::menuIconRestartBot : &st::menuIconBlock);
|
||||||
|
}
|
||||||
|
|
||||||
void Filler::addTogglePin() {
|
void Filler::addTogglePin() {
|
||||||
if (!_peer || _topic) {
|
if (!_peer || _topic) {
|
||||||
// #TODO forum pinned
|
// #TODO forum pinned
|
||||||
|
@ -802,13 +817,19 @@ void Filler::addDeleteContact() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Filler::addManageTopic() {
|
void Filler::addDeleteTopic() {
|
||||||
const auto topic = _thread->asTopic();
|
if (!_topic/* || !_topic->canDelete()*/) {
|
||||||
if (!topic) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto history = topic->history();
|
}
|
||||||
const auto rootId = topic->rootId();
|
|
||||||
|
|
||||||
|
void Filler::addManageTopic() {
|
||||||
|
if (!_topic || !_topic->canEdit()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto history = _topic->history();
|
||||||
|
const auto rootId = _topic->rootId();
|
||||||
const auto navigation = _controller;
|
const auto navigation = _controller;
|
||||||
_addAction(tr::lng_forum_topic_edit(tr::now), [=] {
|
_addAction(tr::lng_forum_topic_edit(tr::now), [=] {
|
||||||
navigation->show(
|
navigation->show(
|
||||||
|
@ -995,6 +1016,7 @@ void Filler::fillContextMenuActions() {
|
||||||
}
|
}
|
||||||
addToggleMuteSubmenu(false);
|
addToggleMuteSubmenu(false);
|
||||||
addToggleUnreadMark();
|
addToggleUnreadMark();
|
||||||
|
addToggleTopicClosed();
|
||||||
addToggleFolder();
|
addToggleFolder();
|
||||||
if (const auto user = _peer->asUser()) {
|
if (const auto user = _peer->asUser()) {
|
||||||
if (!user->isContact()) {
|
if (!user->isContact()) {
|
||||||
|
@ -1004,6 +1026,7 @@ void Filler::fillContextMenuActions() {
|
||||||
addClearHistory();
|
addClearHistory();
|
||||||
addDeleteChat();
|
addDeleteChat();
|
||||||
addLeaveChat();
|
addLeaveChat();
|
||||||
|
addDeleteTopic();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Filler::fillHistoryActions() {
|
void Filler::fillHistoryActions() {
|
||||||
|
@ -1032,21 +1055,25 @@ void Filler::fillProfileActions() {
|
||||||
addNewMembers();
|
addNewMembers();
|
||||||
addManageTopic();
|
addManageTopic();
|
||||||
addManageChat();
|
addManageChat();
|
||||||
|
addToggleTopicClosed();
|
||||||
addViewDiscussion();
|
addViewDiscussion();
|
||||||
addExportChat();
|
addExportChat();
|
||||||
addBlockUser();
|
addBlockUser();
|
||||||
addReport();
|
addReport();
|
||||||
addLeaveChat();
|
addLeaveChat();
|
||||||
addDeleteContact();
|
addDeleteContact();
|
||||||
|
addDeleteTopic();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Filler::fillRepliesActions() {
|
void Filler::fillRepliesActions() {
|
||||||
if (_thread->asTopic()) {
|
if (_topic) {
|
||||||
addInfo();
|
addInfo();
|
||||||
addManageTopic();
|
addManageTopic();
|
||||||
addManageChat();
|
addManageChat();
|
||||||
|
addDeleteTopic();
|
||||||
}
|
}
|
||||||
addCreatePoll();
|
addCreatePoll();
|
||||||
|
addToggleTopicClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Filler::fillScheduledActions() {
|
void Filler::fillScheduledActions() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue