mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 05:07:10 +02:00
Support gifts pinning.
This commit is contained in:
parent
7840fa6d90
commit
0f74456f30
14 changed files with 219 additions and 9 deletions
|
@ -3428,6 +3428,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_gift_display_done_channel" = "The gift is now shown in channel's Gifts.";
|
||||
"lng_gift_display_done_hide" = "The gift is now hidden from your profile page.";
|
||||
"lng_gift_display_done_hide_channel" = "The gift is now hidden from channel's Gifts.";
|
||||
"lng_gift_pinned_done" = "The gift will always be shown on top.";
|
||||
"lng_gift_got_stars#one" = "You got **{count} Star** for this gift.";
|
||||
"lng_gift_got_stars#other" = "You got **{count} Stars** for this gift.";
|
||||
"lng_gift_channel_got#one" = "Channel got **{count} Star** for this gift.";
|
||||
|
|
|
@ -904,6 +904,7 @@ std::optional<Data::SavedStarGift> FromTL(
|
|||
.date = data.vdate().v,
|
||||
.upgradable = data.is_can_upgrade(),
|
||||
.anonymous = data.is_name_hidden(),
|
||||
.pinned = data.is_pinned_to_top(),
|
||||
.hidden = data.is_unsaved(),
|
||||
.mine = to->isSelf(),
|
||||
};
|
||||
|
|
|
@ -70,6 +70,7 @@ struct CreditsHistoryEntry final {
|
|||
uint64 giftChannelSavedId = 0;
|
||||
uint64 stargiftId = 0;
|
||||
std::shared_ptr<UniqueGift> uniqueGift;
|
||||
Fn<std::vector<CreditsHistoryEntry>()> pinnedSavedGifts;
|
||||
StarsAmount starrefAmount;
|
||||
int starrefCommission = 0;
|
||||
uint64 starrefRecipientId = 0;
|
||||
|
@ -93,6 +94,7 @@ struct CreditsHistoryEntry final {
|
|||
bool giftTransferred : 1 = false;
|
||||
bool giftRefunded : 1 = false;
|
||||
bool giftUpgraded : 1 = false;
|
||||
bool giftPinned : 1 = false;
|
||||
bool savedToProfile : 1 = false;
|
||||
bool fromGiftsList : 1 = false;
|
||||
bool fromGiftSlug : 1 = false;
|
||||
|
|
|
@ -87,6 +87,8 @@ struct GiftUpdate {
|
|||
Convert,
|
||||
Transfer,
|
||||
Delete,
|
||||
Pin,
|
||||
Unpin,
|
||||
};
|
||||
|
||||
Data::SavedStarGiftId id;
|
||||
|
|
|
@ -132,6 +132,7 @@ struct SavedStarGift {
|
|||
TimeId date = 0;
|
||||
bool upgradable = false;
|
||||
bool anonymous = false;
|
||||
bool pinned = false;
|
||||
bool hidden = false;
|
||||
bool mine = false;
|
||||
};
|
||||
|
|
|
@ -223,6 +223,8 @@ darkGiftNftWear: icon {{ "menu/nft_wear", groupCallMembersFg }};
|
|||
darkGiftNftTakeOff: icon {{ "menu/nft_takeoff", groupCallMembersFg }};
|
||||
darkGiftHide: icon {{ "menu/stealth", groupCallMembersFg }};
|
||||
darkGiftShow: icon {{ "menu/show_in_chat", groupCallMembersFg }};
|
||||
darkGiftPin: icon {{ "menu/pin", groupCallMembersFg }};
|
||||
darkGiftUnpin: icon {{ "menu/unpin", groupCallMembersFg }};
|
||||
darkGiftPalette: TextPalette(defaultTextPalette) {
|
||||
linkFg: mediaviewTextLinkFg;
|
||||
monoFg: groupCallMembersFg;
|
||||
|
|
|
@ -463,6 +463,24 @@ void GiftButton::paintEvent(QPaintEvent *e) {
|
|||
position.y() - rubberOut,
|
||||
cached);
|
||||
}
|
||||
|
||||
v::match(_descriptor, [](const GiftTypePremium &) {
|
||||
}, [&](const GiftTypeStars &data) {
|
||||
if (unique && data.pinned) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
const auto &icon = st::giftBoxPinIcon;
|
||||
const auto skip = st::giftBoxUserpicSkip;
|
||||
const auto add = (st::giftBoxUserpicSize - icon.width()) / 2;
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(unique->backdrop.patternColor);
|
||||
const auto rect = QRect(
|
||||
QPoint(_extend.left() + skip, _extend.top() + skip),
|
||||
QSize(icon.width() + 2 * add, icon.height() + 2 * add));
|
||||
p.drawEllipse(rect);
|
||||
icon.paintInCenter(p, rect);
|
||||
}
|
||||
});
|
||||
|
||||
if (!_button.isEmpty()) {
|
||||
p.setBrush(unique
|
||||
? QBrush(QColor(255, 255, 255, .2 * 255))
|
||||
|
|
|
@ -56,7 +56,9 @@ struct GiftTypePremium {
|
|||
struct GiftTypeStars {
|
||||
Data::StarGift info;
|
||||
PeerData *from = nullptr;
|
||||
TimeId date = 0;
|
||||
bool userpic = false;
|
||||
bool pinned = false;
|
||||
bool hidden = false;
|
||||
bool mine = false;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_app_config.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
@ -50,7 +51,9 @@ constexpr auto kPerPage = 50;
|
|||
.from = ((gift.anonymous || !gift.fromId)
|
||||
? nullptr
|
||||
: to->owner().peer(gift.fromId).get()),
|
||||
.date = gift.date,
|
||||
.userpic = !gift.info.unique,
|
||||
.pinned = gift.pinned,
|
||||
.hidden = gift.hidden,
|
||||
.mine = to->isSelf(),
|
||||
};
|
||||
|
@ -104,6 +107,9 @@ private:
|
|||
void showMenuFor(not_null<GiftButton*> button, QPoint point);
|
||||
void refreshAbout();
|
||||
|
||||
void markPinned(std::vector<Entry>::iterator i);
|
||||
void markUnpinned(std::vector<Entry>::iterator i);
|
||||
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
const not_null<Window::SessionController*> _window;
|
||||
|
@ -203,6 +209,13 @@ void InnerWidget::subscribeToUpdates() {
|
|||
view.manageId = {};
|
||||
}
|
||||
}
|
||||
} else if (update.action == Action::Pin
|
||||
|| update.action == Action::Unpin) {
|
||||
if (update.action == Action::Pin) {
|
||||
markPinned(i);
|
||||
} else {
|
||||
markUnpinned(i);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -210,6 +223,65 @@ void InnerWidget::subscribeToUpdates() {
|
|||
}, lifetime());
|
||||
}
|
||||
|
||||
void InnerWidget::markPinned(std::vector<Entry>::iterator i) {
|
||||
const auto index = int(i - begin(_entries));
|
||||
|
||||
i->gift.pinned = true;
|
||||
v::match(i->descriptor, [](const GiftTypePremium &) {
|
||||
}, [&](GiftTypeStars &data) {
|
||||
data.pinned = true;
|
||||
});
|
||||
if (index) {
|
||||
std::rotate(begin(_entries), i, i + 1);
|
||||
}
|
||||
auto unpin = end(_entries);
|
||||
const auto session = &_window->session();
|
||||
const auto limit = session->appConfig().pinnedGiftsLimit();
|
||||
if (limit < _entries.size()) {
|
||||
const auto j = begin(_entries) + limit;
|
||||
if (j->gift.pinned) {
|
||||
unpin = j;
|
||||
}
|
||||
}
|
||||
for (auto &view : _views) {
|
||||
if (view.index <= index) {
|
||||
view.index = -1;
|
||||
view.manageId = {};
|
||||
}
|
||||
}
|
||||
if (unpin != end(_entries)) {
|
||||
markUnpinned(unpin);
|
||||
}
|
||||
}
|
||||
|
||||
void InnerWidget::markUnpinned(std::vector<Entry>::iterator i) {
|
||||
const auto index = int(i - begin(_entries));
|
||||
|
||||
i->gift.pinned = false;
|
||||
v::match(i->descriptor, [](const GiftTypePremium &) {
|
||||
}, [&](GiftTypeStars &data) {
|
||||
data.pinned = false;
|
||||
});
|
||||
auto after = index + 1;
|
||||
for (auto j = i + 1; j != end(_entries); ++j) {
|
||||
if (!j->gift.pinned && j->gift.date <= i->gift.date) {
|
||||
break;
|
||||
}
|
||||
++after;
|
||||
}
|
||||
if (after == _entries.size()) {
|
||||
_entries.erase(i);
|
||||
} else if (after > index + 1) {
|
||||
std::rotate(i, i + 1, begin(_entries) + after);
|
||||
}
|
||||
for (auto &view : _views) {
|
||||
if (view.index >= index) {
|
||||
view.index = -1;
|
||||
view.manageId = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InnerWidget::visibleTopBottomUpdated(
|
||||
int visibleTop,
|
||||
int visibleBottom) {
|
||||
|
@ -412,9 +484,30 @@ void InnerWidget::showMenuFor(not_null<GiftButton*> button, QPoint point) {
|
|||
return;
|
||||
}
|
||||
|
||||
const auto entry = ::Settings::SavedStarGiftEntry(
|
||||
auto entry = ::Settings::SavedStarGiftEntry(
|
||||
_peer,
|
||||
_entries[index].gift);
|
||||
auto pinnedIds = std::vector<Data::SavedStarGiftId>();
|
||||
for (const auto &entry : _entries) {
|
||||
if (entry.gift.pinned) {
|
||||
pinnedIds.push_back(entry.gift.manageId);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
entry.pinnedSavedGifts = [pinnedIds, peer = _peer] {
|
||||
auto result = std::vector<Data::CreditsHistoryEntry>();
|
||||
result.reserve(pinnedIds.size());
|
||||
for (const auto &id : pinnedIds) {
|
||||
result.push_back({
|
||||
.bareMsgId = uint64(id.userMessageId().bare),
|
||||
.bareEntryOwnerId = id.chat() ? id.chat()->id.value : 0,
|
||||
.giftChannelSavedId = id.chatSavedId(),
|
||||
.stargift = true,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
};
|
||||
_menu = base::make_unique_q<Ui::PopupMenu>(this, st::popupMenuWithIcons);
|
||||
::Settings::FillSavedStarGiftMenu(
|
||||
_controller->uiShow(),
|
||||
|
|
|
@ -89,6 +89,10 @@ int AppConfig::paidMessageCommission() const {
|
|||
return get<int>(u"stars_paid_message_commission_permille"_q, 850);
|
||||
}
|
||||
|
||||
int AppConfig::pinnedGiftsLimit() const {
|
||||
return get<int>(u"stargifts_pinned_to_top_limit"_q, 6);
|
||||
}
|
||||
|
||||
void AppConfig::refresh(bool force) {
|
||||
if (_requestId || !_api) {
|
||||
if (force) {
|
||||
|
|
|
@ -77,6 +77,8 @@ public:
|
|||
[[nodiscard]] int paidMessageStarsMax() const;
|
||||
[[nodiscard]] int paidMessageCommission() const;
|
||||
|
||||
[[nodiscard]] int pinnedGiftsLimit() const;
|
||||
|
||||
void refresh(bool force = false);
|
||||
|
||||
private:
|
||||
|
|
|
@ -221,6 +221,55 @@ void ToggleStarGiftSaved(
|
|||
}).send();
|
||||
}
|
||||
|
||||
void ToggleStarGiftPinned(
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
Data::SavedStarGiftId savedId,
|
||||
std::vector<Data::SavedStarGiftId> already,
|
||||
bool pinned,
|
||||
Fn<void(bool)> done = nullptr) {
|
||||
already.erase(ranges::remove(already, savedId), end(already));
|
||||
if (pinned) {
|
||||
already.insert(begin(already), savedId);
|
||||
const auto limit = show->session().appConfig().pinnedGiftsLimit();
|
||||
if (already.size() > limit) {
|
||||
already.erase(begin(already) + limit, end(already));
|
||||
}
|
||||
}
|
||||
|
||||
auto inputs = QVector<MTPInputSavedStarGift>();
|
||||
inputs.reserve(already.size());
|
||||
for (const auto &id : already) {
|
||||
inputs.push_back(Api::InputSavedStarGiftId(id));
|
||||
}
|
||||
|
||||
const auto api = &show->session().api();
|
||||
const auto peer = savedId.chat()
|
||||
? savedId.chat()
|
||||
: show->session().user();
|
||||
api->request(MTPpayments_ToggleStarGiftsPinnedToTop(
|
||||
peer->input,
|
||||
MTP_vector<MTPInputSavedStarGift>(std::move(inputs))
|
||||
)).done([=] {
|
||||
using GiftAction = Data::GiftUpdate::Action;
|
||||
show->session().data().notifyGiftUpdate({
|
||||
.id = savedId,
|
||||
.action = (pinned ? GiftAction::Pin : GiftAction::Unpin),
|
||||
});
|
||||
|
||||
if (const auto onstack = done) {
|
||||
onstack(true);
|
||||
}
|
||||
if (pinned) {
|
||||
show->showToast(tr::lng_gift_pinned_done(tr::now));
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
if (const auto onstack = done) {
|
||||
onstack(false);
|
||||
}
|
||||
show->showToast(error.type());
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ConfirmConvertStarGift(
|
||||
std::shared_ptr<Ui::Show> show,
|
||||
rpl::producer<TextWithEntities> confirmText,
|
||||
|
@ -861,7 +910,41 @@ void FillUniqueGiftMenu(
|
|||
const Data::CreditsHistoryEntry &e,
|
||||
SavedStarGiftMenuType type,
|
||||
CreditsEntryBoxStyleOverrides st) {
|
||||
const auto session = &show->session();
|
||||
const auto savedId = EntryToSavedStarGiftId(session, e);
|
||||
const auto giftChannel = savedId.chat();
|
||||
const auto canToggle = savedId
|
||||
&& e.id.isEmpty()
|
||||
&& (e.in || (giftChannel && giftChannel->canManageGifts()))
|
||||
&& !e.giftTransferred
|
||||
&& !e.giftRefunded;
|
||||
|
||||
const auto unique = e.uniqueGift;
|
||||
if (unique
|
||||
&& canToggle
|
||||
&& e.savedToProfile
|
||||
&& type == SavedStarGiftMenuType::List) {
|
||||
const auto already = [session, entries = e.pinnedSavedGifts] {
|
||||
Expects(entries != nullptr);
|
||||
|
||||
auto list = entries();
|
||||
auto result = std::vector<Data::SavedStarGiftId>();
|
||||
result.reserve(list.size());
|
||||
for (const auto &entry : list) {
|
||||
result.push_back(EntryToSavedStarGiftId(session, entry));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
if (e.giftPinned) {
|
||||
menu->addAction(tr::lng_context_unpin_from_top(tr::now), [=] {
|
||||
ToggleStarGiftPinned(show, savedId, already(), false);
|
||||
}, st.unpin ? st.unpin : &st::menuIconUnpin);
|
||||
} else {
|
||||
menu->addAction(tr::lng_context_pin_to_top(tr::now), [=] {
|
||||
ToggleStarGiftPinned(show, savedId, already(), true);
|
||||
}, st.pin ? st.pin : &st::menuIconPin);
|
||||
}
|
||||
}
|
||||
if (unique) {
|
||||
const auto local = u"nft/"_q + unique->slug;
|
||||
const auto url = show->session().createInternalLinkFull(local);
|
||||
|
@ -879,14 +962,7 @@ void FillUniqueGiftMenu(
|
|||
}, st.share ? st.share : &st::menuIconShare);
|
||||
}
|
||||
|
||||
const auto savedId = EntryToSavedStarGiftId(&show->session(), e);
|
||||
const auto giftChannel = savedId.chat();
|
||||
const auto canToggleVisibility = savedId
|
||||
&& e.id.isEmpty()
|
||||
&& (e.in || (giftChannel && giftChannel->canManageGifts()))
|
||||
&& !e.giftTransferred
|
||||
&& !e.giftRefunded;
|
||||
if (canToggleVisibility && type == SavedStarGiftMenuType::List) {
|
||||
if (canToggle && type == SavedStarGiftMenuType::List) {
|
||||
if (e.savedToProfile) {
|
||||
menu->addAction(tr::lng_gift_menu_hide(tr::now), [=] {
|
||||
ToggleStarGiftSaved(show, savedId, false);
|
||||
|
@ -958,6 +1034,8 @@ CreditsEntryBoxStyleOverrides DarkCreditsEntryBoxStyle() {
|
|||
.takeoff = &st::darkGiftNftTakeOff,
|
||||
.show = &st::darkGiftShow,
|
||||
.hide = &st::darkGiftHide,
|
||||
.pin = &st::darkGiftPin,
|
||||
.unpin = &st::darkGiftUnpin,
|
||||
.shareBox = std::make_shared<ShareBoxStyleOverrides>(
|
||||
DarkShareBoxStyle()),
|
||||
.giftWearBox = std::make_shared<GiftWearBoxStyleOverride>(
|
||||
|
@ -1951,6 +2029,7 @@ Data::CreditsHistoryEntry SavedStarGiftEntry(
|
|||
.converted = false,
|
||||
.anonymous = data.anonymous,
|
||||
.stargift = true,
|
||||
.giftPinned = data.pinned,
|
||||
.savedToProfile = !data.hidden,
|
||||
.fromGiftsList = true,
|
||||
.canUpgradeGift = data.upgradable,
|
||||
|
|
|
@ -115,6 +115,8 @@ struct CreditsEntryBoxStyleOverrides {
|
|||
const style::icon *takeoff = nullptr;
|
||||
const style::icon *show = nullptr;
|
||||
const style::icon *hide = nullptr;
|
||||
const style::icon *pin = nullptr;
|
||||
const style::icon *unpin = nullptr;
|
||||
std::shared_ptr<ShareBoxStyleOverrides> shareBox;
|
||||
std::shared_ptr<GiftWearBoxStyleOverride> giftWearBox;
|
||||
};
|
||||
|
|
|
@ -178,6 +178,7 @@ giftListAboutMargin: margins(12px, 24px, 12px, 24px);
|
|||
giftBoxEmojiToggleTop: 7px;
|
||||
giftBoxLimitTop: 28px;
|
||||
giftBoxLockMargins: margins(-2px, 1px, 0px, 0px);
|
||||
giftBoxPinIcon: icon {{ "dialogs/dialogs_pinned", premiumButtonFg }};
|
||||
|
||||
creditsHistoryEntriesList: PeerList(defaultPeerList) {
|
||||
padding: margins(
|
||||
|
|
Loading…
Add table
Reference in a new issue