Allow topic deletion.

This commit is contained in:
John Preston 2022-10-19 14:59:37 +04:00
parent adaa1d0c55
commit 7cdf20a7c5
43 changed files with 144 additions and 64 deletions

View file

@ -3518,6 +3518,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"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_topic_closed" = "This topic is now closed.";
"lng_forum_topic_delete" = "Delete";
"lng_forum_topic_delete_sure" = "Are you sure you want to delete this topic?";
"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";

View file

@ -25,7 +25,7 @@ AttachedStickers::AttachedStickers(not_null<ApiWrap*> api)
void AttachedStickers::request( void AttachedStickers::request(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
MTPmessages_GetAttachedStickers &&mtpRequest) { MTPmessages_GetAttachedStickers &&mtpRequest) {
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
_api.request(_requestId).cancel(); _api.request(_requestId).cancel();
_requestId = _api.request( _requestId = _api.request(
std::move(mtpRequest) std::move(mtpRequest)

View file

@ -83,7 +83,7 @@ void SendBotCallbackData(
if (withPassword) { if (withPassword) {
flags |= MTPmessages_GetBotCallbackAnswer::Flag::f_password; flags |= MTPmessages_GetBotCallbackAnswer::Flag::f_password;
} }
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
const auto show = std::make_shared<Window::Show>(controller); const auto show = std::make_shared<Window::Show>(controller);
button->requestId = api->request(MTPmessages_GetBotCallbackAnswer( button->requestId = api->request(MTPmessages_GetBotCallbackAnswer(
MTP_flags(flags), MTP_flags(flags),
@ -202,7 +202,7 @@ void SendBotCallbackDataWithPassword(
return; return;
} }
api->cloudPassword().reload(); api->cloudPassword().reload();
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
const auto show = std::make_shared<Window::Show>(controller); const auto show = std::make_shared<Window::Show>(controller);
SendBotCallbackData(controller, item, row, column, std::nullopt, [=](const QString &error) { SendBotCallbackData(controller, item, row, column, std::nullopt, [=](const QString &error) {
auto box = PrePasswordErrorBox( auto box = PrePasswordErrorBox(

View file

@ -107,7 +107,7 @@ void CheckChatInvite(
const QString &hash, const QString &hash,
ChannelData *invitePeekChannel) { ChannelData *invitePeekChannel) {
const auto session = &controller->session(); const auto session = &controller->session();
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
session->api().checkChatInvite(hash, [=](const MTPChatInvite &result) { session->api().checkChatInvite(hash, [=](const MTPChatInvite &result) {
Core::App().hideMediaView(); Core::App().hideMediaView();
result.match([=](const MTPDchatInvite &data) { result.match([=](const MTPDchatInvite &data) {

View file

@ -66,7 +66,7 @@ void ToggleFavedSticker(
if (faved && !document->sticker()) { if (faved && !document->sticker()) {
return; return;
} }
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
auto done = [=] { auto done = [=] {
document->owner().stickers().setFaved(weak.get(), document, faved); document->owner().stickers().setFaved(weak.get(), document, faved);
}; };

View file

@ -1815,7 +1815,7 @@ void ApiWrap::sendNotifySettingsUpdates() {
} }
void ApiWrap::saveDraftToCloudDelayed(not_null<Data::Thread*> thread) { void ApiWrap::saveDraftToCloudDelayed(not_null<Data::Thread*> thread) {
_draftsSaveRequestIds.emplace(base::make_weak(thread.get()), 0); _draftsSaveRequestIds.emplace(base::make_weak(thread), 0);
if (!_draftsSaveTimer.isActive()) { if (!_draftsSaveTimer.isActive()) {
_draftsSaveTimer.callOnce(kSaveCloudDraftTimeout); _draftsSaveTimer.callOnce(kSaveCloudDraftTimeout);
} }

View file

@ -148,7 +148,7 @@ void FillChooseFilterMenu(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::PopupMenu*> menu, not_null<Ui::PopupMenu*> menu,
not_null<History*> history) { not_null<History*> history) {
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
const auto validator = ChooseFilterValidator(history); const auto validator = ChooseFilterValidator(history);
for (const auto &filter : history->owner().chatsFilters().list()) { for (const auto &filter : history->owner().chatsFilters().list()) {
const auto id = filter.id(); const auto id = filter.id();

View file

@ -18,7 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/continuous_sliders.h" #include "ui/widgets/continuous_sliders.h"
#include "ui/widgets/box_content_divider.h" #include "ui/widgets/box_content_divider.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/toast/toast.h" #include "ui/toasts/common_toasts.h"
#include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_icon.h"
#include "info/profile/info_profile_values.h" #include "info/profile/info_profile_values.h"
#include "boxes/peers/edit_participants_box.h" #include "boxes/peers/edit_participants_box.h"
@ -319,7 +319,7 @@ ChatAdminRights AdminRightsForOwnershipTransfer(bool isGroup) {
Fn<void()> AboutGigagroupCallback( Fn<void()> AboutGigagroupCallback(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
not_null<Window::SessionController*> controller) { not_null<Window::SessionController*> controller) {
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
const auto converting = std::make_shared<bool>(); const auto converting = std::make_shared<bool>();
const auto convertSure = [=] { const auto convertSure = [=] {
@ -333,9 +333,10 @@ Fn<void()> AboutGigagroupCallback(
channel->session().api().applyUpdates(result); channel->session().api().applyUpdates(result);
if (const auto strongController = weak.get()) { if (const auto strongController = weak.get()) {
strongController->window().hideSettingsAndLayer(); strongController->window().hideSettingsAndLayer();
Ui::Toast::Show( Ui::ShowMultilineToast({
strongController->widget(), .parentOverride = strongController->widget(),
tr::lng_gigagroup_done(tr::now)); .text = { tr::lng_gigagroup_done(tr::now) },
});
} }
}).fail([=] { }).fail([=] {
*converting = false; *converting = false;
@ -430,7 +431,8 @@ void EditPeerPermissionsBox::prepare() {
disabledByAdminRights, disabledByAdminRights,
tr::lng_rights_permission_cant_edit(tr::now)); tr::lng_rights_permission_cant_edit(tr::now));
if (const auto channel = _peer->asChannel()) { if (const auto channel = _peer->asChannel()) {
if (channel->isPublic()) { if (channel->isPublic()
|| (channel->isMegagroup() && channel->linkedChat())) {
result.emplace( result.emplace(
Flag::ChangeInfo | Flag::PinMessages, Flag::ChangeInfo | Flag::PinMessages,
tr::lng_rights_permission_unavailable(tr::now)); tr::lng_rights_permission_unavailable(tr::now));
@ -732,7 +734,10 @@ EditFlagsControl<Flags> CreateEditFlags(
) | rpl::start_with_next([=](bool checked) { ) | rpl::start_with_next([=](bool checked) {
if (locked.has_value()) { if (locked.has_value()) {
if (checked != toggled) { if (checked != toggled) {
Ui::Toast::Show(parent, *locked); Ui::ShowMultilineToast({
.parentOverride = parent,
.text = { *locked },
});
control->setChecked(toggled); control->setChecked(toggled);
} }
} else { } else {

View file

@ -1125,7 +1125,7 @@ void Show(
} }
} }
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
list.push_back({ list.push_back({
.descriptor = descriptor, .descriptor = descriptor,
.media = (descriptor.requestedSticker .media = (descriptor.requestedSticker

View file

@ -1489,7 +1489,7 @@ void ShareGameScoreByHash(
if (const auto item = session.data().message(peerId, msgId)) { if (const auto item = session.data().message(peerId, msgId)) {
FastShareMessage(controller, item); FastShareMessage(controller, item);
} else { } else {
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
const auto resolveMessageAndShareScore = crl::guard(weak, [=]( const auto resolveMessageAndShareScore = crl::guard(weak, [=](
PeerData *peer) { PeerData *peer) {
auto done = crl::guard(weak, [=] { auto done = crl::guard(weak, [=] {

View file

@ -193,7 +193,7 @@ object_ptr<Ui::BoxContent> PrepareInviteBox(
&st::groupCallInviteMembersList, &st::groupCallInviteMembersList,
&st::groupCallMultiSelect); &st::groupCallMultiSelect);
const auto weak = base::make_weak(call.get()); const auto weak = base::make_weak(call);
const auto invite = [=](const std::vector<not_null<UserData*>> &users) { const auto invite = [=](const std::vector<not_null<UserData*>> &users) {
const auto call = weak.get(); const auto call = weak.get();
if (!call) { if (!call) {

View file

@ -455,7 +455,7 @@ void LeaveBox(
st::boxRowPadding.right(), st::boxRowPadding.right(),
st::boxRowPadding.bottom())) st::boxRowPadding.bottom()))
: nullptr; : nullptr;
const auto weak = base::make_weak(call.get()); const auto weak = base::make_weak(call);
auto label = scheduled auto label = scheduled
? tr::lng_group_call_close() ? tr::lng_group_call_close()
: tr::lng_group_call_leave(); : tr::lng_group_call_leave();
@ -488,7 +488,7 @@ void FillMenu(
Fn<void()> chooseJoinAs, Fn<void()> chooseJoinAs,
Fn<void()> chooseShareScreenSource, Fn<void()> chooseShareScreenSource,
Fn<void(object_ptr<Ui::BoxContent>)> showBox) { Fn<void(object_ptr<Ui::BoxContent>)> showBox) {
const auto weak = base::make_weak(call.get()); const auto weak = base::make_weak(call);
const auto resolveReal = [=] { const auto resolveReal = [=] {
const auto real = peer->groupCall(); const auto real = peer->groupCall();
const auto strong = weak.get(); const auto strong = weak.get();

View file

@ -2552,7 +2552,7 @@ not_null<Ui::RpWidget*> Panel::widget() const {
} }
Show::Show(not_null<Panel*> panel) Show::Show(not_null<Panel*> panel)
: _panel(base::make_weak(panel.get())) { : _panel(base::make_weak(panel)) {
} }
Show::~Show() = default; Show::~Show() = default;

View file

@ -244,7 +244,7 @@ void SettingsBox(
not_null<GroupCall*> call) { not_null<GroupCall*> call) {
using namespace Settings; using namespace Settings;
const auto weakCall = base::make_weak(call.get()); const auto weakCall = base::make_weak(call);
const auto weakBox = Ui::MakeWeak(box); const auto weakBox = Ui::MakeWeak(box);
struct State { struct State {

View file

@ -167,7 +167,7 @@ void BotKeyboard::mouseReleaseEvent(QMouseEvent *e) {
ActivateClickHandler(window(), activated, { ActivateClickHandler(window(), activated, {
e->button(), e->button(),
QVariant::fromValue(ClickHandlerContext{ QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(_controller.get()), .sessionWindow = base::make_weak(_controller),
}) })
}); });
} }

View file

@ -435,7 +435,7 @@ void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) {
ActivateClickHandler(window(), activated, { ActivateClickHandler(window(), activated, {
e->button(), e->button(),
QVariant::fromValue(ClickHandlerContext{ QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(_controller.get()), .sessionWindow = base::make_weak(_controller),
}) })
}); });
} }

View file

@ -189,7 +189,7 @@ std::shared_ptr<LargeEmojiImage> EmojiPack::image(EmojiPtr emoji) {
} }
auto result = std::make_shared<LargeEmojiImage>(); auto result = std::make_shared<LargeEmojiImage>();
const auto raw = result.get(); const auto raw = result.get();
const auto weak = base::make_weak(_session.get()); const auto weak = base::make_weak(_session);
raw->load = [=] { raw->load = [=] {
Core::App().emojiImageLoader().with([=]( Core::App().emojiImageLoader().with([=](
const EmojiImageLoader &loader) { const EmojiImageLoader &loader) {

View file

@ -49,7 +49,7 @@ auto LottieCachedFromContent(
key, key,
std::move(handler)); std::move(handler));
}; };
const auto weak = base::make_weak(session.get()); const auto weak = base::make_weak(session);
const auto put = [=](QByteArray &&cached) { const auto put = [=](QByteArray &&cached) {
crl::on_main(weak, [=, data = std::move(cached)]() mutable { crl::on_main(weak, [=, data = std::move(cached)]() mutable {
weak->data().cacheBigFile().put(key, std::move(data)); weak->data().cacheBigFile().put(key, std::move(data));

View file

@ -769,7 +769,7 @@ void Application::forceLogOut(
})); }));
box->setCloseByEscape(false); box->setCloseByEscape(false);
box->setCloseByOutsideClick(false); box->setCloseByOutsideClick(false);
const auto weak = base::make_weak(account.get()); const auto weak = base::make_weak(account);
connect(box, &QObject::destroyed, [=] { connect(box, &QObject::destroyed, [=] {
crl::on_main(weak, [=] { crl::on_main(weak, [=] {
account->forcedLogOut(); account->forcedLogOut();

View file

@ -930,7 +930,7 @@ void DownloadManager::writePostponed(not_null<Main::Session*> session) {
Fn<std::optional<QByteArray>()> DownloadManager::serializator( Fn<std::optional<QByteArray>()> DownloadManager::serializator(
not_null<Main::Session*> session) const { not_null<Main::Session*> session) const {
return [this, weak = base::make_weak(session.get())]() return [this, weak = base::make_weak(session)]()
-> std::optional<QByteArray> { -> std::optional<QByteArray> {
const auto strong = weak.get(); const auto strong = weak.get();
if (!strong) { if (!strong) {

View file

@ -127,10 +127,13 @@ void Forum::applyReceivedTopics(const MTPmessages_ForumTopics &result) {
void Forum::applyTopicDeleted(MsgId rootId) { void Forum::applyTopicDeleted(MsgId rootId) {
const auto i = _topics.find(rootId); const auto i = _topics.find(rootId);
if (i != end(_topics)) { if (i != end(_topics)) {
Core::App().notifications().clearFromTopic(i->second.get()); const auto raw = i->second.get();
_topicDestroyed.fire(i->second.get()); Core::App().notifications().clearFromTopic(raw);
_history->destroyMessagesByTopic(rootId); owner().removeChatListEntry(raw);
_topicDestroyed.fire(raw);
_topics.erase(i); _topics.erase(i);
_history->destroyMessagesByTopic(rootId);
} }
} }

View file

@ -202,6 +202,13 @@ bool ForumTopic::canEdit() const {
return (_flags & Flag::My) || channel()->canEditTopics(); return (_flags & Flag::My) || channel()->canEditTopics();
} }
bool ForumTopic::canDelete() const {
return !creating()
&& (channel()->canEditTopics()
// We don't know if we can delete or not.
/*|| ((_flags & Flag::My) && onlyOneMyMessage)*/);
}
bool ForumTopic::canToggleClosed() const { bool ForumTopic::canToggleClosed() const {
return !creating() && canEdit(); return !creating() && canEdit();
} }

View file

@ -64,6 +64,7 @@ public:
[[nodiscard]] bool canEdit() const; [[nodiscard]] bool canEdit() const;
[[nodiscard]] bool canToggleClosed() const; [[nodiscard]] bool canToggleClosed() const;
[[nodiscard]] bool canTogglePinned() const; [[nodiscard]] bool canTogglePinned() const;
[[nodiscard]] bool canDelete() const;
[[nodiscard]] bool closed() const; [[nodiscard]] bool closed() const;
void setClosed(bool closed); void setClosed(bool closed);

View file

@ -628,7 +628,7 @@ auto CustomEmojiManager::createLoaderWithSetId(
} }
} else { } else {
const auto i = SizeIndex(tag); const auto i = SizeIndex(tag);
_loaders[i][documentId].push_back(base::make_weak(result.get())); _loaders[i][documentId].push_back(base::make_weak(result));
_pendingForRequest.emplace(documentId); _pendingForRequest.emplace(documentId);
if (!_requestId && _pendingForRequest.size() == 1) { if (!_requestId && _pendingForRequest.size() == 1) {
crl::on_main(this, [=] { request(); }); crl::on_main(this, [=] { request(); });

View file

@ -1659,7 +1659,7 @@ void InnerWidget::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton but
? (ElementDelegate*)weak ? (ElementDelegate*)weak
: nullptr; : nullptr;
}, },
.sessionWindow = base::make_weak(_controller.get()), .sessionWindow = base::make_weak(_controller),
}) })
}); });
return; return;

View file

@ -1836,7 +1836,7 @@ void HistoryInner::mouseActionFinish(
: _mouseActionItem : _mouseActionItem
? _mouseActionItem->fullId() ? _mouseActionItem->fullId()
: FullMsgId(); : FullMsgId();
const auto weak = base::make_weak(_controller.get()); const auto weak = base::make_weak(_controller);
mouseActionCancel(); mouseActionCancel();
ActivateClickHandler( ActivateClickHandler(
window(), window(),
@ -4176,7 +4176,7 @@ void HistoryInner::onParentGeometryChanged() {
Fn<HistoryView::ElementDelegate*()> HistoryInner::elementDelegateFactory( Fn<HistoryView::ElementDelegate*()> HistoryInner::elementDelegateFactory(
FullMsgId itemId) const { FullMsgId itemId) const {
const auto weak = base::make_weak(_controller.get()); const auto weak = base::make_weak(_controller);
return [=]() -> HistoryView::ElementDelegate* { return [=]() -> HistoryView::ElementDelegate* {
if (const auto strong = weak.get()) { if (const auto strong = weak.get()) {
auto &data = strong->session().data(); auto &data = strong->session().data();
@ -4194,7 +4194,7 @@ ClickHandlerContext HistoryInner::prepareClickHandlerContext(
return ClickHandlerContext{ return ClickHandlerContext{
.itemId = itemId, .itemId = itemId,
.elementDelegate = elementDelegateFactory(itemId), .elementDelegate = elementDelegateFactory(itemId),
.sessionWindow = base::make_weak(_controller.get()), .sessionWindow = base::make_weak(_controller),
}; };
} }

View file

@ -1439,7 +1439,7 @@ void AddEmojiPacksAction(
menu->menu(), menu->menu(),
menu->st().menu, menu->st().menu,
std::move(text)); std::move(text));
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
button->setClickedCallback([=] { button->setClickedCallback([=] {
const auto strong = weak.get(); const auto strong = weak.get();
if (!strong) { if (!strong) {

View file

@ -3087,7 +3087,7 @@ void ListWidget::mouseActionFinish(
? (ElementDelegate*)weak ? (ElementDelegate*)weak
: nullptr; : nullptr;
}, },
.sessionWindow = base::make_weak(_controller.get()), .sessionWindow = base::make_weak(_controller),
}) })
}); });
return; return;

View file

@ -2862,7 +2862,7 @@ ClickHandlerPtr Message::rightActionLink() const {
savedFromPeer->session().api().requestMessageData( savedFromPeer->session().api().requestMessageData(
savedFromPeer, savedFromPeer,
savedFromMsgId, savedFromMsgId,
[=, weak = base::make_weak(controller.get())] { [=, weak = base::make_weak(controller)] {
if (const auto strong = showByThreadWeak.lock()) { if (const auto strong = showByThreadWeak.lock()) {
if (const auto strongController = weak.get()) { if (const auto strongController = weak.get()) {
*prequested = 2; *prequested = 2;

View file

@ -578,7 +578,7 @@ void RepliesWidget::setupComposeControls() {
const auto topic = _topic const auto topic = _topic
? _topic ? _topic
: _history->peer->forumTopicFor(_rootId); : _history->peer->forumTopicFor(_rootId);
return (topic->canToggleClosed() || !topic->closed()) return (!topic || topic->canToggleClosed() || !topic->closed())
? std::optional<QString>() ? std::optional<QString>()
: tr::lng_forum_topic_closed(tr::now); : tr::lng_forum_topic_closed(tr::now);
}); });

View file

@ -20,7 +20,7 @@ void FillTextWithAnimatedSpoilers(
not_null<Element*> view, not_null<Element*> view,
Ui::Text::String &text) { Ui::Text::String &text) {
if (text.hasSpoilers()) { if (text.hasSpoilers()) {
text.setSpoilerLinkFilter([weak = base::make_weak(view.get())]( text.setSpoilerLinkFilter([weak = base::make_weak(view)](
const ClickContext &context) { const ClickContext &context) {
const auto my = context.other.value<ClickHandlerContext>(); const auto my = context.other.value<ClickHandlerContext>();
const auto button = context.button; const auto button = context.button;

View file

@ -967,7 +967,7 @@ AttachSelectorResult MakeJustSelectorMenu(
state.toggling); state.toggling);
}, selector->lifetime()); }, selector->lifetime());
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
controller->enableGifPauseReason( controller->enableGifPauseReason(
Window::GifPauseReason::MediaPreview); Window::GifPauseReason::MediaPreview);
QObject::connect(menu.get(), &QObject::destroyed, [weak] { QObject::connect(menu.get(), &QObject::destroyed, [weak] {
@ -1040,7 +1040,7 @@ AttachSelectorResult AttachSelectorToMenu(
state.toggling); state.toggling);
}, selector->lifetime()); }, selector->lifetime());
const auto weak = base::make_weak(controller.get()); const auto weak = base::make_weak(controller);
controller->enableGifPauseReason( controller->enableGifPauseReason(
Window::GifPauseReason::MediaPreview); Window::GifPauseReason::MediaPreview);
QObject::connect(menu.get(), &QObject::destroyed, [weak] { QObject::connect(menu.get(), &QObject::destroyed, [weak] {

View file

@ -1726,7 +1726,7 @@ void ListWidget::mouseActionFinish(
QVariant::fromValue(ClickHandlerContext{ QVariant::fromValue(ClickHandlerContext{
.itemId = fullId, .itemId = fullId,
.sessionWindow = base::make_weak( .sessionWindow = base::make_weak(
_controller->parentController().get()), _controller->parentController()),
}) })
}); });
return; return;

View file

@ -293,7 +293,7 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
const auto context = ClickContext{ const auto context = ClickContext{
button, button,
QVariant::fromValue(ClickHandlerContext{ QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(window.get()), .sessionWindow = base::make_weak(window),
.peer = peer, .peer = peer,
}) })
}; };
@ -740,7 +740,7 @@ void ActionsFiller::addBotCommandActions(not_null<UserData*> user) {
BotCommandClickHandler('/' + original).onClick(ClickContext{ BotCommandClickHandler('/' + original).onClick(ClickContext{
Qt::LeftButton, Qt::LeftButton,
QVariant::fromValue(ClickHandlerContext{ QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(window.get()), .sessionWindow = base::make_weak(window),
.peer = user, .peer = user,
}) })
}); });

View file

@ -253,7 +253,7 @@ void Inner::mouseReleaseEvent(QMouseEvent *e) {
ActivateClickHandler(window(), activated, { ActivateClickHandler(window(), activated, {
e->button(), e->button(),
QVariant::fromValue(ClickHandlerContext{ QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(_controller.get()), .sessionWindow = base::make_weak(_controller),
}) })
}); });
} }

View file

@ -112,7 +112,7 @@ MuteItem::MuteItem(
st::defaultPopupMenu.showDuration); st::defaultPopupMenu.showDuration);
}, lifetime()); }, lifetime());
const auto weak = base::make_weak(thread.get()); const auto weak = base::make_weak(thread);
setClickedCallback([=] { setClickedCallback([=] {
if (const auto strong = weak.get()) { if (const auto strong = weak.get()) {
strong->owner().notifySettings().update( strong->owner().notifySettings().update(
@ -161,7 +161,7 @@ void MuteBox(not_null<Ui::GenericBox*> box, not_null<Data::Thread*> thread) {
: tr::lng_mute_menu_mute(); : tr::lng_mute_menu_mute();
}) | rpl::flatten_latest(); }) | rpl::flatten_latest();
const auto weak = base::make_weak(thread.get()); const auto weak = base::make_weak(thread);
Ui::ConfirmBox(box, { Ui::ConfirmBox(box, {
.confirmed = [=] { .confirmed = [=] {
if (const auto strong = weak.get()) { if (const auto strong = weak.get()) {
@ -191,7 +191,7 @@ void PickMuteBox(
const auto pickerCallback = TimePickerBox(box, seconds, phrases, 0); const auto pickerCallback = TimePickerBox(box, seconds, phrases, 0);
const auto weak = base::make_weak(thread.get()); const auto weak = base::make_weak(thread);
Ui::ConfirmBox(box, { Ui::ConfirmBox(box, {
.confirmed = [=] { .confirmed = [=] {
const auto muteFor = pickerCallback(); const auto muteFor = pickerCallback();
@ -240,7 +240,7 @@ void FillMuteMenu(
not_null<Ui::PopupMenu*> menu, not_null<Ui::PopupMenu*> menu,
not_null<Data::Thread*> thread, not_null<Data::Thread*> thread,
std::shared_ptr<Ui::Show> show) { std::shared_ptr<Ui::Show> show) {
const auto weak = base::make_weak(thread.get()); const auto weak = base::make_weak(thread);
const auto with = [=](Fn<void(not_null<Data::Thread*> thread)> handler) { const auto with = [=](Fn<void(not_null<Data::Thread*> thread)> handler) {
return [=] { return [=] {
if (const auto strong = weak.get()) { if (const auto strong = weak.get()) {

View file

@ -225,7 +225,7 @@ void SetupUnreadMentionsMenu(
const auto sendRequest = [=]( const auto sendRequest = [=](
not_null<Data::Thread*> thread, not_null<Data::Thread*> thread,
Fn<void()> done) { Fn<void()> done) {
sendOne(base::make_weak(thread.get()), std::move(done), sendOne); sendOne(base::make_weak(thread), std::move(done), sendOne);
}; };
SetupReadAllMenu(button, currentThread, text, sendRequest); SetupReadAllMenu(button, currentThread, text, sendRequest);
} }
@ -266,7 +266,7 @@ void SetupUnreadReactionsMenu(
const auto sendRequest = [=]( const auto sendRequest = [=](
not_null<Data::Thread*> thread, not_null<Data::Thread*> thread,
Fn<void()> done) { Fn<void()> done) {
sendOne(base::make_weak(thread.get()), std::move(done), sendOne); sendOne(base::make_weak(thread), std::move(done), sendOne);
}; };
SetupReadAllMenu(button, currentThread, text, sendRequest); SetupReadAllMenu(button, currentThread, text, sendRequest);
} }

View file

@ -28,7 +28,7 @@ DoneHandler ConcurrentSender::HandlerMaker::MakeDone(
not_null<ConcurrentSender*> sender, not_null<ConcurrentSender*> sender,
Fn<void(FnMut<void()>)> runner) { Fn<void(FnMut<void()>)> runner) {
return [ return [
weak = base::make_weak(sender.get()), weak = base::make_weak(sender),
runner = std::move(runner) runner = std::move(runner)
](const Response &response) mutable { ](const Response &response) mutable {
runner([=]() mutable { runner([=]() mutable {
@ -47,7 +47,7 @@ FailHandler ConcurrentSender::HandlerMaker::MakeFail(
Fn<void(FnMut<void()>)> runner, Fn<void(FnMut<void()>)> runner,
FailSkipPolicy skipPolicy) { FailSkipPolicy skipPolicy) {
return [ return [
weak = base::make_weak(sender.get()), weak = base::make_weak(sender),
runner = std::move(runner), runner = std::move(runner),
skipPolicy skipPolicy
](const Error &error, const Response &response) mutable { ](const Error &error, const Response &response) mutable {

View file

@ -988,7 +988,7 @@ TopBar::TopBar(
ActivateClickHandler(_about, handler, { ActivateClickHandler(_about, handler, {
button, button,
QVariant::fromValue(ClickHandlerContext{ QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(controller.get()), .sessionWindow = base::make_weak(controller),
.botStartAutoSubmit = true, .botStartAutoSubmit = true,
}) })
}); });
@ -1795,7 +1795,7 @@ not_null<Ui::GradientButton*> CreateSubscribeButton(
UrlClickHandler::Open( UrlClickHandler::Open(
local, local,
QVariant::fromValue(ClickHandlerContext{ QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(controller.get()), .sessionWindow = base::make_weak(controller),
.botStartAutoSubmit = true, .botStartAutoSubmit = true,
})); }));
} else { } else {

View file

@ -176,7 +176,7 @@ void Account::startAdded(MTP::AuthKeyPtr localKey) {
} }
void Account::clearLegacyFiles() { void Account::clearLegacyFiles() {
const auto weak = base::make_weak(_owner.get()); const auto weak = base::make_weak(_owner);
ClearLegacyFiles(_basePath, [weak, this]( ClearLegacyFiles(_basePath, [weak, this](
FnMut<void(base::flat_set<QString>&&)> then) { FnMut<void(base::flat_set<QString>&&)> then) {
crl::on_main(weak, [this, then = std::move(then)]() mutable { crl::on_main(weak, [this, then = std::move(then)]() mutable {

View file

@ -155,7 +155,7 @@ void PeerMenuAddMuteSubmenuAction(
const PeerMenuCallback &addAction) { const PeerMenuCallback &addAction) {
const auto notifySettings = &thread->owner().notifySettings(); const auto notifySettings = &thread->owner().notifySettings();
notifySettings->request(thread); notifySettings->request(thread);
const auto weak = base::make_weak(thread.get()); const auto weak = base::make_weak(thread);
const auto with = [=](Fn<void(not_null<Data::Thread*>)> callback) { const auto with = [=](Fn<void(not_null<Data::Thread*>)> callback) {
return [=] { return [=] {
if (const auto strong = weak.get()) { if (const auto strong = weak.get()) {
@ -830,12 +830,24 @@ void Filler::addDeleteContact() {
} }
void Filler::addDeleteTopic() { void Filler::addDeleteTopic() {
if (!_topic/* || !_topic->canDelete()*/) { if (!_topic || !_topic->canDelete()) {
return; return;
} }
const auto controller = _controller;
const auto weak = base::make_weak(_topic);
const auto callback = [=] {
if (const auto strong = weak.get()) {
PeerMenuDeleteTopicWithConfirmation(controller, strong);
}
};
_addAction({
.text = tr::lng_forum_topic_delete(tr::now),
.handler = callback,
.icon = &st::menuIconDeleteAttention,
.isAttention = true,
});
} }
void Filler::addManageTopic() { void Filler::addManageTopic() {
if (!_topic || !_topic->canEdit()) { if (!_topic || !_topic->canEdit()) {
return; return;
@ -971,6 +983,7 @@ void Filler::addCreateTopic() {
} }
const auto peer = _peer; const auto peer = _peer;
const auto controller = _controller; const auto controller = _controller;
_addAction(PeerMenuCallback::Args{ .isSeparator = true });
_addAction(tr::lng_forum_create_topic(tr::now), [=] { _addAction(tr::lng_forum_create_topic(tr::now), [=] {
if (const auto forum = peer->forum()) { if (const auto forum = peer->forum()) {
controller->show(Box( controller->show(Box(
@ -979,7 +992,6 @@ void Filler::addCreateTopic() {
forum->history())); forum->history()));
} }
}, &st::menuIconDiscussion); }, &st::menuIconDiscussion);
_addAction(PeerMenuCallback::Args{ .isSeparator = true });
} }
void Filler::addViewAsMessages() { void Filler::addViewAsMessages() {
@ -1004,7 +1016,6 @@ void Filler::fillChatsListActions() {
if (!_peer || !_peer->isForum()) { if (!_peer || !_peer->isForum()) {
return; return;
} }
addCreateTopic();
addViewAsMessages(); addViewAsMessages();
addInfo(); addInfo();
addNewMembers(); addNewMembers();
@ -1017,6 +1028,7 @@ void Filler::fillChatsListActions() {
} else { } else {
addJoinChat(); addJoinChat();
} }
addCreateTopic();
} }
void Filler::fillContextMenuActions() { void Filler::fillContextMenuActions() {
@ -1082,10 +1094,10 @@ void Filler::fillRepliesActions() {
addInfo(); addInfo();
addManageTopic(); addManageTopic();
addManageChat(); addManageChat();
addDeleteTopic();
} }
addCreatePoll(); addCreatePoll();
addToggleTopicClosed(); addToggleTopicClosed();
addDeleteTopic();
} }
void Filler::fillScheduledActions() { void Filler::fillScheduledActions() {
@ -1159,6 +1171,49 @@ void PeerMenuDeleteContact(
Ui::LayerOption::CloseOther); Ui::LayerOption::CloseOther);
} }
void PeerMenuDeleteTopicWithConfirmation(
not_null<Window::SessionNavigation*> navigation,
not_null<Data::ForumTopic*> topic) {
const auto weak = base::make_weak(topic);
const auto callback = [=](Fn<void()> &&close) {
close();
if (const auto strong = weak.get()) {
PeerMenuDeleteTopic(navigation, strong);
}
};
navigation->parentController()->show(Ui::MakeConfirmBox({
.text = tr::lng_forum_topic_delete_sure(tr::now),
.confirmed = callback,
.confirmText = tr::lng_box_delete(),
.confirmStyle = &st::attentionBoxButton,
}));
}
void PeerMenuDeleteTopic(
not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel,
MsgId rootId) {
const auto api = &channel->session().api();
api->request(MTPchannels_DeleteTopicHistory(
channel->inputChannel,
MTP_int(rootId)
)).done([=](const MTPmessages_AffectedHistory &result) {
const auto offset = api->applyAffectedHistory(channel, result);
if (offset > 0) {
PeerMenuDeleteTopic(navigation, channel, rootId);
} else if (const auto forum = channel->forum()) {
forum->applyTopicDeleted(rootId);
}
}).send();
}
void PeerMenuDeleteTopic(
not_null<Window::SessionNavigation*> navigation,
not_null<Data::ForumTopic*> topic) {
PeerMenuDeleteTopic(navigation, topic->channel(), topic->rootId());
}
void PeerMenuShareContactBox( void PeerMenuShareContactBox(
not_null<Window::SessionNavigation*> navigation, not_null<Window::SessionNavigation*> navigation,
not_null<UserData*> user) { not_null<UserData*> user) {

View file

@ -24,6 +24,7 @@ namespace Data {
class Folder; class Folder;
class Session; class Session;
struct ForwardDraft; struct ForwardDraft;
class ForumTopic;
} // namespace Data } // namespace Data
namespace Dialogs { namespace Dialogs {
@ -74,6 +75,12 @@ void PeerMenuCreatePoll(
PollData::Flags disabled = PollData::Flags(), PollData::Flags disabled = PollData::Flags(),
Api::SendType sendType = Api::SendType::Normal, Api::SendType sendType = Api::SendType::Normal,
SendMenu::Type sendMenuType = SendMenu::Type::Scheduled); SendMenu::Type sendMenuType = SendMenu::Type::Scheduled);
void PeerMenuDeleteTopicWithConfirmation(
not_null<Window::SessionNavigation*> navigation,
not_null<Data::ForumTopic*> topic);
void PeerMenuDeleteTopic(
not_null<Window::SessionNavigation*> navigation,
not_null<Data::ForumTopic*> topic);
struct ClearChat { struct ClearChat {
}; };

@ -1 +1 @@
Subproject commit 2a94813b6aa1f8645fd9de88a78981356259fab7 Subproject commit 12814dcf5067d687c47c710689902fd1219bec4f