Allow editing/deleting collections.

This commit is contained in:
John Preston
2025-07-24 16:57:54 +04:00
parent 2b16b0fc7c
commit 448356f534
6 changed files with 189 additions and 16 deletions
+2
View File
@@ -3765,6 +3765,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_collection_limit_title" = "Limit Reached";
"lng_gift_collection_limit_text" = "Please remove one of the existing collections to add a new one.";
"lng_gift_collection_delete" = "Delete Collection";
"lng_gift_collection_delete_sure" = "Are you sure you want to delete this collection?";
"lng_gift_collection_delete_button" = "Delete";
"lng_gift_collection_add_to" = "Add to Collection";
"lng_accounts_limit_title" = "Limit Reached";
@@ -25,26 +25,29 @@ namespace {
constexpr auto kCollectionNameLimit = 12;
} // namespace
void NewCollectionBox(
void EditCollectionBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer,
int id,
Data::SavedStarGiftId addId,
Fn<void(MTPStarGiftCollection)> added) {
QString currentName,
Fn<void(MTPStarGiftCollection)> finished) {
box->setTitle(tr::lng_gift_collection_new_title());
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
tr::lng_gift_collection_new_text(),
(id
? tr::lng_gift_collection_edit()
: tr::lng_gift_collection_new_text()),
st::collectionAbout));
const auto title = box->addRow(
object_ptr<Ui::InputField>(
box,
st::collectionNameField,
tr::lng_gift_collection_new_ph()));
tr::lng_gift_collection_new_ph(),
currentName));
title->setMaxLength(kCollectionNameLimit * 2);
box->setFocusCallback([=] {
title->setFocusFast();
@@ -56,7 +59,10 @@ void NewCollectionBox(
const auto session = &peer->session();
const auto creating = std::make_shared<bool>(false);
box->addButton(tr::lng_gift_collection_new_create(), [=] {
auto text = id
? tr::lng_settings_save()
: tr::lng_gift_collection_new_create();
box->addButton(std::move(text), [=] {
if (*creating) {
return;
}
@@ -72,22 +78,19 @@ void NewCollectionBox(
ids.push_back(Api::InputSavedStarGiftId(addId));
}
const auto weak = base::make_weak(box);
session->api().request(MTPpayments_CreateStarGiftCollection(
peer->input,
MTP_string(text),
MTP_vector<MTPInputSavedStarGift>(ids)
)).done([=](const MTPStarGiftCollection &result) {
const auto done = [=](const MTPStarGiftCollection &result) {
*creating = false;
if (const auto onstack = added) {
if (const auto onstack = finished) {
onstack(result);
}
if (const auto strong = weak.get()) {
strong->closeBox();
}
}).fail([=](const MTP::Error &error) {
};
const auto fail = [=](const MTP::Error &error) {
*creating = false;
const auto &type = error.type();
if (type == u""_q) {
if (type == u"COLLECTIONS_TOO_MANY"_q) {
show->show(Ui::MakeInformBox({
.text = tr::lng_gift_collection_limit_text(),
.confirmText = tr::lng_box_ok(),
@@ -99,13 +102,54 @@ void NewCollectionBox(
} else {
show->showToast(error.type());
}
}).send();
};
if (id) {
using Flag = MTPpayments_UpdateStarGiftCollection::Flag;
session->api().request(MTPpayments_UpdateStarGiftCollection(
MTP_flags(Flag::f_title),
peer->input,
MTP_int(id),
MTP_string(text),
MTPVector<MTPInputSavedStarGift>(),
MTPVector<MTPInputSavedStarGift>(),
MTPVector<MTPInputSavedStarGift>()
)).done(done).fail(fail).send();
} else {
session->api().request(MTPpayments_CreateStarGiftCollection(
peer->input,
MTP_string(text),
MTP_vector<MTPInputSavedStarGift>(ids)
)).done(done).fail(fail).send();
}
});
box->addButton(tr::lng_cancel(), [=] {
box->closeBox();
});
}
} // namespace
void NewCollectionBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer,
Data::SavedStarGiftId addId,
Fn<void(MTPStarGiftCollection)> added) {
EditCollectionBox(box, navigation, peer, 0, addId, QString(), added);
}
void EditCollectionNameBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer,
int id,
QString current,
Fn<void(QString)> done) {
EditCollectionBox(box, navigation, peer, id, {}, current, [=](
const MTPStarGiftCollection &result) {
done(qs(result.data().vtitle()));
});
}
} // namespace Info::PeerGifts
@@ -28,4 +28,12 @@ void NewCollectionBox(
Data::SavedStarGiftId addId,
Fn<void(MTPStarGiftCollection)> added);
void EditCollectionNameBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer,
int id,
QString current,
Fn<void(QString)> done);
} // namespace Info::PeerGifts
@@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/peer_gifts/info_peer_gifts_collections.h"
#include "info/peer_gifts/info_peer_gifts_common.h"
#include "info/info_controller.h"
#include "ui/boxes/confirm_box.h"
#include "ui/controls/sub_tabs.h"
#include "ui/layers/generic_box.h"
#include "ui/text/text_utilities.h"
@@ -173,9 +174,15 @@ private:
void validateButtons();
void showGift(int index);
void showMenuFor(not_null<GiftButton*> button, QPoint point);
void showMenuForCollection(int id);
void editCollectionName(int id);
void confirmDeleteCollection(int id);
void refreshAbout();
void refreshCollectionsTabs();
void collectionRenamed(int id, QString name);
void collectionRemoved(int id);
void markPinned(std::vector<Entry>::iterator i);
void markUnpinned(std::vector<Entry>::iterator i);
@@ -776,6 +783,60 @@ auto InnerWidget::pinnedSavedGifts()
};
}
void InnerWidget::showMenuForCollection(int id) {
if (_menu || _addingToCollectionId) {
return;
}
_menu = base::make_unique_q<Ui::PopupMenu>(this, st::popupMenuWithIcons);
const auto addAction = Ui::Menu::CreateAddActionCallback(_menu);
addAction(tr::lng_gift_collection_add_title(tr::now), [=] {
editCollectionGifts(id);
}, &st::menuIconGiftPremium);
addAction(tr::lng_gift_collection_edit(tr::now), [=] {
editCollectionName(id);
}, &st::menuIconEdit);
addAction({
.text = tr::lng_gift_collection_delete(tr::now),
.handler = [=] { confirmDeleteCollection(id); },
.icon = &st::menuIconDeleteAttention,
.isAttention = true,
});
_menu->popup(QCursor::pos());
}
void InnerWidget::editCollectionName(int id) {
const auto done = [=](QString name) {
collectionRenamed(id, name);
};
const auto i = ranges::find(_collections, id, &Data::GiftCollection::id);
if (i == end(_collections)) {
return;
}
_window->uiShow()->show(Box(
EditCollectionNameBox,
_window,
peer(),
id,
i->title,
done));
}
void InnerWidget::confirmDeleteCollection(int id) {
const auto done = [=](Fn<void()> close) {
_window->session().api().request(
MTPpayments_DeleteStarGiftCollection(_peer->input, MTP_int(id))
).send();
collectionRemoved(id);
close();
};
_window->uiShow()->show(Ui::MakeConfirmBox({
.text = tr::lng_gift_collection_delete_sure(),
.confirmed = crl::guard(this, done),
.confirmText = tr::lng_gift_collection_delete_button(),
.confirmStyle = &st::attentionBoxButton,
}));
}
void InnerWidget::showMenuFor(not_null<GiftButton*> button, QPoint point) {
if (_menu || _addingToCollectionId) {
return;
@@ -1126,12 +1187,57 @@ void InnerWidget::refreshCollectionsTabs() {
_descriptorChanges.fire(std::move(now));
}
}, _collectionsTabs->lifetime());
_collectionsTabs->contextMenuRequests(
) | rpl::start_with_next([=](const QString &id) {
if (id == u"add"_q
|| id == u"all"_q
|| !_peer->canManageGifts()) {
return;
}
showMenuForCollection(id.toInt());
}, _collectionsTabs->lifetime());
} else {
_collectionsTabs->setTabs(std::move(tabs), context);
}
resizeToWidth(width());
}
void InnerWidget::collectionRenamed(int id, QString name) {
const auto i = ranges::find(_collections, id, &Data::GiftCollection::id);
if (i != end(_collections)) {
i->title = name;
refreshCollectionsTabs();
}
}
void InnerWidget::collectionRemoved(int id) {
auto now = _descriptor.current();
if (now.collectionId == id) {
now.collectionId = 0;
_descriptorChanges.fire(std::move(now));
}
Assert(_entries != &_perCollection[id]);
_perCollection.remove(id);
const auto removeFrom = [&](Entries &entries) {
for (auto &entry : entries.list) {
entry.gift.collectionIds.erase(
ranges::remove(entry.gift.collectionIds, id),
end(entry.gift.collectionIds));
}
};
removeFrom(_all);
for (auto &[_, entries] : _perCollection) {
removeFrom(entries);
}
const auto i = ranges::find(_collections, id, &Data::GiftCollection::id);
if (i != end(_collections)) {
_collections.erase(i);
refreshCollectionsTabs();
}
}
int InnerWidget::resizeGetHeight(int width) {
const auto padding = st::giftBoxPadding;
const auto count = int(_list->size());
@@ -95,6 +95,10 @@ rpl::producer<QString> SubTabs::activated() const {
return _activated.events();
}
rpl::producer<QString> SubTabs::contextMenuRequests() const {
return _contextMenuRequests.events();
}
void SubTabs::setSelected(int index) {
const auto was = (_selected >= 0);
const auto now = (index >= 0);
@@ -195,6 +199,12 @@ void SubTabs::mouseReleaseEvent(QMouseEvent *e) {
}
}
void SubTabs::contextMenuEvent(QContextMenuEvent *e) {
if (_selected >= 0 && _selected < _buttons.size()) {
_contextMenuRequests.fire_copy(_buttons[_selected].tab.id);
}
}
void SubTabs::paintEvent(QPaintEvent *e) {
auto p = QPainter(this);
auto hq = PainterHighQualityEnabler(p);
@@ -43,6 +43,7 @@ public:
void setActiveTab(const QString &id);
[[nodiscard]] rpl::producer<QString> activated() const;
[[nodiscard]] rpl::producer<QString> contextMenuRequests() const;
private:
struct Button {
@@ -57,6 +58,7 @@ private:
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
void paintEvent(QPaintEvent *e) override;
bool eventHook(QEvent *e) override;
@@ -66,6 +68,7 @@ private:
std::vector<Button> _buttons;
rpl::event_stream<QString> _activated;
rpl::event_stream<QString> _contextMenuRequests;
int _dragx = 0;
int _pressx = 0;
float64 _dragscroll = 0.;