mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Nice selection of gifts for a collection.
This commit is contained in:
@@ -1315,6 +1315,8 @@ PRIVATE
|
||||
mtproto/special_config_request.cpp
|
||||
mtproto/special_config_request.h
|
||||
mtproto/type_utils.h
|
||||
overview/overview_checkbox.cpp
|
||||
overview/overview_checkbox.h
|
||||
overview/overview_layout.cpp
|
||||
overview/overview_layout.h
|
||||
overview/overview_layout_delegate.h
|
||||
|
||||
@@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "lang/lang_keys.h"
|
||||
#include "info/channel_statistics/earn/earn_icons.h"
|
||||
#include "main/main_session.h"
|
||||
#include "overview/overview_checkbox.h"
|
||||
#include "settings/settings_credits_graphics.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/format_values.h"
|
||||
@@ -34,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_credits.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_overview.h"
|
||||
#include "styles/style_premium.h"
|
||||
|
||||
namespace Info::PeerGifts {
|
||||
@@ -78,6 +80,18 @@ GiftButton::~GiftButton() {
|
||||
unsubscribe();
|
||||
}
|
||||
|
||||
void GiftButton::onStateChanged(State was, StateChangeSource source) {
|
||||
if (_check) {
|
||||
const auto diff = state() ^ was;
|
||||
if (diff & State::Enum::Over) {
|
||||
_check->setActive(state() & State::Enum::Over);
|
||||
}
|
||||
if (diff & State::Enum::Down) {
|
||||
_check->setPressed(state() & State::Enum::Down);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GiftButton::unsubscribe() {
|
||||
if (base::take(_subscribed)) {
|
||||
_userpic->subscribeToUpdates(nullptr);
|
||||
@@ -85,6 +99,16 @@ void GiftButton::unsubscribe() {
|
||||
}
|
||||
|
||||
void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
|
||||
_mode = mode;
|
||||
|
||||
if (_mode != GiftButtonMode::Selection) {
|
||||
_check = nullptr;
|
||||
} else if (!_check) {
|
||||
_check = std::make_unique<Overview::Layout::Checkbox>(
|
||||
[=] { update(); },
|
||||
st::overviewSmallCheck);
|
||||
}
|
||||
|
||||
const auto unique = v::is<GiftTypeStars>(descriptor)
|
||||
? v::get<GiftTypeStars>(descriptor).info.unique.get()
|
||||
: nullptr;
|
||||
@@ -106,7 +130,6 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
|
||||
_descriptor = descriptor;
|
||||
_resalePrice = resalePrice;
|
||||
const auto resale = (_resalePrice > 0);
|
||||
_small = (mode != Mode::Full);
|
||||
v::match(descriptor, [&](const GiftTypePremium &data) {
|
||||
const auto months = data.months;
|
||||
_text = Ui::Text::String(st::giftBoxGiftHeight / 4);
|
||||
@@ -147,12 +170,12 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
|
||||
const auto soldOut = data.info.limitedCount
|
||||
&& !data.userpic
|
||||
&& !data.info.limitedLeft;
|
||||
_userpic = !data.userpic
|
||||
_userpic = (!data.userpic || _mode == GiftButtonMode::Selection)
|
||||
? nullptr
|
||||
: data.from
|
||||
? Ui::MakeUserpicThumbnail(data.from)
|
||||
: Ui::MakeHiddenAuthorThumbnail();
|
||||
if (_small && !resale) {
|
||||
if (small() && !resale) {
|
||||
_price = {};
|
||||
_stars.reset();
|
||||
return;
|
||||
@@ -169,7 +192,7 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
|
||||
? unique->starsForResale
|
||||
: data.info.starsResellMin)
|
||||
).append(data.info.resellCount > 1 ? "+" : ""))
|
||||
: (_small && unique && unique->starsForResale)
|
||||
: (small() && unique && unique->starsForResale)
|
||||
? Data::FormatGiftResaleAsked(*unique)
|
||||
: unique
|
||||
? tr::lng_gift_transfer_button(
|
||||
@@ -214,7 +237,7 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
|
||||
_uniquePatternEmoji = nullptr;
|
||||
_uniquePatternCache.clear();
|
||||
|
||||
if (_small && !resale) {
|
||||
if (small() && !resale) {
|
||||
_button = QRect();
|
||||
return;
|
||||
}
|
||||
@@ -225,7 +248,7 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
|
||||
QSize(buttonw, buttonh)
|
||||
).marginsAdded(st::giftBoxButtonPadding);
|
||||
const auto skipy = _delegate->buttonSize().height()
|
||||
- (_small
|
||||
- (small()
|
||||
? st::giftBoxButtonBottomSmall
|
||||
: _byStars.isEmpty()
|
||||
? st::giftBoxButtonBottom
|
||||
@@ -295,11 +318,17 @@ void GiftButton::setGeometry(QRect inner, QMargins extend) {
|
||||
}
|
||||
|
||||
QMargins GiftButton::currentExtend() const {
|
||||
const auto progress = _selectedAnimation.value(_selected ? 1. : 0.);
|
||||
const auto progress = (_mode == Mode::Selection)
|
||||
? 0.
|
||||
: _selectedAnimation.value(_selected ? 1. : 0.);
|
||||
const auto added = anim::interpolate(0, st::giftBoxSelectSkip, progress);
|
||||
return _extend + QMargins(added, added, added, added);
|
||||
}
|
||||
|
||||
bool GiftButton::small() const {
|
||||
return _mode != GiftButtonMode::Full;
|
||||
}
|
||||
|
||||
void GiftButton::toggleSelected(bool selected, anim::type animated) {
|
||||
if (_selected == selected) {
|
||||
if (animated == anim::type::instant) {
|
||||
@@ -310,8 +339,14 @@ void GiftButton::toggleSelected(bool selected, anim::type animated) {
|
||||
const auto duration = st::defaultRoundCheckbox.duration;
|
||||
_selected = selected;
|
||||
if (animated == anim::type::instant) {
|
||||
if (_check) {
|
||||
_check->finishAnimating();
|
||||
}
|
||||
_selectedAnimation.stop();
|
||||
return;
|
||||
} else if (_check) {
|
||||
_check->setChecked(selected, animated);
|
||||
return;
|
||||
}
|
||||
_selectedAnimation.start([=] {
|
||||
update();
|
||||
@@ -358,7 +393,9 @@ void GiftButton::paintBackground(QPainter &p, const QImage &background) {
|
||||
}
|
||||
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
const auto progress = _selectedAnimation.value(_selected ? 1. : 0.);
|
||||
const auto progress = (_mode == Mode::Selection)
|
||||
? 0.
|
||||
: _selectedAnimation.value(_selected ? 1. : 0.);
|
||||
if (progress < 0.01) {
|
||||
return;
|
||||
}
|
||||
@@ -446,7 +483,7 @@ void GiftButton::paintEvent(QPaintEvent *e) {
|
||||
const auto unique = v::is<GiftTypeStars>(_descriptor)
|
||||
? v::get<GiftTypeStars>(_descriptor).info.unique.get()
|
||||
: nullptr;
|
||||
const auto onsale = (unique && unique->starsForResale && _small);
|
||||
const auto onsale = unique && unique->starsForResale && small();
|
||||
const auto requirePremium = v::is<GiftTypeStars>(_descriptor)
|
||||
&& !v::get<GiftTypeStars>(_descriptor).userpic
|
||||
&& !v::get<GiftTypeStars>(_descriptor).info.unique
|
||||
@@ -482,6 +519,14 @@ void GiftButton::paintEvent(QPaintEvent *e) {
|
||||
const auto image = _userpic->image(st::giftBoxUserpicSize);
|
||||
const auto skip = st::giftBoxUserpicSkip;
|
||||
p.drawImage(extend.left() + skip, extend.top() + skip, image);
|
||||
} else if (_check) {
|
||||
const auto skip = st::giftBoxUserpicSkip;
|
||||
_check->paint(
|
||||
p,
|
||||
QPoint(extend.left() + skip, extend.top() + skip),
|
||||
width,
|
||||
_selected,
|
||||
true);
|
||||
}
|
||||
|
||||
auto frame = QImage();
|
||||
@@ -502,7 +547,7 @@ void GiftButton::paintEvent(QPaintEvent *e) {
|
||||
p.drawImage(
|
||||
QRect(
|
||||
(width - size.width()) / 2,
|
||||
(_small
|
||||
(small()
|
||||
? st::giftBoxSmallStickerTop
|
||||
: _text.isEmpty()
|
||||
? st::giftBoxStickerStarTop
|
||||
@@ -516,7 +561,7 @@ void GiftButton::paintEvent(QPaintEvent *e) {
|
||||
if (hidden) {
|
||||
const auto topleft = QPoint(
|
||||
(width - st::giftBoxStickerSize.width()) / 2,
|
||||
(_small
|
||||
(small()
|
||||
? st::giftBoxSmallStickerTop
|
||||
: _text.isEmpty()
|
||||
? st::giftBoxStickerStarTop
|
||||
@@ -781,7 +826,7 @@ QSize Delegate::buttonSize() {
|
||||
const auto available = width - padding.left() - padding.right();
|
||||
const auto singlew = (available - 2 * st::giftBoxGiftSkip.x())
|
||||
/ kGiftsPerRow;
|
||||
const auto minimal = (_mode == GiftButtonMode::Minimal);
|
||||
const auto minimal = (_mode != GiftButtonMode::Full);
|
||||
_single = QSize(
|
||||
singlew,
|
||||
minimal ? st::giftBoxGiftSmall : st::giftBoxGiftHeight);
|
||||
|
||||
@@ -34,6 +34,10 @@ namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Overview::Layout {
|
||||
class Checkbox;
|
||||
} // namespace Overview::Layout
|
||||
|
||||
namespace Ui {
|
||||
class DynamicImage;
|
||||
} // namespace Ui
|
||||
@@ -118,9 +122,10 @@ struct GiftBadge {
|
||||
const GiftBadge &) = default;
|
||||
};
|
||||
|
||||
enum class GiftButtonMode {
|
||||
enum class GiftButtonMode : uint8 {
|
||||
Full,
|
||||
Minimal,
|
||||
Selection,
|
||||
};
|
||||
|
||||
class GiftButtonDelegate {
|
||||
@@ -173,7 +178,9 @@ private:
|
||||
|
||||
void setDocument(not_null<DocumentData*> document);
|
||||
[[nodiscard]] QMargins currentExtend() const;
|
||||
[[nodiscard]] bool small() const;
|
||||
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
void unsubscribe();
|
||||
|
||||
const not_null<GiftButtonDelegate*> _delegate;
|
||||
@@ -190,11 +197,12 @@ private:
|
||||
base::flat_map<float64, QImage> _uniquePatternCache;
|
||||
std::optional<Ui::Premium::ColoredMiniStars> _stars;
|
||||
Ui::Animations::Simple _selectedAnimation;
|
||||
std::unique_ptr<Overview::Layout::Checkbox> _check;
|
||||
int _resalePrice = 0;
|
||||
GiftButtonMode _mode = GiftButtonMode::Full;
|
||||
bool _subscribed = false;
|
||||
bool _patterned = false;
|
||||
bool _selected = false;
|
||||
bool _small = false;
|
||||
|
||||
QRect _button;
|
||||
QMargins _extend;
|
||||
|
||||
@@ -201,6 +201,7 @@ private:
|
||||
const not_null<Window::SessionController*> _window;
|
||||
const not_null<PeerData*> _peer;
|
||||
const int _addingToCollectionId = 0;
|
||||
const GiftButtonMode _mode;
|
||||
|
||||
rpl::variable<Descriptor> _descriptor;
|
||||
Delegate _delegate;
|
||||
@@ -267,8 +268,11 @@ InnerWidget::InnerWidget(
|
||||
, _window(window)
|
||||
, _peer(peer)
|
||||
, _addingToCollectionId(addingToCollectionId)
|
||||
, _mode(_addingToCollectionId
|
||||
? GiftButtonMode::Selection
|
||||
: GiftButtonMode::Minimal)
|
||||
, _descriptor(std::move(descriptor))
|
||||
, _delegate(&_window->session(), GiftButtonMode::Minimal)
|
||||
, _delegate(&_window->session(), _mode)
|
||||
, _all(std::move(all))
|
||||
, _entries(&_all)
|
||||
, _list(&_entries->list)
|
||||
@@ -750,7 +754,7 @@ void InnerWidget::validateButtons() {
|
||||
view.button->toggleSelected(
|
||||
_addingToCollectionId && _inCollection.contains(manageId),
|
||||
anim::type::instant);
|
||||
view.button->setDescriptor(descriptor, GiftButton::Mode::Minimal);
|
||||
view.button->setDescriptor(descriptor, _mode);
|
||||
view.button->setClickedCallback(callback);
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "overview/overview_checkbox.h"
|
||||
|
||||
#include "styles/style_overview.h"
|
||||
#include "styles/style_widgets.h"
|
||||
|
||||
namespace Overview::Layout {
|
||||
|
||||
void Checkbox::paint(
|
||||
QPainter &p,
|
||||
QPoint position,
|
||||
int outerWidth,
|
||||
bool selected,
|
||||
bool selecting) {
|
||||
_check.setDisplayInactive(selecting);
|
||||
_check.setChecked(selected);
|
||||
const auto pression = _pression.value((_active && _pressed) ? 1. : 0.);
|
||||
const auto scale = 1. - (1. - st::overviewCheckPressedSize) * pression;
|
||||
_check.paint(p, position.x(), position.y(), outerWidth, scale);
|
||||
}
|
||||
|
||||
void Checkbox::setActive(bool active) {
|
||||
_active = active;
|
||||
if (_pressed) {
|
||||
startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
void Checkbox::setPressed(bool pressed) {
|
||||
_pressed = pressed;
|
||||
if (_active) {
|
||||
startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
void Checkbox::setChecked(bool checked, anim::type animated) {
|
||||
_check.setChecked(checked, animated);
|
||||
}
|
||||
|
||||
void Checkbox::startAnimation() {
|
||||
const auto showPressed = (_pressed && _active);
|
||||
_pression.start(
|
||||
_updateCallback,
|
||||
showPressed ? 0. : 1.,
|
||||
showPressed ? 1. : 0.,
|
||||
st::overviewCheck.duration);
|
||||
}
|
||||
|
||||
void Checkbox::finishAnimating() {
|
||||
_pression.stop();
|
||||
_check.finishAnimating();
|
||||
}
|
||||
|
||||
} // namespace Overview::Layout
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/effects/round_checkbox.h"
|
||||
|
||||
namespace style {
|
||||
struct RoundCheckbox;
|
||||
} // namespace style
|
||||
|
||||
namespace Overview::Layout {
|
||||
|
||||
class Checkbox {
|
||||
public:
|
||||
template <typename UpdateCallback>
|
||||
Checkbox(UpdateCallback callback, const style::RoundCheckbox &st)
|
||||
: _updateCallback(callback)
|
||||
, _check(st, _updateCallback) {
|
||||
}
|
||||
|
||||
void paint(
|
||||
QPainter &p,
|
||||
QPoint position,
|
||||
int outerWidth,
|
||||
bool selected,
|
||||
bool selecting);
|
||||
|
||||
void setActive(bool active);
|
||||
void setPressed(bool pressed);
|
||||
void setChecked(bool checked, anim::type animated = anim::type::normal);
|
||||
void finishAnimating();
|
||||
|
||||
void invalidateCache() {
|
||||
_check.invalidateCache();
|
||||
}
|
||||
|
||||
private:
|
||||
void startAnimation();
|
||||
|
||||
Fn<void()> _updateCallback;
|
||||
Ui::RoundCheckbox _check;
|
||||
|
||||
Ui::Animations::Simple _pression;
|
||||
bool _active = false;
|
||||
bool _pressed = false;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Overview::Layout
|
||||
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "overview/overview_layout.h"
|
||||
|
||||
#include "overview/overview_checkbox.h"
|
||||
#include "overview/overview_layout_delegate.h"
|
||||
#include "core/ui_integration.h" // TextContext
|
||||
#include "data/data_document.h"
|
||||
@@ -49,8 +50,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "styles/style_overview.h"
|
||||
|
||||
namespace Overview {
|
||||
namespace Layout {
|
||||
namespace Overview::Layout {
|
||||
namespace {
|
||||
|
||||
using TextState = HistoryView::TextState;
|
||||
@@ -123,62 +123,6 @@ void PaintSensitiveTag(Painter &p, QRect r) {
|
||||
|
||||
} // namespace
|
||||
|
||||
class Checkbox {
|
||||
public:
|
||||
template <typename UpdateCallback>
|
||||
Checkbox(UpdateCallback callback, const style::RoundCheckbox &st)
|
||||
: _updateCallback(callback)
|
||||
, _check(st, _updateCallback) {
|
||||
}
|
||||
|
||||
void paint(Painter &p, QPoint position, int outerWidth, bool selected, bool selecting);
|
||||
|
||||
void setActive(bool active);
|
||||
void setPressed(bool pressed);
|
||||
|
||||
void invalidateCache() {
|
||||
_check.invalidateCache();
|
||||
}
|
||||
|
||||
private:
|
||||
void startAnimation();
|
||||
|
||||
Fn<void()> _updateCallback;
|
||||
Ui::RoundCheckbox _check;
|
||||
|
||||
Ui::Animations::Simple _pression;
|
||||
bool _active = false;
|
||||
bool _pressed = false;
|
||||
|
||||
};
|
||||
|
||||
void Checkbox::paint(Painter &p, QPoint position, int outerWidth, bool selected, bool selecting) {
|
||||
_check.setDisplayInactive(selecting);
|
||||
_check.setChecked(selected);
|
||||
const auto pression = _pression.value((_active && _pressed) ? 1. : 0.);
|
||||
const auto masterScale = 1. - (1. - st::overviewCheckPressedSize) * pression;
|
||||
_check.paint(p, position.x(), position.y(), outerWidth, masterScale);
|
||||
}
|
||||
|
||||
void Checkbox::setActive(bool active) {
|
||||
_active = active;
|
||||
if (_pressed) {
|
||||
startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
void Checkbox::setPressed(bool pressed) {
|
||||
_pressed = pressed;
|
||||
if (_active) {
|
||||
startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
void Checkbox::startAnimation() {
|
||||
auto showPressed = (_pressed && _active);
|
||||
_pression.start(_updateCallback, showPressed ? 0. : 1., showPressed ? 1. : 0., st::overviewCheck.duration);
|
||||
}
|
||||
|
||||
ItemBase::ItemBase(
|
||||
not_null<Delegate*> delegate,
|
||||
not_null<HistoryItem*> parent)
|
||||
@@ -2501,5 +2445,4 @@ void Gif::updateStatusText() {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Layout
|
||||
} // namespace Overview
|
||||
} // namespace Overview::Layout
|
||||
|
||||
@@ -31,8 +31,7 @@ namespace Ui {
|
||||
class SpoilerAnimation;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Overview {
|
||||
namespace Layout {
|
||||
namespace Overview::Layout {
|
||||
|
||||
class Checkbox;
|
||||
class ItemBase;
|
||||
@@ -512,5 +511,4 @@ private:
|
||||
|
||||
};
|
||||
|
||||
} // namespace Layout
|
||||
} // namespace Overview
|
||||
} // namespace Overview::Layout
|
||||
|
||||
@@ -9,8 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
class StickerPremiumMark;
|
||||
|
||||
namespace Overview {
|
||||
namespace Layout {
|
||||
namespace Overview::Layout {
|
||||
|
||||
class ItemBase;
|
||||
|
||||
@@ -31,5 +30,4 @@ public:
|
||||
|
||||
};
|
||||
|
||||
} // namespace Layout
|
||||
} // namespace Overview
|
||||
} // namespace Overview::Layout
|
||||
|
||||
@@ -308,6 +308,10 @@ void RoundCheckbox::setChecked(bool newChecked, anim::type animated) {
|
||||
}
|
||||
}
|
||||
|
||||
void RoundCheckbox::finishAnimating() {
|
||||
_checkedProgress.stop();
|
||||
}
|
||||
|
||||
void RoundCheckbox::invalidateCache() {
|
||||
if (!_inactiveCacheBg.isNull() || !_inactiveCacheFg.isNull()) {
|
||||
prepareInactiveCache();
|
||||
|
||||
@@ -34,6 +34,7 @@ public:
|
||||
void setChecked(
|
||||
bool newChecked,
|
||||
anim::type animated = anim::type::normal);
|
||||
void finishAnimating();
|
||||
|
||||
void invalidateCache();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user