mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Improve group sticker set setup box.
This commit is contained in:
parent
7f5a91d2bb
commit
fa818407e6
12 changed files with 478 additions and 167 deletions
|
@ -922,6 +922,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
"lng_stickers_masks_pack" = "This is a pack of mask stickers. You can use them in the photo editor on our mobile apps.";
|
||||
"lng_stickers_group_set" = "Group sticker set";
|
||||
"lng_stickers_remove_group_set" = "Remove group sticker set?";
|
||||
"lng_stickers_group_from_your" = "Choose from your stickers";
|
||||
|
||||
"lng_in_dlg_photo" = "Photo";
|
||||
"lng_in_dlg_video" = "Video";
|
||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "boxes/abstract_box.h"
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/effects/widget_fade_wrap.h"
|
||||
|
@ -30,9 +31,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
BoxLayerTitleShadow::BoxLayerTitleShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxLayerTitleShadow) {
|
||||
}
|
||||
|
||||
QPointer<Ui::RoundButton> BoxContent::addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback) {
|
||||
return addButton(std::move(textFactory), std::move(clickCallback), st::defaultBoxButton);
|
||||
}
|
||||
|
@ -421,3 +419,22 @@ void AbstractBox::keyPressEvent(QKeyEvent *e) {
|
|||
LayerWidget::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
BoxLayerTitleShadow::BoxLayerTitleShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxLayerTitleShadow) {
|
||||
}
|
||||
|
||||
BoxContentDivider::BoxContentDivider(QWidget *parent) : TWidget(parent) {
|
||||
}
|
||||
|
||||
int BoxContentDivider::resizeGetHeight(int newWidth) {
|
||||
return st::rightsDividerHeight;
|
||||
}
|
||||
|
||||
void BoxContentDivider::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
p.fillRect(e->rect(), st::contactsAboutBg);
|
||||
auto dividerFillTop = myrtlrect(0, 0, width(), st::profileDividerTop.height());
|
||||
st::profileDividerTop.fill(p, dividerFillTop);
|
||||
auto dividerFillBottom = myrtlrect(0, height() - st::profileDividerBottom.height(), width(), st::profileDividerBottom.height());
|
||||
st::profileDividerBottom.fill(p, dividerFillBottom);
|
||||
}
|
||||
|
|
|
@ -36,11 +36,7 @@ namespace Window {
|
|||
class Controller;
|
||||
} // namespace Window
|
||||
|
||||
class BoxLayerTitleShadow : public Ui::PlainShadow {
|
||||
public:
|
||||
BoxLayerTitleShadow(QWidget *parent);
|
||||
|
||||
};
|
||||
class BoxLayerTitleShadow;
|
||||
|
||||
class BoxContentDelegate {
|
||||
public:
|
||||
|
@ -287,6 +283,22 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class BoxLayerTitleShadow : public Ui::PlainShadow {
|
||||
public:
|
||||
BoxLayerTitleShadow(QWidget *parent);
|
||||
|
||||
};
|
||||
|
||||
class BoxContentDivider : public TWidget {
|
||||
public:
|
||||
BoxContentDivider(QWidget *parent);
|
||||
|
||||
protected:
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
};
|
||||
|
||||
enum CreatingGroupType {
|
||||
CreatingGroupNone,
|
||||
CreatingGroupGroup,
|
||||
|
|
|
@ -679,3 +679,16 @@ muteChatTitle: FlatLabel(boxLabel) {
|
|||
font: font(boxFontSize semibold);
|
||||
}
|
||||
}
|
||||
|
||||
groupStickersRemove: contactsSearchCancel;
|
||||
groupStickersRemovePosition: point(6px, 6px);
|
||||
groupStickersFieldPadding: margins(8px, 6px, 8px, 6px);
|
||||
groupStickersField: InputField(contactsSearchField) {
|
||||
placeholderFont: boxTextFont;
|
||||
font: boxTextFont;
|
||||
placeholderMargins: margins(0px, 0px, 0px, 0px);
|
||||
textMargins: margins(0px, 7px, 0px, 0px);
|
||||
textBg: boxBg;
|
||||
heightMin: 32px;
|
||||
}
|
||||
groupStickersSubTitleHeight: 36px;
|
||||
|
|
|
@ -25,7 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "boxes/calendar_box.h"
|
||||
|
||||
|
@ -74,30 +73,6 @@ void ApplyDependencies(CheckboxesMap &checkboxes, DependenciesMap &dependencies,
|
|||
|
||||
} // namespace
|
||||
|
||||
class EditParticipantBox::Divider : public TWidget {
|
||||
public:
|
||||
Divider(QWidget *parent) : TWidget(parent) {
|
||||
}
|
||||
|
||||
protected:
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
};
|
||||
|
||||
int EditParticipantBox::Divider::resizeGetHeight(int newWidth) {
|
||||
return st::rightsDividerHeight;
|
||||
}
|
||||
|
||||
void EditParticipantBox::Divider::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
p.fillRect(e->rect(), st::contactsAboutBg);
|
||||
auto dividerFillTop = myrtlrect(0, 0, width(), st::profileDividerTop.height());
|
||||
st::profileDividerTop.fill(p, dividerFillTop);
|
||||
auto dividerFillBottom = myrtlrect(0, height() - st::profileDividerBottom.height(), width(), st::profileDividerBottom.height());
|
||||
st::profileDividerBottom.fill(p, dividerFillBottom);
|
||||
}
|
||||
|
||||
class EditParticipantBox::Inner : public TWidget {
|
||||
public:
|
||||
Inner(QWidget *parent, gsl::not_null<ChannelData*> channel, gsl::not_null<UserData*> user, bool hasAdminRights);
|
||||
|
@ -236,7 +211,7 @@ void EditAdminBox::prepare() {
|
|||
auto hadRights = _oldRights.c_channelAdminRights().vflags.v;
|
||||
setTitle(langFactory(hadRights ? lng_rights_edit_admin : lng_channel_add_admin));
|
||||
|
||||
addControl(object_ptr<Divider>(this), QMargins());
|
||||
addControl(object_ptr<BoxContentDivider>(this), QMargins());
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_edit_admin_header), Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel), st::rightsHeaderMargin);
|
||||
|
||||
auto prepareRights = (hadRights ? _oldRights : DefaultRights(channel()));
|
||||
|
@ -355,7 +330,7 @@ void EditRestrictedBox::prepare() {
|
|||
|
||||
setTitle(langFactory(lng_rights_user_restrictions));
|
||||
|
||||
addControl(object_ptr<Divider>(this), QMargins());
|
||||
addControl(object_ptr<BoxContentDivider>(this), QMargins());
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_user_restrictions_header), Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel), st::rightsHeaderMargin);
|
||||
|
||||
auto prepareRights = (_oldRights.c_channelBannedRights().vflags.v ? _oldRights : DefaultRights(channel()));
|
||||
|
@ -378,7 +353,7 @@ void EditRestrictedBox::prepare() {
|
|||
addCheckbox(Flag::f_send_stickers | Flag::f_send_gifs | Flag::f_send_games | Flag::f_send_inline, lang(lng_rights_chat_send_stickers));
|
||||
addCheckbox(Flag::f_embed_links, lang(lng_rights_chat_send_links));
|
||||
|
||||
addControl(object_ptr<Divider>(this), st::rightsUntilMargin);
|
||||
addControl(object_ptr<BoxContentDivider>(this), st::rightsUntilMargin);
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_chat_banned_until_header), Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel), st::rightsHeaderMargin);
|
||||
setRestrictUntil(_until);
|
||||
|
||||
|
|
|
@ -57,8 +57,6 @@ protected:
|
|||
return _hasAdminRights;
|
||||
}
|
||||
|
||||
class Divider;
|
||||
|
||||
private:
|
||||
gsl::not_null<ChannelData*> _channel;
|
||||
gsl::not_null<UserData*> _user;
|
||||
|
|
|
@ -31,16 +31,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/effects/slide_animation.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "auth_session.h"
|
||||
#include "messenger.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kArchivedLimitFirstRequest = 10;
|
||||
constexpr int kArchivedLimitPerPage = 30;
|
||||
constexpr auto kArchivedLimitFirstRequest = 10;
|
||||
constexpr auto kArchivedLimitPerPage = 30;
|
||||
constexpr auto kHandleMegagroupSetAddressChangeTimeout = TimeMs(1000);
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -156,6 +160,7 @@ StickersBox::StickersBox(QWidget*, gsl::not_null<ChannelData*> megagroup)
|
|||
: _section(Section::Installed)
|
||||
, _installed(0, this, megagroup)
|
||||
, _megagroupSet(megagroup) {
|
||||
subscribe(_installed.widget()->scrollToY, [this](int y) { onScrollToY(y); });
|
||||
}
|
||||
|
||||
void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result) {
|
||||
|
@ -264,7 +269,12 @@ void StickersBox::prepare() {
|
|||
_archived.widget()->setLoadMoreCallback([this] { loadMoreArchived(); });
|
||||
}
|
||||
|
||||
if (_megagroupSet) {
|
||||
addButton(langFactory(lng_settings_save), [this] { _installed.widget()->saveGroupSet(); closeBox(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
} else {
|
||||
addButton(langFactory(lng_about_done), [this] { closeBox(); });
|
||||
}
|
||||
|
||||
if (_section == Section::Installed) {
|
||||
_tab = &_installed;
|
||||
|
@ -554,7 +564,7 @@ void StickersBox::rebuildList(Tab *tab) {
|
|||
}
|
||||
|
||||
void StickersBox::closeHook() {
|
||||
if (!_installed.widget()) {
|
||||
if (!_installed.widget() || _megagroupSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -569,8 +579,30 @@ void StickersBox::closeHook() {
|
|||
}
|
||||
}
|
||||
|
||||
void StickersBox::setInnerFocus() {
|
||||
if (_megagroupSet) {
|
||||
_installed.widget()->setInnerFocus();
|
||||
}
|
||||
}
|
||||
|
||||
StickersBox::~StickersBox() = default;
|
||||
|
||||
StickersBox::Inner::Row::Row(uint64 id, DocumentData *sticker, int32 count, const QString &title, int titleWidth, bool installed, bool official, bool unread, bool archived, bool removed, int32 pixw, int32 pixh) : id(id)
|
||||
, sticker(sticker)
|
||||
, count(count)
|
||||
, title(title)
|
||||
, titleWidth(titleWidth)
|
||||
, installed(installed)
|
||||
, official(official)
|
||||
, unread(unread)
|
||||
, archived(archived)
|
||||
, removed(removed)
|
||||
, pixw(pixw)
|
||||
, pixh(pixh) {
|
||||
}
|
||||
|
||||
StickersBox::Inner::Row::~Row() = default;
|
||||
|
||||
StickersBox::Inner::Inner(QWidget *parent, StickersBox::Section section) : TWidget(parent)
|
||||
, _section(section)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
|
@ -599,7 +631,17 @@ StickersBox::Inner::Inner(QWidget *parent, gsl::not_null<ChannelData*> megagroup
|
|||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _a_shifting(animation(this, &Inner::step_shifting))
|
||||
, _itemsTop(st::membersMarginTop)
|
||||
, _megagroupSet(megagroup) {
|
||||
, _megagroupSet(megagroup)
|
||||
, _megagroupSetInput(_megagroupSet->mgInfo->stickerSet)
|
||||
, _megagroupSetField(this, st::groupStickersField, [] { return qsl("stickerset"); }, QString(), true)
|
||||
, _megagroupDivider(this)
|
||||
, _megagroupSubTitle(this, lang(lng_stickers_group_from_your), Ui::FlatLabel::InitType::Simple, st::boxTitle) {
|
||||
_megagroupSetField->setLinkPlaceholder(Messenger::Instance().createInternalLink(qsl("addstickers/")));
|
||||
_megagroupSetField->setPlaceholderHidden(false);
|
||||
_megagroupSetAddressChangedTimer.setCallback([this] { handleMegagroupSetAddressChange(); });
|
||||
connect(_megagroupSetField, &Ui::MaskedInputField::changed, this, [this] { _megagroupSetAddressChangedTimer.callOnce(kHandleMegagroupSetAddressChangeTimeout); });
|
||||
connect(_megagroupSetField, &Ui::MaskedInputField::submitted, this, [this] { _megagroupSetAddressChangedTimer.cancel(); handleMegagroupSetAddressChange(); });
|
||||
|
||||
setup();
|
||||
}
|
||||
|
||||
|
@ -611,41 +653,76 @@ void StickersBox::Inner::setup() {
|
|||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
void StickersBox::Inner::setInnerFocus() {
|
||||
if (_megagroupSetField) {
|
||||
_megagroupSetField->setFocusFast();
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::paintEvent(QPaintEvent *e) {
|
||||
QRect r(e->rect());
|
||||
Painter p(this);
|
||||
|
||||
_a_shifting.step();
|
||||
|
||||
auto clip = e->rect();
|
||||
auto ms = getms();
|
||||
p.fillRect(r, st::boxBg);
|
||||
p.setClipRect(r);
|
||||
p.fillRect(clip, st::boxBg);
|
||||
p.setClipRect(clip);
|
||||
|
||||
if (_megagroupSelectedSet) {
|
||||
auto setTop = _megagroupDivider->y() - _rowHeight;
|
||||
p.translate(0, setTop);
|
||||
paintRow(p, _megagroupSelectedSet.get(), -1, ms);
|
||||
p.translate(0, -setTop);
|
||||
}
|
||||
|
||||
auto y = _itemsTop;
|
||||
if (_rows.isEmpty()) {
|
||||
if (_rows.empty()) {
|
||||
p.setFont(st::noContactsFont);
|
||||
p.setPen(st::noContactsColor);
|
||||
p.drawText(QRect(0, y, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center);
|
||||
} else {
|
||||
p.translate(0, _itemsTop);
|
||||
|
||||
int32 yFrom = r.y() - _itemsTop, yTo = r.y() + r.height() - _itemsTop;
|
||||
int32 yFrom = clip.y() - _itemsTop, yTo = clip.y() + clip.height() - _itemsTop;
|
||||
int32 from = floorclamp(yFrom - _rowHeight, _rowHeight, 0, _rows.size());
|
||||
int32 to = ceilclamp(yTo + _rowHeight, _rowHeight, 0, _rows.size());
|
||||
p.translate(0, from * _rowHeight);
|
||||
for (int32 i = from; i < to; ++i) {
|
||||
if (i != _above) {
|
||||
paintRow(p, i, ms);
|
||||
paintRow(p, _rows[i].get(), i, ms);
|
||||
}
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
if (from <= _above && _above < to) {
|
||||
p.translate(0, (_above - to) * _rowHeight);
|
||||
paintRow(p, _above, ms);
|
||||
paintRow(p, _rows[_above].get(), _above, ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::resizeEvent(QResizeEvent *e) {
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
void StickersBox::Inner::updateControlsGeometry() {
|
||||
if (_megagroupSet) {
|
||||
auto top = st::groupStickersFieldPadding.top();
|
||||
auto fieldLeft = st::boxLayerTitlePosition.x();
|
||||
_megagroupSetField->setGeometryToLeft(fieldLeft, top, width() - fieldLeft - st::groupStickersFieldPadding.right(), _megagroupSetField->height());
|
||||
top += _megagroupSetField->height() + st::groupStickersFieldPadding.bottom();
|
||||
if (_megagroupSelectedRemove) {
|
||||
_megagroupSelectedShadow->setGeometryToLeft(0, top, width(), st::lineWidth);
|
||||
top += st::lineWidth;
|
||||
_megagroupSelectedRemove->moveToRight(st::groupStickersRemovePosition.x(), top + st::groupStickersRemovePosition.y());
|
||||
top += _rowHeight;
|
||||
}
|
||||
_megagroupDivider->setGeometryToLeft(0, top, width(), _megagroupDivider->height());
|
||||
top += _megagroupDivider->height();
|
||||
_megagroupSubTitle->moveToLeft(st::boxLayerTitlePosition.x(), top + st::boxLayerTitlePosition.y());
|
||||
}
|
||||
}
|
||||
|
||||
QRect StickersBox::Inner::relativeButtonRect(bool removeButton) const {
|
||||
auto buttonw = st::stickersRemove.width;
|
||||
auto buttonh = st::stickersRemove.height;
|
||||
|
@ -662,14 +739,21 @@ QRect StickersBox::Inner::relativeButtonRect(bool removeButton) const {
|
|||
return QRect(buttonx, buttony, buttonw, buttonh);
|
||||
}
|
||||
|
||||
void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
|
||||
auto s = _rows.at(index);
|
||||
|
||||
auto xadd = 0, yadd = qRound(s->yadd.current());
|
||||
void StickersBox::Inner::paintRow(Painter &p, Row *set, int index, TimeMs ms) {
|
||||
auto xadd = 0, yadd = qRound(set->yadd.current());
|
||||
if (xadd || yadd) p.translate(xadd, yadd);
|
||||
|
||||
if (_megagroupSet) {
|
||||
if (index >= 0 && index == _selected) {
|
||||
p.fillRect(0, 0, width(), _rowHeight, st::contactsBgOver);
|
||||
if (set->ripple) {
|
||||
set->ripple->paint(p, 0, 0, width(), ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_section == Section::Installed) {
|
||||
if (index == _above) {
|
||||
if (index >= 0 && index == _above) {
|
||||
auto current = _aboveShadowFadeOpacity.current();
|
||||
if (_started >= 0) {
|
||||
auto reachedOpacity = aboveShadowOpacity();
|
||||
|
@ -686,16 +770,16 @@ void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
|
|||
App::roundRect(p, row, st::boxBg, BoxCorners);
|
||||
|
||||
p.setOpacity(1. - current);
|
||||
paintFakeButton(p, index, ms);
|
||||
paintFakeButton(p, set, index, ms);
|
||||
p.setOpacity(1.);
|
||||
} else if (!_megagroupSet) {
|
||||
paintFakeButton(p, index, ms);
|
||||
paintFakeButton(p, set, index, ms);
|
||||
}
|
||||
} else if (!_megagroupSet) {
|
||||
paintFakeButton(p, index, ms);
|
||||
paintFakeButton(p, set, index, ms);
|
||||
}
|
||||
|
||||
if (s->removed && _section == Section::Installed) {
|
||||
if (set->removed && _section == Section::Installed) {
|
||||
p.setOpacity(st::stickersRowDisabledOpacity);
|
||||
}
|
||||
|
||||
|
@ -703,15 +787,15 @@ void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
|
|||
|
||||
if (!_megagroupSet && _section == Section::Installed) {
|
||||
stickerx += st::stickersReorderIcon.width() + st::stickersReorderSkip;
|
||||
if (!s->isRecentSet()) {
|
||||
if (!set->isRecentSet()) {
|
||||
st::stickersReorderIcon.paint(p, st::contactsPadding.left(), (_rowHeight - st::stickersReorderIcon.height()) / 2, width());
|
||||
}
|
||||
}
|
||||
|
||||
if (s->sticker) {
|
||||
s->sticker->thumb->load();
|
||||
QPixmap pix(s->sticker->thumb->pix(s->pixw, s->pixh));
|
||||
p.drawPixmapLeft(stickerx + (st::contactsPhotoSize - s->pixw) / 2, st::contactsPadding.top() + (st::contactsPhotoSize - s->pixh) / 2, width(), pix);
|
||||
if (set->sticker) {
|
||||
set->sticker->thumb->load();
|
||||
auto pix = set->sticker->thumb->pix(set->pixw, set->pixh);
|
||||
p.drawPixmapLeft(stickerx + (st::contactsPhotoSize - set->pixw) / 2, st::contactsPadding.top() + (st::contactsPhotoSize - set->pixh) / 2, width(), pix);
|
||||
}
|
||||
|
||||
int namex = stickerx + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
|
@ -722,19 +806,19 @@ void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
|
|||
|
||||
p.setFont(st::contactsNameStyle.font);
|
||||
p.setPen(st::contactsNameFg);
|
||||
p.drawTextLeft(namex, namey, width(), s->title, s->titleWidth);
|
||||
p.drawTextLeft(namex, namey, width(), set->title, set->titleWidth);
|
||||
|
||||
if (s->unread) {
|
||||
if (set->unread) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::stickersFeaturedUnreadBg);
|
||||
|
||||
{
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.drawEllipse(rtlrect(namex + s->titleWidth + st::stickersFeaturedUnreadSkip, namey + st::stickersFeaturedUnreadTop, st::stickersFeaturedUnreadSize, st::stickersFeaturedUnreadSize, width()));
|
||||
p.drawEllipse(rtlrect(namex + set->titleWidth + st::stickersFeaturedUnreadSkip, namey + st::stickersFeaturedUnreadTop, st::stickersFeaturedUnreadSize, st::stickersFeaturedUnreadSize, width()));
|
||||
}
|
||||
}
|
||||
|
||||
auto statusText = (s->count > 0) ? lng_stickers_count(lt_count, s->count) : lang(lng_contacts_loading);
|
||||
auto statusText = (set->count > 0) ? lng_stickers_count(lt_count, set->count) : lang(lng_contacts_loading);
|
||||
|
||||
p.setFont(st::contactsStatusFont);
|
||||
p.setPen(st::contactsStatusFg);
|
||||
|
@ -744,8 +828,7 @@ void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
|
|||
if (xadd || yadd) p.translate(-xadd, -yadd);
|
||||
}
|
||||
|
||||
void StickersBox::Inner::paintFakeButton(Painter &p, int index, TimeMs ms) {
|
||||
auto set = _rows[index];
|
||||
void StickersBox::Inner::paintFakeButton(Painter &p, Row *set, int index, TimeMs ms) {
|
||||
auto removeButton = (_section == Section::Installed && !set->removed);
|
||||
auto rect = relativeButtonRect(removeButton);
|
||||
if (_section != Section::Installed && set->installed && !set->archived && !set->removed) {
|
||||
|
@ -794,7 +877,7 @@ void StickersBox::Inner::mousePressEvent(QMouseEvent *e) {
|
|||
_mouse = e->globalPos();
|
||||
onUpdateSelected();
|
||||
|
||||
_pressed = _selected;
|
||||
setPressed(_selected);
|
||||
if (_actionSel >= 0) {
|
||||
setActionDown(_actionSel);
|
||||
update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight);
|
||||
|
@ -810,7 +893,7 @@ void StickersBox::Inner::setActionDown(int newActionDown) {
|
|||
}
|
||||
if (_actionDown >= 0 && _actionDown < _rows.size()) {
|
||||
update(0, _itemsTop + _actionDown * _rowHeight, width(), _rowHeight);
|
||||
auto set = _rows[_actionDown];
|
||||
auto &set = _rows[_actionDown];
|
||||
if (set->ripple) {
|
||||
set->ripple->lastStop();
|
||||
}
|
||||
|
@ -818,7 +901,7 @@ void StickersBox::Inner::setActionDown(int newActionDown) {
|
|||
_actionDown = newActionDown;
|
||||
if (_actionDown >= 0 && _actionDown < _rows.size()) {
|
||||
update(0, _itemsTop + _actionDown * _rowHeight, width(), _rowHeight);
|
||||
auto set = _rows[_actionDown];
|
||||
auto &set = _rows[_actionDown];
|
||||
auto removeButton = (_section == Section::Installed && !set->removed);
|
||||
if (!set->ripple) {
|
||||
if (_section == Section::Installed) {
|
||||
|
@ -844,8 +927,46 @@ void StickersBox::Inner::setActionDown(int newActionDown) {
|
|||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::setSelected(int selected) {
|
||||
if (_selected == selected) {
|
||||
return;
|
||||
}
|
||||
if (_megagroupSet && _selected >= 0 && _selected < _rows.size()) {
|
||||
update(0, _itemsTop + _selected * _rowHeight, width(), _rowHeight);
|
||||
}
|
||||
_selected = selected;
|
||||
if (_megagroupSet && _selected >= 0 && _selected < _rows.size()) {
|
||||
update(0, _itemsTop + _selected * _rowHeight, width(), _rowHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::setPressed(int pressed) {
|
||||
if (_pressed == pressed) {
|
||||
return;
|
||||
}
|
||||
if (_megagroupSet && _pressed >= 0 && _pressed < _rows.size()) {
|
||||
update(0, _itemsTop + _pressed * _rowHeight, width(), _rowHeight);
|
||||
auto &set = _rows[_pressed];
|
||||
if (set->ripple) {
|
||||
set->ripple->lastStop();
|
||||
}
|
||||
}
|
||||
_pressed = pressed;
|
||||
if (_megagroupSet && _pressed >= 0 && _pressed < _rows.size()) {
|
||||
update(0, _itemsTop + _pressed * _rowHeight, width(), _rowHeight);
|
||||
auto &set = _rows[_pressed];
|
||||
auto rippleMask = Ui::RippleAnimation::rectMask(QSize(width(), _rowHeight));
|
||||
if (!_rows[_pressed]->ripple) {
|
||||
_rows[_pressed]->ripple = std::make_unique<Ui::RippleAnimation>(st::contactsRipple, std::move(rippleMask), [this, index = _pressed] {
|
||||
update(0, _itemsTop + index * _rowHeight, width(), _rowHeight);
|
||||
});
|
||||
}
|
||||
_rows[_pressed]->ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(0, _itemsTop + _pressed * _rowHeight));
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::ensureRipple(const style::RippleAnimation &st, QImage mask, bool removeButton) {
|
||||
_rows[_actionDown]->ripple = MakeShared<Ui::RippleAnimation>(st, std::move(mask), [this, index = _actionDown, removeButton] {
|
||||
_rows[_actionDown]->ripple = std::make_unique<Ui::RippleAnimation>(st, std::move(mask), [this, index = _actionDown, removeButton] {
|
||||
update(myrtlrect(relativeButtonRect(removeButton).translated(0, _itemsTop + index * _rowHeight)));
|
||||
});
|
||||
}
|
||||
|
@ -906,10 +1027,10 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
auto selected = -1;
|
||||
auto actionSel = -1;
|
||||
auto inDragArea = false;
|
||||
if (in && !_rows.isEmpty()) {
|
||||
if (in && !_rows.empty()) {
|
||||
selected = floorclamp(local.y() - _itemsTop, _rowHeight, 0, _rows.size() - 1);
|
||||
local.setY(local.y() - _itemsTop - selected * _rowHeight);
|
||||
auto set = _rows[selected];
|
||||
auto &set = _rows[selected];
|
||||
if (!_megagroupSet && (_section == Section::Installed || !set->installed || set->archived || set->removed)) {
|
||||
auto removeButton = (_section == Section::Installed && !set->removed);
|
||||
auto rect = myrtlrect(relativeButtonRect(removeButton));
|
||||
|
@ -931,7 +1052,7 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
setCursor((selected >= 0 || _pressed >= 0) ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
}
|
||||
_selected = selected;
|
||||
setSelected(selected);
|
||||
}
|
||||
if (_inDragArea != inDragArea) {
|
||||
_inDragArea = inDragArea;
|
||||
|
@ -978,16 +1099,14 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
|||
} else if (pressed == _selected && _actionSel < 0 && _actionDown < 0) {
|
||||
if (_selected >= 0 && !_inDragArea) {
|
||||
auto &sets = Global::RefStickerSets();
|
||||
auto row = _rows[pressed];
|
||||
auto &row = _rows[pressed];
|
||||
if (!row->isRecentSet()) {
|
||||
auto it = sets.find(row->id);
|
||||
if (it != sets.cend()) {
|
||||
_selected = -1;
|
||||
if (_megagroupSet) {
|
||||
Auth().api().setGroupStickerSet(_megagroupSet, Stickers::inputSetId(*it));
|
||||
Ui::hideLayer();
|
||||
App::main()->onStickersInstalled(Stickers::MegagroupSetId);
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)));
|
||||
} else {
|
||||
setSelected(-1);
|
||||
Ui::show(Box<StickerSetBox>(Stickers::inputSetId(*it)), KeepOtherLayers);
|
||||
}
|
||||
}
|
||||
|
@ -997,8 +1116,18 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
|||
setActionDown(-1);
|
||||
}
|
||||
|
||||
void StickersBox::Inner::saveGroupSet() {
|
||||
Expects(_megagroupSet != nullptr);
|
||||
auto oldId = (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) ? _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid.v : 0;
|
||||
auto newId = (_megagroupSetInput.type() == mtpc_inputStickerSetID) ? _megagroupSetInput.c_inputStickerSetID().vid.v : 0;
|
||||
if (newId != oldId) {
|
||||
Auth().api().setGroupStickerSet(_megagroupSet, _megagroupSetInput);
|
||||
App::main()->onStickersInstalled(Stickers::MegagroupSetId);
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::setRowRemoved(int index, bool removed) {
|
||||
auto row = _rows[index];
|
||||
auto &row = _rows[index];
|
||||
if (row->removed != removed) {
|
||||
row->removed = removed;
|
||||
row->ripple.reset();
|
||||
|
@ -1012,6 +1141,11 @@ void StickersBox::Inner::leaveEventHook(QEvent *e) {
|
|||
onUpdateSelected();
|
||||
}
|
||||
|
||||
void StickersBox::Inner::leaveToChildEvent(QEvent *e, QWidget *child) {
|
||||
_mouse = QPoint(-1, -1);
|
||||
onUpdateSelected();
|
||||
}
|
||||
|
||||
void StickersBox::Inner::step_shifting(TimeMs ms, bool timer) {
|
||||
auto animating = false;
|
||||
auto updateMin = -1;
|
||||
|
@ -1062,19 +1196,16 @@ void StickersBox::Inner::step_shifting(TimeMs ms, bool timer) {
|
|||
}
|
||||
|
||||
void StickersBox::Inner::clear() {
|
||||
for (int32 i = 0, l = _rows.size(); i < l; ++i) {
|
||||
delete _rows.at(i);
|
||||
}
|
||||
_rows.clear();
|
||||
_animStartTimes.clear();
|
||||
_aboveShadowFadeStart = 0;
|
||||
_aboveShadowFadeOpacity = anim::value();
|
||||
_a_shifting.stop();
|
||||
_above = _dragging = _started = -1;
|
||||
_selected = -1;
|
||||
_pressed = -1;
|
||||
_actionDown = -1;
|
||||
setSelected(-1);
|
||||
setPressed(-1);
|
||||
setActionSel(-1);
|
||||
setActionDown(-1);
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -1089,10 +1220,86 @@ void StickersBox::Inner::setActionSel(int32 actionSel) {
|
|||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::handleMegagroupSetAddressChange() {
|
||||
auto text = _megagroupSetField->getLastText().trimmed();
|
||||
if (text.isEmpty()) {
|
||||
if (_megagroupSelectedSet) {
|
||||
auto it = Global::StickerSets().constFind(_megagroupSelectedSet->id);
|
||||
if (it != Global::StickerSets().end() && !it->shortName.isEmpty()) {
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
|
||||
}
|
||||
}
|
||||
} else if (!_megagroupSetRequestId) {
|
||||
_megagroupSetRequestId = request(MTPmessages_GetStickerSet(MTP_inputStickerSetShortName(MTP_string(text)))).done([this](const MTPmessages_StickerSet &result) {
|
||||
_megagroupSetRequestId = 0;
|
||||
auto set = Stickers::FeedSetFull(result);
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetID(MTP_long(set->id), MTP_long(set->access)));
|
||||
}).fail([this](const RPCError &error) {
|
||||
_megagroupSetRequestId = 0;
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
|
||||
}).send();
|
||||
} else {
|
||||
_megagroupSetAddressChangedTimer.callOnce(kHandleMegagroupSetAddressChangeTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::rebuildMegagroupSet() {
|
||||
Expects(_megagroupSet != nullptr);
|
||||
if (_megagroupSetInput.type() != mtpc_inputStickerSetID) {
|
||||
if (_megagroupSelectedSet) {
|
||||
_megagroupSetField->setText(QString());
|
||||
_megagroupSetField->finishAnimations();
|
||||
}
|
||||
_megagroupSelectedSet.reset();
|
||||
_megagroupSelectedRemove.destroy();
|
||||
_megagroupSelectedShadow.destroy();
|
||||
return;
|
||||
}
|
||||
auto &set = _megagroupSetInput.c_inputStickerSetID();
|
||||
auto setId = set.vid.v;
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.cend() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
Auth().api().scheduleStickerSetRequest(set.vid.v, set.vaccess_hash.v);
|
||||
return;
|
||||
}
|
||||
|
||||
auto maxNameWidth = countMaxNameWidth();
|
||||
auto titleWidth = 0;
|
||||
auto title = fillSetTitle(*it, maxNameWidth, &titleWidth);
|
||||
auto count = fillSetCount(*it);
|
||||
auto sticker = (DocumentData*)nullptr;
|
||||
auto pixw = 0, pixh = 0;
|
||||
fillSetCover(*it, &sticker, &pixw, &pixh);
|
||||
auto installed = true, official = false, unread = false, archived = false, removed = false;
|
||||
if (!_megagroupSelectedSet || _megagroupSelectedSet->id != it->id) {
|
||||
_megagroupSetField->setText(it->shortName);
|
||||
_megagroupSetField->finishAnimations();
|
||||
}
|
||||
_megagroupSelectedSet = std::make_unique<Row>(it->id, sticker, count, title, titleWidth, installed, official, unread, archived, removed, pixw, pixh);
|
||||
_itemsTop += st::lineWidth + _rowHeight;
|
||||
|
||||
if (!_megagroupSelectedRemove) {
|
||||
_megagroupSelectedRemove.create(this, st::groupStickersRemove);
|
||||
_megagroupSelectedRemove->showFast();
|
||||
_megagroupSelectedRemove->setClickedCallback([this] {
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
|
||||
});
|
||||
_megagroupSelectedShadow.create(this);
|
||||
updateControlsGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::rebuild() {
|
||||
_itemsTop = st::membersMarginTop;
|
||||
|
||||
int maxNameWidth = countMaxNameWidth();
|
||||
if (_megagroupSet) {
|
||||
_itemsTop += st::groupStickersFieldPadding.top() + _megagroupSetField->height() + st::groupStickersFieldPadding.bottom();
|
||||
_itemsTop += _megagroupDivider->height() + st::groupStickersSubTitleHeight;
|
||||
rebuildMegagroupSet();
|
||||
}
|
||||
|
||||
auto maxNameWidth = countMaxNameWidth();
|
||||
|
||||
clear();
|
||||
auto &order = ([this]() -> const Stickers::Order & {
|
||||
|
@ -1131,21 +1338,34 @@ void StickersBox::Inner::rebuild() {
|
|||
updateSize();
|
||||
}
|
||||
|
||||
void StickersBox::Inner::updateSize() {
|
||||
resize(width(), _itemsTop + _rows.size() * _rowHeight + st::membersMarginBottom);
|
||||
void StickersBox::Inner::setMegagroupSelectedSet(const MTPInputStickerSet &set) {
|
||||
_megagroupSetInput = set;
|
||||
rebuild();
|
||||
scrollToY.notify(0, true);
|
||||
onUpdateSelected();
|
||||
}
|
||||
|
||||
void StickersBox::Inner::setMinHeight(int newWidth, int minHeight) {
|
||||
_minHeight = minHeight;
|
||||
updateSize(newWidth);
|
||||
}
|
||||
|
||||
void StickersBox::Inner::updateSize(int newWidth) {
|
||||
auto naturalHeight = _itemsTop + int(_rows.size()) * _rowHeight + st::membersMarginBottom;
|
||||
resize(newWidth ? newWidth : width(), qMax(_minHeight, naturalHeight));
|
||||
checkLoadMore();
|
||||
}
|
||||
|
||||
void StickersBox::Inner::updateRows() {
|
||||
int maxNameWidth = countMaxNameWidth();
|
||||
auto &sets = Global::StickerSets();
|
||||
for_const (auto row, _rows) {
|
||||
for_const (auto &row, _rows) {
|
||||
auto it = sets.constFind(row->id);
|
||||
if (it != sets.cend()) {
|
||||
auto &set = it.value();
|
||||
if (!row->sticker) {
|
||||
DocumentData *sticker = nullptr;
|
||||
int pixw = 0, pixh = 0;
|
||||
auto sticker = (DocumentData*)nullptr;
|
||||
auto pixw = 0, pixh = 0;
|
||||
fillSetCover(set, &sticker, &pixw, &pixh);
|
||||
if (sticker) {
|
||||
row->sticker = sticker;
|
||||
|
@ -1172,7 +1392,7 @@ void StickersBox::Inner::updateRows() {
|
|||
}
|
||||
|
||||
bool StickersBox::Inner::appendSet(const Stickers::Set &set) {
|
||||
for_const (auto row, _rows) {
|
||||
for_const (auto &row, _rows) {
|
||||
if (row->id == set.id) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1212,7 +1432,7 @@ void StickersBox::Inner::rebuildAppendSet(const Stickers::Set &set, int maxNameW
|
|||
QString title = fillSetTitle(set, maxNameWidth, &titleWidth);
|
||||
int count = fillSetCount(set);
|
||||
|
||||
_rows.push_back(new Row(set.id, sticker, count, title, titleWidth, installed, official, unread, archived, removed, pixw, pixh));
|
||||
_rows.push_back(std::make_unique<Row>(set.id, sticker, count, title, titleWidth, installed, official, unread, archived, removed, pixw, pixh));
|
||||
_animStartTimes.push_back(0);
|
||||
}
|
||||
|
||||
|
@ -1288,8 +1508,8 @@ template <typename Check>
|
|||
Stickers::Order StickersBox::Inner::collectSets(Check check) const {
|
||||
Stickers::Order result;
|
||||
result.reserve(_rows.size());
|
||||
for_const (auto row, _rows) {
|
||||
if (check(row)) {
|
||||
for_const (auto &row, _rows) {
|
||||
if (check(row.get())) {
|
||||
result.push_back(row->id);
|
||||
}
|
||||
}
|
||||
|
@ -1315,8 +1535,8 @@ Stickers::Order StickersBox::Inner::getRemovedSets() const {
|
|||
}
|
||||
|
||||
int StickersBox::Inner::getRowIndex(uint64 setId) const {
|
||||
for (auto i = 0, count = _rows.size(); i != count; ++i) {
|
||||
auto row = _rows[i];
|
||||
for (auto i = 0, count = int(_rows.size()); i != count; ++i) {
|
||||
auto &row = _rows[i];
|
||||
if (row->id == setId) {
|
||||
return i;
|
||||
}
|
||||
|
@ -1328,18 +1548,18 @@ void StickersBox::Inner::setFullOrder(const Stickers::Order &order) {
|
|||
for_const (auto setId, order) {
|
||||
auto index = getRowIndex(setId);
|
||||
if (index >= 0) {
|
||||
auto row = _rows[index];
|
||||
auto row = std::move(_rows[index]);
|
||||
auto count = _rows.size();
|
||||
for (auto i = index + 1; i != count; ++i) {
|
||||
_rows[i - 1] = _rows[i];
|
||||
_rows[i - 1] = std::move(_rows[i]);
|
||||
}
|
||||
_rows[count - 1] = row;
|
||||
_rows[count - 1] = std::move(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::setRemovedSets(const Stickers::Order &removed) {
|
||||
for (auto i = 0, count = _rows.size(); i != count; ++i) {
|
||||
for (auto i = 0, count = int(_rows.size()); i != count; ++i) {
|
||||
setRowRemoved(i, removed.contains(_rows[i]->id));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "base/timer.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
class ConfirmBox;
|
||||
|
||||
|
@ -33,6 +35,8 @@ class PlainShadow;
|
|||
class RippleAnimation;
|
||||
class SettingsSlider;
|
||||
class SlideAnimation;
|
||||
class UsernameInput;
|
||||
class CrossButton;
|
||||
} // namespace Ui
|
||||
|
||||
class StickersBox : public BoxContent, public RPCSender {
|
||||
|
@ -48,6 +52,7 @@ public:
|
|||
StickersBox(QWidget*, gsl::not_null<ChannelData*> megagroup);
|
||||
|
||||
void closeHook() override;
|
||||
void setInnerFocus() override;
|
||||
|
||||
~StickersBox();
|
||||
|
||||
|
@ -142,7 +147,7 @@ private:
|
|||
int stickerPacksCount(bool includeArchivedOfficial = false);
|
||||
|
||||
// This class is hold in header because it requires Qt preprocessing.
|
||||
class StickersBox::Inner : public TWidget, private base::Subscriber {
|
||||
class StickersBox::Inner : public TWidget, private base::Subscriber, private MTP::Sender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -151,8 +156,13 @@ public:
|
|||
Inner(QWidget *parent, const Stickers::Order &archivedIds);
|
||||
Inner(QWidget *parent, gsl::not_null<ChannelData*> megagroup);
|
||||
|
||||
base::Observable<int> scrollToY;
|
||||
void setInnerFocus();
|
||||
|
||||
void saveGroupSet();
|
||||
|
||||
void rebuild();
|
||||
void updateSize();
|
||||
void updateSize(int newWidth = 0);
|
||||
void updateRows(); // refresh only pack cover stickers
|
||||
bool appendSet(const Stickers::Set &set);
|
||||
|
||||
|
@ -171,6 +181,7 @@ public:
|
|||
}
|
||||
|
||||
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||
void setMinHeight(int newWidth, int minHeight);
|
||||
|
||||
int getVisibleTop() const {
|
||||
return _visibleTop;
|
||||
|
@ -180,10 +191,12 @@ public:
|
|||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
||||
|
||||
signals:
|
||||
void draggingScrollDelta(int delta);
|
||||
|
@ -192,6 +205,29 @@ public slots:
|
|||
void onUpdateSelected();
|
||||
|
||||
private:
|
||||
struct Row {
|
||||
Row(uint64 id, DocumentData *sticker, int32 count, const QString &title, int titleWidth, bool installed, bool official, bool unread, bool archived, bool removed, int32 pixw, int32 pixh);
|
||||
bool isRecentSet() const {
|
||||
return (id == Stickers::CloudRecentSetId);
|
||||
}
|
||||
~Row();
|
||||
|
||||
uint64 id = 0;
|
||||
DocumentData *sticker = nullptr;
|
||||
int32 count = 0;
|
||||
QString title;
|
||||
int titleWidth = 0;
|
||||
bool installed = false;
|
||||
bool official = false;
|
||||
bool unread = false;
|
||||
bool archived = false;
|
||||
bool removed = false;
|
||||
int32 pixw = 0;
|
||||
int32 pixh = 0;
|
||||
anim::value yadd;
|
||||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
};
|
||||
|
||||
template <typename Check>
|
||||
Stickers::Order collectSets(Check check) const;
|
||||
|
||||
|
@ -200,63 +236,40 @@ private:
|
|||
int getRowIndex(uint64 setId) const;
|
||||
void setRowRemoved(int index, bool removed);
|
||||
|
||||
void setSelected(int selected);
|
||||
void setActionDown(int newActionDown);
|
||||
void setPressed(int pressed);
|
||||
void setup();
|
||||
QRect relativeButtonRect(bool removeButton) const;
|
||||
void ensureRipple(const style::RippleAnimation &st, QImage mask, bool removeButton);
|
||||
|
||||
void step_shifting(TimeMs ms, bool timer);
|
||||
void paintRow(Painter &p, int index, TimeMs ms);
|
||||
void paintFakeButton(Painter &p, int index, TimeMs ms);
|
||||
void paintRow(Painter &p, Row *set, int index, TimeMs ms);
|
||||
void paintFakeButton(Painter &p, Row *set, int index, TimeMs ms);
|
||||
void clear();
|
||||
void setActionSel(int32 actionSel);
|
||||
float64 aboveShadowOpacity() const;
|
||||
|
||||
void readVisibleSets();
|
||||
|
||||
Section _section;
|
||||
Stickers::Order _archivedIds;
|
||||
|
||||
int32 _rowHeight;
|
||||
struct Row {
|
||||
Row(uint64 id, DocumentData *sticker, int32 count, const QString &title, int titleWidth, bool installed, bool official, bool unread, bool archived, bool removed, int32 pixw, int32 pixh) : id(id)
|
||||
, sticker(sticker)
|
||||
, count(count)
|
||||
, title(title)
|
||||
, titleWidth(titleWidth)
|
||||
, installed(installed)
|
||||
, official(official)
|
||||
, unread(unread)
|
||||
, archived(archived)
|
||||
, removed(removed)
|
||||
, pixw(pixw)
|
||||
, pixh(pixh)
|
||||
, yadd(0, 0) {
|
||||
}
|
||||
bool isRecentSet() const {
|
||||
return (id == Stickers::CloudRecentSetId);
|
||||
}
|
||||
uint64 id;
|
||||
DocumentData *sticker;
|
||||
int32 count;
|
||||
QString title;
|
||||
int titleWidth;
|
||||
bool installed, official, unread, archived, removed;
|
||||
int32 pixw, pixh;
|
||||
anim::value yadd;
|
||||
QSharedPointer<Ui::RippleAnimation> ripple;
|
||||
};
|
||||
using Rows = QList<Row*>;
|
||||
|
||||
void updateControlsGeometry();
|
||||
void rebuildAppendSet(const Stickers::Set &set, int maxNameWidth);
|
||||
void fillSetCover(const Stickers::Set &set, DocumentData **outSticker, int *outWidth, int *outHeight) const;
|
||||
int fillSetCount(const Stickers::Set &set) const;
|
||||
QString fillSetTitle(const Stickers::Set &set, int maxNameWidth, int *outTitleWidth) const;
|
||||
void fillSetFlags(const Stickers::Set &set, bool *outInstalled, bool *outOfficial, bool *outUnread, bool *outArchived);
|
||||
void rebuildMegagroupSet();
|
||||
void handleMegagroupSetAddressChange();
|
||||
void setMegagroupSelectedSet(const MTPInputStickerSet &set);
|
||||
|
||||
int countMaxNameWidth() const;
|
||||
|
||||
Rows _rows;
|
||||
Section _section;
|
||||
Stickers::Order _archivedIds;
|
||||
|
||||
int32 _rowHeight;
|
||||
|
||||
std::vector<std::unique_ptr<Row>> _rows;
|
||||
QList<TimeMs> _animStartTimes;
|
||||
TimeMs _aboveShadowFadeStart = 0;
|
||||
anim::value _aboveShadowFadeOpacity;
|
||||
|
@ -288,7 +301,18 @@ private:
|
|||
int _dragging = -1;
|
||||
int _above = -1;
|
||||
|
||||
int _minHeight = 0;
|
||||
|
||||
int _scrollbar = 0;
|
||||
ChannelData *_megagroupSet = nullptr;
|
||||
MTPInputStickerSet _megagroupSetInput = MTP_inputStickerSetEmpty();
|
||||
std::unique_ptr<Row> _megagroupSelectedSet;
|
||||
object_ptr<Ui::UsernameInput> _megagroupSetField = { nullptr };
|
||||
object_ptr<BoxLayerTitleShadow> _megagroupSelectedShadow = { nullptr };
|
||||
object_ptr<Ui::CrossButton> _megagroupSelectedRemove = { nullptr };
|
||||
object_ptr<BoxContentDivider> _megagroupDivider = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _megagroupSubTitle = { nullptr };
|
||||
base::Timer _megagroupSetAddressChangedTimer;
|
||||
mtpRequestId _megagroupSetRequestId = 0;
|
||||
|
||||
};
|
||||
|
|
|
@ -436,10 +436,10 @@ void StickersListWidget::Footer::step_icons(TimeMs ms, bool timer) {
|
|||
|
||||
StickersListWidget::StickersListWidget(QWidget *parent, gsl::not_null<Window::Controller*> controller) : Inner(parent, controller)
|
||||
, _section(Section::Stickers)
|
||||
, _megagroupSetAbout(st::emojiPanWidth - st::emojiScroll.width - st::emojiPanHeaderLeft)
|
||||
, _addText(lang(lng_stickers_featured_add).toUpper())
|
||||
, _addWidth(st::stickersTrendingAdd.font->width(_addText))
|
||||
, _settings(this, lang(lng_stickers_you_have))
|
||||
, _megagroupSetAbout(st::emojiPanWidth - st::emojiScroll.width - st::emojiPanHeaderLeft) {
|
||||
, _settings(this, lang(lng_stickers_you_have)) {
|
||||
resize(st::emojiPanWidth - st::emojiScroll.width - st::buttonRadius, countHeight());
|
||||
|
||||
setMouseTracking(true);
|
||||
|
@ -877,7 +877,10 @@ bool StickersListWidget::hasRemoveButton(int index) const {
|
|||
}
|
||||
if (set.id == Stickers::MegagroupSetId) {
|
||||
t_assert(_megagroupSet != nullptr);
|
||||
return set.pack.empty() ? (index + 1 != _mySets.size()) : _megagroupSet->canEditStickers();
|
||||
if (index + 1 != _mySets.size()) {
|
||||
return true;
|
||||
}
|
||||
return !set.pack.empty() && _megagroupSet->canEditStickers();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1015,7 +1018,9 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
|||
if (_section == Section::Featured) {
|
||||
installSet(sets[button->section].id);
|
||||
} else if (sets[button->section].id == Stickers::MegagroupSetId) {
|
||||
removeMegagroupSet(sets[button->section].pack.empty());
|
||||
auto removeLocally = sets[button->section].pack.empty()
|
||||
|| !_megagroupSet->canEditStickers();
|
||||
removeMegagroupSet(removeLocally);
|
||||
} else {
|
||||
removeSet(sets[button->section].id);
|
||||
}
|
||||
|
@ -1293,36 +1298,53 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
|
|||
if (!_megagroupSet) {
|
||||
return;
|
||||
}
|
||||
auto canEdit = _megagroupSet->canEditStickers();
|
||||
auto isShownHere = [place](bool hidden) {
|
||||
return (hidden == (place == GroupStickersPlace::Hidden));
|
||||
};
|
||||
if (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetEmpty) {
|
||||
if (_megagroupSet->canEditStickers()) {
|
||||
if (canEdit) {
|
||||
auto hidden = Auth().data().isGroupStickersSectionHidden(_megagroupSet->id);
|
||||
if (hidden == (place == GroupStickersPlace::Hidden)) {
|
||||
if (isShownHere(hidden)) {
|
||||
_mySets.push_back(Set(Stickers::MegagroupSetId, qFlags(MTPDstickerSet_ClientFlag::f_special), lang(lng_group_stickers), 0));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (place != GroupStickersPlace::Visible) {
|
||||
return;
|
||||
}
|
||||
if (Auth().data().isGroupStickersSectionHidden(_megagroupSet->id)) {
|
||||
auto hidden = Auth().data().isGroupStickersSectionHidden(_megagroupSet->id);
|
||||
auto removeHiddenForGroup = [this, &hidden] {
|
||||
if (hidden) {
|
||||
Auth().data().removeGroupStickersSectionHidden(_megagroupSet->id);
|
||||
Local::writeUserSettings();
|
||||
hidden = false;
|
||||
}
|
||||
};
|
||||
if (canEdit && hidden) {
|
||||
removeHiddenForGroup();
|
||||
}
|
||||
if (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) {
|
||||
auto &set = _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID();
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.constFind(set.vid.v);
|
||||
if (it != sets.cend()) {
|
||||
auto isInstalled = (it->flags & MTPDstickerSet::Flag::f_installed)
|
||||
&& !(it->flags & MTPDstickerSet::Flag::f_archived);
|
||||
if (isInstalled && !canEdit) {
|
||||
removeHiddenForGroup();
|
||||
} else if (isShownHere(hidden)) {
|
||||
_mySets.push_back(Set(Stickers::MegagroupSetId, qFlags(MTPDstickerSet_ClientFlag::f_special), lang(lng_group_stickers), it->stickers.size() + 1, it->stickers));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!isShownHere(hidden)) {
|
||||
return;
|
||||
}
|
||||
request(MTPmessages_GetStickerSet(_megagroupSet->mgInfo->stickerSet)).done([this](const MTPmessages_StickerSet &result) {
|
||||
if (auto set = Stickers::FeedSetFull(result)) {
|
||||
refreshStickers();
|
||||
}
|
||||
});
|
||||
}).send();
|
||||
}
|
||||
|
||||
void StickersListWidget::fillIcons(QList<StickerIcon> &icons) {
|
||||
|
@ -1417,6 +1439,9 @@ void StickersListWidget::updateSelected() {
|
|||
newSelected = OverButton { section };
|
||||
} else if (!(sets[section].flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
newSelected = OverSet { section };
|
||||
} else if (sets[section].id == Stickers::MegagroupSetId
|
||||
&& (_megagroupSet->canEditStickers() || !sets[section].pack.empty())) {
|
||||
newSelected = OverSet { section };
|
||||
}
|
||||
} else if (p.y() >= info.rowsTop && p.y() < info.rowsBottom && sx >= 0) {
|
||||
auto yOffset = p.y() - info.rowsTop;
|
||||
|
@ -1578,6 +1603,21 @@ void StickersListWidget::showMegagroupSet(ChannelData *megagroup) {
|
|||
}
|
||||
|
||||
void StickersListWidget::displaySet(uint64 setId) {
|
||||
if (setId == Stickers::MegagroupSetId) {
|
||||
if (_megagroupSet->canEditStickers()) {
|
||||
_displayingSetId = setId;
|
||||
auto box = Ui::show(Box<StickersBox>(_megagroupSet));
|
||||
connect(box, &QObject::destroyed, this, [this] {
|
||||
_displayingSetId = 0;
|
||||
emit checkForHide();
|
||||
});
|
||||
return;
|
||||
} else if (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) {
|
||||
setId = _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid.v;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend()) {
|
||||
|
@ -1608,8 +1648,8 @@ void StickersListWidget::installSet(uint64 setId) {
|
|||
}
|
||||
}
|
||||
|
||||
void StickersListWidget::removeMegagroupSet(bool empty) {
|
||||
if (empty) {
|
||||
void StickersListWidget::removeMegagroupSet(bool locally) {
|
||||
if (locally) {
|
||||
Auth().data().setGroupStickersSectionHidden(_megagroupSet->id);
|
||||
Local::writeUserSettings();
|
||||
refreshStickers();
|
||||
|
@ -1675,4 +1715,6 @@ void StickersListWidget::removeSet(uint64 setId) {
|
|||
}
|
||||
}
|
||||
|
||||
StickersListWidget::~StickersListWidget() = default;
|
||||
|
||||
} // namespace ChatHelpers
|
||||
|
|
|
@ -62,6 +62,8 @@ public:
|
|||
void notInstalledLocally(uint64 setId);
|
||||
void clearInstalledLocally();
|
||||
|
||||
~StickersListWidget();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
@ -148,7 +150,7 @@ private:
|
|||
|
||||
void displaySet(uint64 setId);
|
||||
void installSet(uint64 setId);
|
||||
void removeMegagroupSet(bool empty);
|
||||
void removeMegagroupSet(bool locally);
|
||||
void removeSet(uint64 setId);
|
||||
|
||||
bool setHasTitle(const Set &set) const;
|
||||
|
|
|
@ -3435,7 +3435,7 @@ void MaskedInputField::paintEvent(QPaintEvent *e) {
|
|||
|
||||
auto placeholderTop = anim::interpolate(0, _st.placeholderShift, placeholderShiftDegree);
|
||||
|
||||
QRect r(rect().marginsRemoved(_st.textMargins + _st.placeholderMargins));
|
||||
QRect r(rect().marginsRemoved(_textMargins + _st.placeholderMargins));
|
||||
r.moveTop(r.top() + placeholderTop);
|
||||
if (rtl()) r.moveLeft(width() - r.left() - r.width());
|
||||
|
||||
|
@ -3460,7 +3460,7 @@ void MaskedInputField::paintEvent(QPaintEvent *e) {
|
|||
|
||||
auto placeholderLeft = anim::interpolate(0, -_st.placeholderShift, placeholderHiddenDegree);
|
||||
|
||||
QRect r(rect().marginsRemoved(_st.textMargins + _st.placeholderMargins));
|
||||
QRect r(rect().marginsRemoved(_textMargins + _st.placeholderMargins));
|
||||
r.moveLeft(r.left() + placeholderLeft);
|
||||
if (rtl()) r.moveLeft(width() - r.left() - r.width());
|
||||
|
||||
|
@ -3469,6 +3469,7 @@ void MaskedInputField::paintEvent(QPaintEvent *e) {
|
|||
p.drawText(r, _placeholder, _st.placeholderAlign);
|
||||
|
||||
p.restore();
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3525,7 +3526,7 @@ void MaskedInputField::resizeEvent(QResizeEvent *e) {
|
|||
|
||||
void MaskedInputField::refreshPlaceholder() {
|
||||
auto placeholderText = _placeholderFactory ? _placeholderFactory() : QString();
|
||||
auto availableWidth = width() - _st.textMargins.left() - _st.textMargins.right() - _st.placeholderMargins.left() - _st.placeholderMargins.right() - 1;
|
||||
auto availableWidth = width() - _textMargins.left() - _textMargins.right() - _st.placeholderMargins.left() - _st.placeholderMargins.right() - 1;
|
||||
if (_st.placeholderScale > 0.) {
|
||||
auto placeholderFont = _st.placeholderFont->f;
|
||||
placeholderFont.setStyleStrategy(QFont::PreferMatch);
|
||||
|
@ -3609,7 +3610,7 @@ void MaskedInputField::startPlaceholderAnimation() {
|
|||
}
|
||||
|
||||
QRect MaskedInputField::placeholderRect() const {
|
||||
return rect().marginsRemoved(_st.textMargins + _st.placeholderMargins);
|
||||
return rect().marginsRemoved(_textMargins + _st.placeholderMargins);
|
||||
}
|
||||
|
||||
void MaskedInputField::placeholderAdditionalPrepare(Painter &p, TimeMs ms) {
|
||||
|
@ -3893,8 +3894,12 @@ void PortInput::correctValue(const QString &was, int32 wasCursor, QString &now,
|
|||
setCorrectedText(now, nowCursor, newText, newPos);
|
||||
}
|
||||
|
||||
UsernameInput::UsernameInput(QWidget *parent, const style::InputField &st, base::lambda<QString()> placeholderFactory, const QString &val, bool isLink) : MaskedInputField(parent, st, std::move(placeholderFactory), val)
|
||||
, _linkPlaceholder(isLink ? Messenger::Instance().createInternalLink(QString()) : QString()) {
|
||||
UsernameInput::UsernameInput(QWidget *parent, const style::InputField &st, base::lambda<QString()> placeholderFactory, const QString &val, bool isLink) : MaskedInputField(parent, st, std::move(placeholderFactory), val) {
|
||||
setLinkPlaceholder(isLink ? Messenger::Instance().createInternalLink(QString()) : QString());
|
||||
}
|
||||
|
||||
void UsernameInput::setLinkPlaceholder(const QString &placeholder) {
|
||||
_linkPlaceholder = placeholder;
|
||||
if (!_linkPlaceholder.isEmpty()) {
|
||||
setTextMargins(style::margins(_st.textMargins.left() + _st.font->width(_linkPlaceholder), _st.textMargins.top(), _st.textMargins.right(), _st.textMargins.bottom()));
|
||||
setPlaceholderHidden(true);
|
||||
|
|
|
@ -878,6 +878,8 @@ class UsernameInput : public MaskedInputField {
|
|||
public:
|
||||
UsernameInput(QWidget *parent, const style::InputField &st, base::lambda<QString()> placeholderFactory, const QString &val, bool isLink);
|
||||
|
||||
void setLinkPlaceholder(const QString &placeholder);
|
||||
|
||||
protected:
|
||||
void correctValue(const QString &was, int wasCursor, QString &now, int &nowCursor) override;
|
||||
void paintAdditionalPlaceholder(Painter &p, TimeMs ms) override;
|
||||
|
|
Loading…
Add table
Reference in a new issue