mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-01 03:50:43 +00:00
Move EmojiPanel bottom controls to Controller.
Open sticker set by click on the name. Add a delete sticker set button.
This commit is contained in:
parent
6d27172b20
commit
0690c4f98c
@ -296,7 +296,7 @@ inline QString ComputeId(Args... args) {\n\
|
||||
if (!writeInitCode()) {
|
||||
return false;
|
||||
}
|
||||
if (!writePacks()) {
|
||||
if (!writeSections()) {
|
||||
return false;
|
||||
}
|
||||
source_->stream() << "\
|
||||
@ -391,22 +391,23 @@ void Init() {\n\
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Generator::writePacks() {
|
||||
constexpr const char *packNames[] = {
|
||||
"dbiesPeople",
|
||||
"dbiesNature",
|
||||
"dbiesFood",
|
||||
"dbiesActivity",
|
||||
"dbiesTravel",
|
||||
"dbiesObjects",
|
||||
"dbiesSymbols",
|
||||
bool Generator::writeSections() {
|
||||
constexpr const char *sectionNames[] = {
|
||||
"Section::People",
|
||||
"Section::Nature",
|
||||
"Section::Food",
|
||||
"Section::Activity",
|
||||
"Section::Travel",
|
||||
"Section::Objects",
|
||||
"Section::Symbols",
|
||||
};
|
||||
source_->stream() << "\
|
||||
\n\
|
||||
int GetPackCount(DBIEmojiSection section) {\n\
|
||||
switch (section) {\n";
|
||||
int GetSectionCount(Section section) {\n\
|
||||
switch (section) {\n\
|
||||
case Section::Recent: return GetRecent().size();\n";
|
||||
auto countIndex = 0;
|
||||
for (auto name : packNames) {
|
||||
for (auto name : sectionNames) {
|
||||
if (countIndex >= int(data_.categories.size())) {
|
||||
logDataError() << "category " << countIndex << " not found.";
|
||||
return false;
|
||||
@ -415,21 +416,29 @@ int GetPackCount(DBIEmojiSection section) {\n\
|
||||
case " << name << ": return " << data_.categories[countIndex++].size() << ";\n";
|
||||
}
|
||||
source_->stream() << "\
|
||||
case dbiesRecent: return GetRecent().size();\n\
|
||||
}\n\
|
||||
return 0;\n\
|
||||
}\n\
|
||||
\n\
|
||||
EmojiPack GetPack(DBIEmojiSection section) {\n\
|
||||
switch (section) {\n";
|
||||
EmojiPack GetSection(Section section) {\n\
|
||||
switch (section) {\n\
|
||||
case Section::Recent: {\n\
|
||||
auto result = EmojiPack();\n\
|
||||
result.reserve(GetRecent().size());\n\
|
||||
for (auto &item : GetRecent()) {\n\
|
||||
result.push_back(item.first);\n\
|
||||
}\n\
|
||||
return result;\n\
|
||||
} break;\n";
|
||||
auto index = 0;
|
||||
for (auto name : packNames) {
|
||||
for (auto name : sectionNames) {
|
||||
if (index >= int(data_.categories.size())) {
|
||||
logDataError() << "category " << index << " not found.";
|
||||
return false;
|
||||
}
|
||||
auto &category = data_.categories[index++];
|
||||
source_->stream() << "\
|
||||
\n\
|
||||
case " << name << ": {\n\
|
||||
static auto result = EmojiPack();\n\
|
||||
if (result.isEmpty()) {\n\
|
||||
@ -441,17 +450,9 @@ EmojiPack GetPack(DBIEmojiSection section) {\n\
|
||||
source_->stream() << "\
|
||||
}\n\
|
||||
return result;\n\
|
||||
} break;\n\n";
|
||||
} break;\n";
|
||||
}
|
||||
source_->stream() << "\
|
||||
case dbiesRecent: {\n\
|
||||
auto result = EmojiPack();\n\
|
||||
result.reserve(GetRecent().size());\n\
|
||||
for (auto &item : GetRecent()) {\n\
|
||||
result.push_back(item.first);\n\
|
||||
}\n\
|
||||
return result;\n\
|
||||
} break;\n\
|
||||
}\n\
|
||||
return EmojiPack();\n\
|
||||
}\n";
|
||||
|
@ -44,7 +44,7 @@ private:
|
||||
bool writeSource();
|
||||
|
||||
bool writeInitCode();
|
||||
bool writePacks();
|
||||
bool writeSections();
|
||||
bool writeFindReplace();
|
||||
bool writeFind();
|
||||
bool writeFindFromDictionary(const std::map<QString, int, std::greater<QString>> &dictionary, bool skipPostfixes = false);
|
||||
|
@ -527,18 +527,6 @@ enum DBIScale {
|
||||
|
||||
static const int MatrixRowShift = 40000;
|
||||
|
||||
enum DBIEmojiSection {
|
||||
dbiesRecent = -1,
|
||||
dbiesPeople = 0,
|
||||
dbiesNature = 1,
|
||||
dbiesFood = 2,
|
||||
dbiesActivity = 3,
|
||||
dbiesTravel = 4,
|
||||
dbiesObjects = 5,
|
||||
dbiesSymbols = 6,
|
||||
dbiesStickers = 666,
|
||||
};
|
||||
|
||||
enum DBIPlatform {
|
||||
dbipWindows = 0,
|
||||
dbipMac = 1,
|
||||
|
@ -28,9 +28,22 @@ namespace base {
|
||||
template <typename... Types>
|
||||
using variant = mapbox::util::variant<Types...>;
|
||||
|
||||
template <typename... Types>
|
||||
using optional_variant = variant<std::nullptr_t, Types...>;
|
||||
|
||||
template <typename T, typename... Types>
|
||||
inline T *get_if(variant<Types...> *v) {
|
||||
return (v && v->template is<T>()) ? &v->template get_unchecked<T>() : nullptr;
|
||||
}
|
||||
|
||||
template <typename T, typename... Types>
|
||||
inline const T *get_if(const variant<Types...> *v) {
|
||||
return (v && v->template is<T>()) ? &v->template get_unchecked<T>() : nullptr;
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
inline bool is_null_variant(const optional_variant<Types...> &variant) {
|
||||
return get_if<std::nullptr_t>(&variant) != nullptr;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stickers/emoji_list_widget.h"
|
||||
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "styles/style_stickers.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "lang.h"
|
||||
@ -33,6 +34,70 @@ constexpr auto kSaveRecentEmojiTimeout = 3000;
|
||||
|
||||
} // namespace
|
||||
|
||||
class EmojiListWidget::Footer : public EmojiPanel::InnerFooter {
|
||||
public:
|
||||
Footer(gsl::not_null<EmojiListWidget*> parent);
|
||||
|
||||
void setCurrentSectionIcon(Section section);
|
||||
|
||||
protected:
|
||||
void processPanelHideFinished() override;
|
||||
|
||||
private:
|
||||
void prepareSection(int &left, int top, int _width, Ui::IconButton *sectionIcon, Section section);
|
||||
void setActiveSection(Section section);
|
||||
|
||||
gsl::not_null<EmojiListWidget*> _pan;
|
||||
std::array<object_ptr<Ui::IconButton>, kEmojiSectionCount> _sections;
|
||||
|
||||
};
|
||||
|
||||
EmojiListWidget::Footer::Footer(gsl::not_null<EmojiListWidget*> parent) : InnerFooter(parent)
|
||||
, _pan(parent)
|
||||
, _sections {
|
||||
object_ptr<Ui::IconButton>(this, st::emojiCategoryRecent),
|
||||
object_ptr<Ui::IconButton>(this, st::emojiCategoryPeople),
|
||||
object_ptr<Ui::IconButton>(this, st::emojiCategoryNature),
|
||||
object_ptr<Ui::IconButton>(this, st::emojiCategoryFood),
|
||||
object_ptr<Ui::IconButton>(this, st::emojiCategoryActivity),
|
||||
object_ptr<Ui::IconButton>(this, st::emojiCategoryTravel),
|
||||
object_ptr<Ui::IconButton>(this, st::emojiCategoryObjects),
|
||||
object_ptr<Ui::IconButton>(this, st::emojiCategorySymbols),
|
||||
} {
|
||||
auto left = (st::emojiPanWidth - _sections.size() * st::emojiCategory.width) / 2;
|
||||
for (auto i = 0; i != _sections.size(); ++i) {
|
||||
auto &button = _sections[i];
|
||||
button->moveToLeft(left, 0);
|
||||
left += button->width();
|
||||
button->setClickedCallback([this, value = static_cast<Section>(i)] { setActiveSection(value); });
|
||||
}
|
||||
setCurrentSectionIcon(Section::Recent);
|
||||
}
|
||||
|
||||
void EmojiListWidget::Footer::processPanelHideFinished() {
|
||||
setCurrentSectionIcon(Section::Recent);
|
||||
}
|
||||
|
||||
void EmojiListWidget::Footer::setCurrentSectionIcon(Section section) {
|
||||
std::array<const style::icon *, kEmojiSectionCount> overrides = {
|
||||
&st::emojiRecentActive,
|
||||
&st::emojiPeopleActive,
|
||||
&st::emojiNatureActive,
|
||||
&st::emojiFoodActive,
|
||||
&st::emojiActivityActive,
|
||||
&st::emojiTravelActive,
|
||||
&st::emojiObjectsActive,
|
||||
&st::emojiSymbolsActive,
|
||||
};
|
||||
for (auto i = 0; i != _sections.size(); ++i) {
|
||||
_sections[i]->setIconOverride((section == static_cast<Section>(i)) ? overrides[i] : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiListWidget::Footer::setActiveSection(Ui::Emoji::Section section) {
|
||||
_pan->showEmojiSection(section);
|
||||
}
|
||||
|
||||
EmojiColorPicker::EmojiColorPicker(QWidget *parent) : TWidget(parent) {
|
||||
setMouseTracking(true);
|
||||
|
||||
@ -237,19 +302,6 @@ void EmojiColorPicker::drawVariant(Painter &p, int variant) {
|
||||
p.drawPixmapLeft(w.x() + (st::emojiPanSize.width() - (esize / cIntRetinaFactor())) / 2, w.y() + (st::emojiPanSize.height() - (esize / cIntRetinaFactor())) / 2, width(), App::emojiLarge(), QRect(_variants[variant]->x() * esize, _variants[variant]->y() * esize, esize, esize));
|
||||
}
|
||||
|
||||
class EmojiListWidget::Controller : public TWidget {
|
||||
public:
|
||||
Controller(gsl::not_null<EmojiListWidget*> parent);
|
||||
|
||||
private:
|
||||
gsl::not_null<EmojiListWidget*> _pan;
|
||||
|
||||
};
|
||||
|
||||
EmojiListWidget::Controller::Controller(gsl::not_null<EmojiListWidget*> parent) : TWidget(parent)
|
||||
, _pan(parent) {
|
||||
}
|
||||
|
||||
EmojiListWidget::EmojiListWidget(QWidget *parent) : Inner(parent)
|
||||
, _picker(this) {
|
||||
resize(st::emojiPanWidth - st::emojiScroll.width - st::buttonRadius, countHeight());
|
||||
@ -262,7 +314,7 @@ EmojiListWidget::EmojiListWidget(QWidget *parent) : Inner(parent)
|
||||
_esize = Ui::Emoji::Size(Ui::Emoji::Index() + 1);
|
||||
|
||||
for (auto i = 0; i != kEmojiSectionCount; ++i) {
|
||||
_counts[i] = Ui::Emoji::GetPackCount(EmojiSectionAtIndex(i));
|
||||
_counts[i] = Ui::Emoji::GetSectionCount(static_cast<Section>(i));
|
||||
}
|
||||
|
||||
_showPickerTimer.setSingleShot(true);
|
||||
@ -271,8 +323,18 @@ EmojiListWidget::EmojiListWidget(QWidget *parent) : Inner(parent)
|
||||
connect(_picker, SIGNAL(hidden()), this, SLOT(onPickerHidden()));
|
||||
}
|
||||
|
||||
object_ptr<TWidget> EmojiListWidget::createController() {
|
||||
return object_ptr<Controller>(this);
|
||||
void EmojiListWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
||||
Inner::setVisibleTopBottom(visibleTop, visibleBottom);
|
||||
if (_footer) {
|
||||
_footer->setCurrentSectionIcon(currentSection(visibleTop));
|
||||
}
|
||||
}
|
||||
|
||||
object_ptr<EmojiPanel::InnerFooter> EmojiListWidget::createFooter() {
|
||||
Expects(_footer == nullptr);
|
||||
auto result = object_ptr<Footer>(this);
|
||||
_footer = result;
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
@ -280,7 +342,7 @@ bool EmojiListWidget::enumerateSections(Callback callback) const {
|
||||
auto info = SectionInfo();
|
||||
for (auto i = 0; i != kEmojiSectionCount; ++i) {
|
||||
info.section = i;
|
||||
info.count = Ui::Emoji::GetPackCount(EmojiSectionAtIndex(i));
|
||||
info.count = Ui::Emoji::GetSectionCount(static_cast<Section>(i));
|
||||
info.rowsCount = (info.count / kEmojiPanelPerRow) + ((info.count % kEmojiPanelPerRow) ? 1 : 0);
|
||||
info.rowsTop = info.top + (i == 0 ? st::emojiPanPadding : st::emojiPanHeader);
|
||||
info.rowsBottom = info.rowsTop + info.rowsCount * st::emojiPanSize.height();
|
||||
@ -318,15 +380,16 @@ EmojiListWidget::SectionInfo EmojiListWidget::sectionInfoByOffset(int yOffset) c
|
||||
}
|
||||
|
||||
int EmojiListWidget::countHeight() {
|
||||
return sectionInfo(kEmojiSectionCount - 1).top + st::emojiPanPadding;
|
||||
return sectionInfo(kEmojiSectionCount - 1).rowsBottom + st::emojiPanPadding;
|
||||
}
|
||||
|
||||
void EmojiListWidget::ensureLoaded(int section) {
|
||||
Expects(section >= 0 && section < kEmojiSectionCount);
|
||||
if (!_emoji[section].isEmpty()) {
|
||||
return;
|
||||
}
|
||||
_emoji[section] = Ui::Emoji::GetPack(EmojiSectionAtIndex(section));
|
||||
if (EmojiSectionAtIndex(section) == dbiesRecent) {
|
||||
_emoji[section] = Ui::Emoji::GetSection(static_cast<Section>(section));
|
||||
if (static_cast<Section>(section) == Section::Recent) {
|
||||
return;
|
||||
}
|
||||
for (auto &emoji : _emoji[section]) {
|
||||
@ -477,7 +540,7 @@ void EmojiListWidget::selectEmoji(EmojiPtr emoji) {
|
||||
if (i->first == emoji) {
|
||||
++i->second;
|
||||
if (i->second > 0x8000) {
|
||||
for (RecentEmojiPack::iterator j = recent.begin(); j != e; ++j) {
|
||||
for (auto j = recent.begin(); j != e; ++j) {
|
||||
if (j->second > 1) {
|
||||
j->second /= 2;
|
||||
} else {
|
||||
@ -596,11 +659,15 @@ void EmojiListWidget::clearSelection() {
|
||||
setSelected(-1);
|
||||
}
|
||||
|
||||
DBIEmojiSection EmojiListWidget::currentSection(int yOffset) const {
|
||||
return EmojiSectionAtIndex(sectionInfoByOffset(yOffset).section);
|
||||
Ui::Emoji::Section EmojiListWidget::currentSection(int yOffset) const {
|
||||
return static_cast<Section>(sectionInfoByOffset(yOffset).section);
|
||||
}
|
||||
|
||||
void EmojiListWidget::hideFinish(bool completely) {
|
||||
EmojiPanel::InnerFooter *EmojiListWidget::getFooter() const {
|
||||
return _footer;
|
||||
}
|
||||
|
||||
void EmojiListWidget::processHideFinished() {
|
||||
if (!_picker->isHidden()) {
|
||||
_picker->hideFast();
|
||||
_pickerSel = -1;
|
||||
@ -610,8 +677,8 @@ void EmojiListWidget::hideFinish(bool completely) {
|
||||
|
||||
void EmojiListWidget::refreshRecent() {
|
||||
clearSelection();
|
||||
_counts[0] = Ui::Emoji::GetPackCount(dbiesRecent);
|
||||
_emoji[0] = Ui::Emoji::GetPack(dbiesRecent);
|
||||
_counts[0] = Ui::Emoji::GetSectionCount(Section::Recent);
|
||||
_emoji[0] = Ui::Emoji::GetSection(Section::Recent);
|
||||
auto h = countHeight();
|
||||
if (h != height()) {
|
||||
resize(width(), h);
|
||||
@ -672,14 +739,14 @@ void EmojiListWidget::setSelected(int newSelected) {
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiListWidget::showEmojiSection(DBIEmojiSection section) {
|
||||
void EmojiListWidget::showEmojiSection(Section section) {
|
||||
clearSelection();
|
||||
|
||||
refreshRecent();
|
||||
|
||||
auto y = 0;
|
||||
enumerateSections([&y, sectionForSearch = section](const SectionInfo &info) {
|
||||
if (EmojiSectionAtIndex(info.section) == sectionForSearch) {
|
||||
if (static_cast<Section>(info.section) == sectionForSearch) {
|
||||
y = info.top;
|
||||
return false;
|
||||
}
|
||||
|
@ -25,9 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
namespace ChatHelpers {
|
||||
|
||||
constexpr auto kEmojiSectionCount = 8;
|
||||
inline DBIEmojiSection EmojiSectionAtIndex(int index) {
|
||||
return (index < 0 || index >= kEmojiSectionCount) ? dbiesRecent : DBIEmojiSection(index - 1);
|
||||
}
|
||||
|
||||
class EmojiColorPicker : public TWidget {
|
||||
Q_OBJECT
|
||||
@ -89,13 +86,15 @@ class EmojiListWidget : public EmojiPanel::Inner {
|
||||
public:
|
||||
EmojiListWidget(QWidget *parent);
|
||||
|
||||
void refreshRecent() override;
|
||||
void hideFinish(bool completely) override;
|
||||
void clearSelection() override;
|
||||
object_ptr<TWidget> createController() override;
|
||||
using Section = Ui::Emoji::Section;
|
||||
|
||||
void showEmojiSection(DBIEmojiSection section);
|
||||
DBIEmojiSection currentSection(int yOffset) const;
|
||||
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||
void refreshRecent() override;
|
||||
void clearSelection() override;
|
||||
object_ptr<EmojiPanel::InnerFooter> createFooter() override;
|
||||
|
||||
void showEmojiSection(Section section);
|
||||
Section currentSection(int yOffset) const;
|
||||
|
||||
public slots:
|
||||
void onShowPicker();
|
||||
@ -117,10 +116,13 @@ protected:
|
||||
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
||||
void enterFromChildEvent(QEvent *e, QWidget *child) override;
|
||||
bool event(QEvent *e) override;
|
||||
|
||||
EmojiPanel::InnerFooter *getFooter() const override;
|
||||
void processHideFinished() override;
|
||||
int countHeight() override;
|
||||
|
||||
private:
|
||||
class Controller;
|
||||
class Footer;
|
||||
|
||||
struct SectionInfo {
|
||||
int section = 0;
|
||||
@ -144,6 +146,8 @@ private:
|
||||
|
||||
QRect emojiRect(int section, int sel);
|
||||
|
||||
Footer *_footer = nullptr;
|
||||
|
||||
int _counts[kEmojiSectionCount];
|
||||
QVector<EmojiPtr> _emoji[kEmojiSectionCount];
|
||||
|
||||
|
@ -28,11 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "boxes/stickersetbox.h"
|
||||
#include "boxes/stickers_box.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
#include "inline_bots/inline_bot_result.h"
|
||||
#include "dialogs/dialogs_layout.h"
|
||||
#include "stickers/stickers.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "lang.h"
|
||||
@ -266,7 +262,9 @@ void EmojiPanel::SlideAnimation::paintFrame(QPainter &p, float64 dt, float64 opa
|
||||
EmojiPanel::Tab::Tab(TabType type, object_ptr<Inner> widget)
|
||||
: _type(type)
|
||||
, _widget(std::move(widget))
|
||||
, _weak(_widget) {
|
||||
, _weak(_widget)
|
||||
, _footer(_widget->createFooter()) {
|
||||
_footer->setParent(_widget->parentWidget());
|
||||
}
|
||||
|
||||
object_ptr<EmojiPanel::Inner> EmojiPanel::Tab::takeWidget() {
|
||||
@ -283,15 +281,6 @@ void EmojiPanel::Tab::saveScrollTop() {
|
||||
}
|
||||
|
||||
EmojiPanel::EmojiPanel(QWidget *parent) : TWidget(parent)
|
||||
, _recent(this, st::emojiCategoryRecent)
|
||||
, _people(this, st::emojiCategoryPeople)
|
||||
, _nature(this, st::emojiCategoryNature)
|
||||
, _food(this, st::emojiCategoryFood)
|
||||
, _activity(this, st::emojiCategoryActivity)
|
||||
, _travel(this, st::emojiCategoryTravel)
|
||||
, _objects(this, st::emojiCategoryObjects)
|
||||
, _symbols(this, st::emojiCategorySymbols)
|
||||
, _a_icons(animation(this, &EmojiPanel::step_icons))
|
||||
, _scroll(this, st::emojiScroll)
|
||||
, _tabsSlider(this, st::emojiTabs)
|
||||
, _topShadow(this, st::shadowFg)
|
||||
@ -317,26 +306,13 @@ EmojiPanel::EmojiPanel(QWidget *parent) : TWidget(parent)
|
||||
|
||||
_bottomShadow->setGeometry(_tabsSlider->x(), _scroll->y() + _scroll->height() - st::lineWidth, _tabsSlider->width(), st::lineWidth);
|
||||
|
||||
int32 left = _iconsLeft = innerRect().x() + (st::emojiPanWidth - 8 * st::emojiCategory.width) / 2;
|
||||
int32 top = _iconsTop = innerRect().y() + innerRect().height() - st::emojiCategory.height;
|
||||
prepareSection(left, top, _width, _recent, dbiesRecent);
|
||||
prepareSection(left, top, _width, _people, dbiesPeople);
|
||||
prepareSection(left, top, _width, _nature, dbiesNature);
|
||||
prepareSection(left, top, _width, _food, dbiesFood);
|
||||
prepareSection(left, top, _width, _activity, dbiesActivity);
|
||||
prepareSection(left, top, _width, _travel, dbiesTravel);
|
||||
prepareSection(left, top, _width, _objects, dbiesObjects);
|
||||
prepareSection(left, top, _width, _symbols, dbiesSymbols);
|
||||
|
||||
setCurrentSectionIcon(dbiesRecent);
|
||||
|
||||
_hideTimer.setSingleShot(true);
|
||||
connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideByTimerOrLeave()));
|
||||
|
||||
for (auto &tab : _tabs) {
|
||||
connect(tab.widget(), &Inner::scrollToY, this, [this, tab = &tab](int y) {
|
||||
if (tab == currentTab()) {
|
||||
_scroll->scrollToY(y);
|
||||
scrollToY(y);
|
||||
} else {
|
||||
tab->saveScrollTop(y);
|
||||
}
|
||||
@ -353,17 +329,12 @@ EmojiPanel::EmojiPanel(QWidget *parent) : TWidget(parent)
|
||||
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||
connect(emoji(), SIGNAL(selected(EmojiPtr)), this, SIGNAL(emojiSelected(EmojiPtr)));
|
||||
connect(stickers(), SIGNAL(selected(DocumentData*)), this, SIGNAL(stickerSelected(DocumentData*)));
|
||||
connect(stickers(), SIGNAL(checkForHide()), this, SLOT(onCheckForHide()));
|
||||
connect(gifs(), SIGNAL(selected(DocumentData*)), this, SIGNAL(stickerSelected(DocumentData*)));
|
||||
connect(gifs(), SIGNAL(selected(PhotoData*)), this, SIGNAL(photoSelected(PhotoData*)));
|
||||
connect(gifs(), SIGNAL(selected(InlineBots::Result*, UserData*)), this, SIGNAL(inlineResultSelected(InlineBots::Result*, UserData*)));
|
||||
|
||||
connect(gifs(), SIGNAL(emptyInlineRows()), this, SLOT(onEmptyInlineRows()));
|
||||
|
||||
connect(stickers(), SIGNAL(displaySet(quint64)), this, SLOT(onDisplaySet(quint64)));
|
||||
connect(stickers(), SIGNAL(installSet(quint64)), this, SLOT(onInstallSet(quint64)));
|
||||
connect(stickers(), SIGNAL(removeSet(quint64)), this, SLOT(onRemoveSet(quint64)));
|
||||
connect(stickers(), SIGNAL(refreshIcons(bool)), this, SLOT(onRefreshIcons(bool)));
|
||||
|
||||
_saveConfigTimer.setSingleShot(true);
|
||||
connect(&_saveConfigTimer, SIGNAL(timeout()), this, SLOT(onSaveConfig()));
|
||||
|
||||
@ -379,7 +350,6 @@ EmojiPanel::EmojiPanel(QWidget *parent) : TWidget(parent)
|
||||
_bottomShadow->raise();
|
||||
_tabsSlider->raise();
|
||||
|
||||
setMouseTracking(true);
|
||||
// setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
||||
|
||||
@ -430,25 +400,14 @@ void EmojiPanel::updateContentHeight() {
|
||||
}
|
||||
_bottomShadow->setGeometry(_tabsSlider->x(), _scroll->y() + _scroll->height() - st::lineWidth, _tabsSlider->width(), st::lineWidth);
|
||||
|
||||
_iconsTop = innerRect().y() + innerRect().height() - st::emojiCategory.height;
|
||||
_recent->move(_recent->x(), _iconsTop);
|
||||
_people->move(_people->x(), _iconsTop);
|
||||
_nature->move(_nature->x(), _iconsTop);
|
||||
_food->move(_food->x(), _iconsTop);
|
||||
_activity->move(_activity->x(), _iconsTop);
|
||||
_travel->move(_travel->x(), _iconsTop);
|
||||
_objects->move(_objects->x(), _iconsTop);
|
||||
_symbols->move(_symbols->x(), _iconsTop);
|
||||
_footerTop = innerRect().y() + innerRect().height() - st::emojiCategory.height;
|
||||
for (auto &tab : _tabs) {
|
||||
tab.footer()->move(_tabsSlider->x(), _footerTop);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void EmojiPanel::prepareSection(int &left, int top, int _width, Ui::IconButton *sectionIcon, DBIEmojiSection value) {
|
||||
sectionIcon->moveToLeft(left, top, _width);
|
||||
left += sectionIcon->width();
|
||||
sectionIcon->setClickedCallback([this, value] { setActiveSection(value); });
|
||||
}
|
||||
|
||||
void EmojiPanel::onWndActiveChanged() {
|
||||
if (!App::wnd()->windowHandle()->isActive() && !isHidden()) {
|
||||
leaveEvent(0);
|
||||
@ -463,23 +422,6 @@ void EmojiPanel::onSaveConfigDelayed(int delay) {
|
||||
_saveConfigTimer.start(delay);
|
||||
}
|
||||
|
||||
void EmojiPanel::paintStickerSettingsIcon(Painter &p) const {
|
||||
int settingsLeft = _iconsLeft + 7 * st::emojiCategory.width;
|
||||
st::stickersSettings.paint(p, settingsLeft + st::emojiCategory.iconPosition.x(), _iconsTop + st::emojiCategory.iconPosition.y(), width());
|
||||
}
|
||||
|
||||
void EmojiPanel::paintFeaturedStickerSetsBadge(Painter &p, int iconLeft) const {
|
||||
if (auto unread = Global::FeaturedStickerSetsUnreadCount()) {
|
||||
Dialogs::Layout::UnreadBadgeStyle unreadSt;
|
||||
unreadSt.sizeId = Dialogs::Layout::UnreadBadgeInStickersPanel;
|
||||
unreadSt.size = st::stickersSettingsUnreadSize;
|
||||
int unreadRight = iconLeft + st::emojiCategory.width - st::stickersSettingsUnreadPosition.x();
|
||||
if (rtl()) unreadRight = width() - unreadRight;
|
||||
int unreadTop = _iconsTop + st::stickersSettingsUnreadPosition.y();
|
||||
Dialogs::Layout::paintUnreadCount(p, QString::number(unread), unreadRight, unreadTop, unreadSt);
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
@ -544,7 +486,7 @@ void EmojiPanel::paintContent(Painter &p) {
|
||||
App::roundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, App::RectPart::TopFull | App::RectPart::NoTopBottom);
|
||||
|
||||
auto showSectionIcons = (_currentTabType != TabType::Gifs);
|
||||
auto bottomPart = QRect(inner.x(), _iconsTop - st::buttonRadius, inner.width(), st::emojiCategory.height + st::buttonRadius);
|
||||
auto bottomPart = QRect(inner.x(), _footerTop - st::buttonRadius, inner.width(), st::emojiCategory.height + st::buttonRadius);
|
||||
auto &bottomBg = showSectionIcons ? st::emojiPanCategories : st::emojiPanBg;
|
||||
auto bottomParts = App::RectPart::NoTopBottom | App::RectPart::BottomFull;
|
||||
App::roundRect(p, bottomPart, bottomBg, ImageRoundRadius::Small, bottomParts);
|
||||
@ -554,81 +496,6 @@ void EmojiPanel::paintContent(Painter &p) {
|
||||
auto sidesHeight = _scroll->y() + _scroll->height() - sidesTop;
|
||||
p.fillRect(myrtlrect(inner.x() + inner.width() - st::emojiScroll.width, sidesTop, st::emojiScroll.width, sidesHeight), st::emojiPanBg);
|
||||
p.fillRect(myrtlrect(inner.x(), sidesTop, st::buttonRadius, sidesHeight), st::emojiPanBg);
|
||||
|
||||
switch (_currentTabType) {
|
||||
case TabType::Emoji: {
|
||||
auto vertical = verticalRect();
|
||||
p.fillRect(vertical.x(), _iconsTop, vertical.width(), st::emojiCategory.height - st::buttonRadius, st::emojiPanCategories);
|
||||
} break;
|
||||
|
||||
case TabType::Stickers: {
|
||||
paintStickerSettingsIcon(p);
|
||||
|
||||
if (!_icons.isEmpty()) {
|
||||
auto x = _iconsLeft;
|
||||
auto selxrel = _iconsLeft + qRound(_iconSelX.current());
|
||||
auto selx = selxrel - qRound(_iconsX.current());
|
||||
|
||||
QRect clip(x, _iconsTop, _iconsLeft + 7 * st::emojiCategory.width - x, st::emojiCategory.height);
|
||||
if (rtl()) clip.moveLeft(width() - x - clip.width());
|
||||
p.setClipRect(clip);
|
||||
|
||||
auto getSpecialSetIcon = [](uint64 setId, bool active) {
|
||||
if (setId == Stickers::FeaturedSetId) {
|
||||
return active ? &st::stickersTrendingActive : &st::stickersTrending;
|
||||
}
|
||||
return active ? &st::emojiRecentActive : &st::emojiRecent;
|
||||
};
|
||||
|
||||
int i = 0;
|
||||
auto iconsX = qRound(_iconsX.current());
|
||||
i += iconsX / int(st::emojiCategory.width);
|
||||
x -= iconsX % int(st::emojiCategory.width);
|
||||
selxrel -= iconsX;
|
||||
for (int l = qMin(_icons.size(), i + 8); i < l; ++i) {
|
||||
auto &s = _icons.at(i);
|
||||
if (s.sticker) {
|
||||
s.sticker->thumb->load();
|
||||
QPixmap pix(s.sticker->thumb->pix(s.pixw, s.pixh));
|
||||
|
||||
p.drawPixmapLeft(x + (st::emojiCategory.width - s.pixw) / 2, _iconsTop + (st::emojiCategory.height - s.pixh) / 2, width(), pix);
|
||||
x += st::emojiCategory.width;
|
||||
} else {
|
||||
getSpecialSetIcon(s.setId, false)->paint(p, x + st::emojiCategory.iconPosition.x(), _iconsTop + st::emojiCategory.iconPosition.y(), width());
|
||||
if (s.setId == Stickers::FeaturedSetId) {
|
||||
paintFeaturedStickerSetsBadge(p, x);
|
||||
}
|
||||
x += st::emojiCategory.width;
|
||||
}
|
||||
}
|
||||
|
||||
if (rtl()) selx = width() - selx - st::emojiCategory.width;
|
||||
p.fillRect(selx, _iconsTop + st::emojiCategory.height - st::stickerIconPadding, st::emojiCategory.width, st::stickerIconSel, st::stickerIconSelColor);
|
||||
|
||||
auto o_left = snap(_iconsX.current() / st::stickerIconLeft.width(), 0., 1.);
|
||||
if (o_left > 0) {
|
||||
p.setOpacity(o_left);
|
||||
st::stickerIconLeft.fill(p, rtlrect(_iconsLeft, _iconsTop, st::stickerIconLeft.width(), st::emojiCategory.height, width()));
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
auto o_right = snap((_iconsMax - _iconsX.current()) / st::stickerIconRight.width(), 0., 1.);
|
||||
if (o_right > 0) {
|
||||
p.setOpacity(o_right);
|
||||
st::stickerIconRight.fill(p, rtlrect(_iconsLeft + 7 * st::emojiCategory.width - st::stickerIconRight.width(), _iconsTop, st::stickerIconRight.width(), st::emojiCategory.height, width()));
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
|
||||
p.setClipRect(QRect());
|
||||
}
|
||||
} break;
|
||||
|
||||
case TabType::Gifs: {
|
||||
p.fillRect(myrtlrect(inner.x() + inner.width() - st::emojiScroll.width, _iconsTop, st::emojiScroll.width, st::emojiCategory.height - st::buttonRadius), st::emojiPanBg);
|
||||
p.fillRect(myrtlrect(inner.x(), _iconsTop, st::buttonRadius, st::emojiCategory.height - st::buttonRadius), st::emojiPanBg);
|
||||
} break;
|
||||
|
||||
default: Unexpected("Bad tab type.");
|
||||
}
|
||||
}
|
||||
|
||||
int EmojiPanel::marginTop() const {
|
||||
@ -653,7 +520,7 @@ void EmojiPanel::enterEventHook(QEvent *e) {
|
||||
}
|
||||
|
||||
bool EmojiPanel::preventAutoHide() const {
|
||||
return _removingSetId || _displayingSetId;
|
||||
return stickers()->preventAutoHide();
|
||||
}
|
||||
|
||||
void EmojiPanel::leaveEventHook(QEvent *e) {
|
||||
@ -686,101 +553,6 @@ void EmojiPanel::otherLeave() {
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::mousePressEvent(QMouseEvent *e) {
|
||||
if (_currentTabType != TabType::Stickers || e->button() != Qt::LeftButton) {
|
||||
return;
|
||||
}
|
||||
_iconsMousePos = e ? e->globalPos() : QCursor::pos();
|
||||
updateSelected();
|
||||
|
||||
if (_iconOver == _icons.size()) {
|
||||
Ui::show(Box<StickersBox>(StickersBox::Section::Installed));
|
||||
} else {
|
||||
_iconDown = _iconOver;
|
||||
_iconsMouseDown = _iconsMousePos;
|
||||
_iconsStartX = qRound(_iconsX.current());
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (_currentTabType != TabType::Stickers) {
|
||||
return;
|
||||
}
|
||||
_iconsMousePos = e ? e->globalPos() : QCursor::pos();
|
||||
updateSelected();
|
||||
|
||||
if (!_iconsDragging && !_icons.isEmpty() && _iconDown >= 0) {
|
||||
if ((_iconsMousePos - _iconsMouseDown).manhattanLength() >= QApplication::startDragDistance()) {
|
||||
_iconsDragging = true;
|
||||
}
|
||||
}
|
||||
if (_iconsDragging) {
|
||||
auto newX = snap(_iconsStartX + (rtl() ? -1 : 1) * (_iconsMouseDown.x() - _iconsMousePos.x()), 0, _iconsMax);
|
||||
if (newX != qRound(_iconsX.current())) {
|
||||
_iconsX = anim::value(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
_a_icons.stop();
|
||||
updateIcons();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (_currentTabType != TabType::Stickers || _icons.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto wasDown = _iconDown;
|
||||
_iconDown = -1;
|
||||
|
||||
_iconsMousePos = e ? e->globalPos() : QCursor::pos();
|
||||
if (_iconsDragging) {
|
||||
auto newX = snap(_iconsStartX + _iconsMouseDown.x() - _iconsMousePos.x(), 0, _iconsMax);
|
||||
if (newX != qRound(_iconsX.current())) {
|
||||
_iconsX = anim::value(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
_a_icons.stop();
|
||||
updateIcons();
|
||||
}
|
||||
_iconsDragging = false;
|
||||
updateSelected();
|
||||
} else {
|
||||
updateSelected();
|
||||
|
||||
if (wasDown == _iconOver && _iconOver >= 0 && _iconOver < _icons.size()) {
|
||||
_iconSelX = anim::value(_iconOver * st::emojiCategory.width, _iconOver * st::emojiCategory.width);
|
||||
stickers()->showStickerSet(_icons[_iconOver].setId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EmojiPanel::event(QEvent *e) {
|
||||
if (e->type() == QEvent::TouchBegin) {
|
||||
|
||||
} else if (e->type() == QEvent::Wheel) {
|
||||
if (!_icons.isEmpty() && _iconOver >= 0 && _iconOver < _icons.size() && _iconDown < 0) {
|
||||
QWheelEvent *ev = static_cast<QWheelEvent*>(e);
|
||||
bool hor = (ev->angleDelta().x() != 0 || ev->orientation() == Qt::Horizontal);
|
||||
bool ver = (ev->angleDelta().y() != 0 || ev->orientation() == Qt::Vertical);
|
||||
if (hor) _horizontal = true;
|
||||
auto newX = qRound(_iconsX.current());
|
||||
if (/*_horizontal && */hor) {
|
||||
newX = snap(newX - (rtl() ? -1 : 1) * (ev->pixelDelta().x() ? ev->pixelDelta().x() : ev->angleDelta().x()), 0, _iconsMax);
|
||||
} else if (/*!_horizontal && */ver) {
|
||||
newX = snap(newX - (ev->pixelDelta().y() ? ev->pixelDelta().y() : ev->angleDelta().y()), 0, _iconsMax);
|
||||
}
|
||||
if (newX != qRound(_iconsX.current())) {
|
||||
_iconsX = anim::value(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
_a_icons.stop();
|
||||
updateSelected();
|
||||
updateIcons();
|
||||
}
|
||||
}
|
||||
}
|
||||
return TWidget::event(e);
|
||||
}
|
||||
|
||||
void EmojiPanel::hideFast() {
|
||||
if (isHidden()) return;
|
||||
|
||||
@ -806,99 +578,6 @@ void EmojiPanel::refreshSavedGifs() {
|
||||
update();
|
||||
}
|
||||
|
||||
void EmojiPanel::onRefreshIcons(bool scrollAnimation) {
|
||||
_iconOver = -1;
|
||||
stickers()->fillIcons(_icons);
|
||||
_iconsX.finish();
|
||||
_iconSelX.finish();
|
||||
_iconsStartAnim = 0;
|
||||
_a_icons.stop();
|
||||
if (_icons.isEmpty()) {
|
||||
_iconsMax = 0;
|
||||
} else {
|
||||
_iconsMax = qMax(int((_icons.size() - 7) * st::emojiCategory.width), 0);
|
||||
}
|
||||
if (_iconsX.current() > _iconsMax) {
|
||||
_iconsX = anim::value(_iconsMax, _iconsMax);
|
||||
}
|
||||
updateSelected();
|
||||
if (_currentTabType == TabType::Stickers) {
|
||||
validateSelectedIcon(scrollAnimation ? ValidateIconAnimations::Scroll : ValidateIconAnimations::None);
|
||||
updateContentHeight();
|
||||
}
|
||||
updateIcons();
|
||||
}
|
||||
|
||||
void EmojiPanel::leaveToChildEvent(QEvent *e, QWidget *child) {
|
||||
if (_currentTabType != TabType::Stickers) {
|
||||
return;
|
||||
}
|
||||
_iconsMousePos = QCursor::pos();
|
||||
updateSelected();
|
||||
}
|
||||
|
||||
void EmojiPanel::updateSelected() {
|
||||
if (_iconDown >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
QPoint p(mapFromGlobal(_iconsMousePos));
|
||||
int32 x = p.x(), y = p.y(), newOver = -1;
|
||||
if (rtl()) x = width() - x;
|
||||
x -= _iconsLeft;
|
||||
if (x >= st::emojiCategory.width * 7 && x < st::emojiCategory.width * 8 && y >= _iconsTop && y < _iconsTop + st::emojiCategory.height) {
|
||||
newOver = _icons.size();
|
||||
} else if (!_icons.isEmpty()) {
|
||||
if (y >= _iconsTop && y < _iconsTop + st::emojiCategory.height && x >= 0 && x < 7 * st::emojiCategory.width && x < _icons.size() * st::emojiCategory.width) {
|
||||
x += qRound(_iconsX.current());
|
||||
newOver = qFloor(x / st::emojiCategory.width);
|
||||
}
|
||||
}
|
||||
if (newOver != _iconOver) {
|
||||
if (newOver < 0) {
|
||||
setCursor(style::cur_default);
|
||||
} else if (_iconOver < 0) {
|
||||
setCursor(style::cur_pointer);
|
||||
}
|
||||
_iconOver = newOver;
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::updateIcons() {
|
||||
if (_currentTabType != TabType::Stickers) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto verticalInner = rect().marginsRemoved(st::emojiPanMargins).marginsRemoved(QMargins(st::buttonRadius, 0, st::buttonRadius, 0));
|
||||
update(verticalInner.left(), _iconsTop, verticalInner.width(), st::emojiCategory.height);
|
||||
}
|
||||
|
||||
void EmojiPanel::step_icons(TimeMs ms, bool timer) {
|
||||
if (_currentTabType != TabType::Stickers) {
|
||||
_a_icons.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_iconsStartAnim) {
|
||||
float64 dt = (ms - _iconsStartAnim) / float64(st::stickerIconMove);
|
||||
if (dt >= 1) {
|
||||
_iconsStartAnim = 0;
|
||||
_iconsX.finish();
|
||||
_iconSelX.finish();
|
||||
} else {
|
||||
_iconsX.update(dt, anim::linear);
|
||||
_iconSelX.update(dt, anim::linear);
|
||||
}
|
||||
if (timer) updateSelected();
|
||||
}
|
||||
|
||||
if (timer) updateIcons();
|
||||
|
||||
if (!_iconsStartAnim) {
|
||||
_a_icons.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::opacityAnimationCallback() {
|
||||
update();
|
||||
if (!_a_opacity.animating()) {
|
||||
@ -1004,23 +683,17 @@ EmojiPanel::~EmojiPanel() = default;
|
||||
|
||||
void EmojiPanel::hideFinished() {
|
||||
hide();
|
||||
currentTab()->widget()->hideFinish(true);
|
||||
for (auto &tab : _tabs) {
|
||||
tab.widget()->panelHideFinished();
|
||||
}
|
||||
_a_show.finish();
|
||||
_showAnimation.reset();
|
||||
_a_slide.finish();
|
||||
_slideAnimation.reset();
|
||||
_cache = QPixmap();
|
||||
_horizontal = false;
|
||||
_hiding = false;
|
||||
|
||||
_scroll->scrollToY(0);
|
||||
setCurrentSectionIcon(dbiesRecent);
|
||||
_iconOver = _iconDown = -1;
|
||||
_iconSel = 0;
|
||||
_iconsX = anim::value();
|
||||
_iconSelX = anim::value();
|
||||
_iconsStartAnim = 0;
|
||||
_a_icons.stop();
|
||||
scrollToY(0);
|
||||
|
||||
Notify::clipStopperHidden(ClipStopperSavedGifsPanel);
|
||||
}
|
||||
@ -1079,25 +752,7 @@ bool EmojiPanel::ui_isInlineItemBeingChosen() {
|
||||
}
|
||||
|
||||
void EmojiPanel::showAll() {
|
||||
if (_currentTabType == TabType::Emoji) {
|
||||
_recent->show();
|
||||
_people->show();
|
||||
_nature->show();
|
||||
_food->show();
|
||||
_activity->show();
|
||||
_travel->show();
|
||||
_objects->show();
|
||||
_symbols->show();
|
||||
} else {
|
||||
_recent->hide();
|
||||
_people->hide();
|
||||
_nature->hide();
|
||||
_food->hide();
|
||||
_activity->hide();
|
||||
_travel->hide();
|
||||
_objects->hide();
|
||||
_symbols->hide();
|
||||
}
|
||||
currentTab()->footer()->show();
|
||||
_scroll->show();
|
||||
_topShadow->show();
|
||||
_bottomShadow->setVisible(_currentTabType == TabType::Gifs);
|
||||
@ -1111,74 +766,10 @@ void EmojiPanel::hideForSliding() {
|
||||
currentTab()->widget()->clearSelection();
|
||||
}
|
||||
|
||||
void EmojiPanel::setActiveSection(DBIEmojiSection tab) {
|
||||
emoji()->showEmojiSection(tab);
|
||||
}
|
||||
|
||||
void EmojiPanel::onScroll() {
|
||||
auto scrollTop = _scroll->scrollTop();
|
||||
auto scrollBottom = scrollTop + _scroll->height();
|
||||
currentTab()->widget()->setVisibleTopBottom(scrollTop, scrollBottom);
|
||||
|
||||
switch (_currentTabType) {
|
||||
case TabType::Emoji: {
|
||||
setCurrentSectionIcon(emoji()->currentSection(scrollTop));
|
||||
} break;
|
||||
|
||||
case TabType::Stickers: {
|
||||
validateSelectedIcon(ValidateIconAnimations::Full);
|
||||
} break;
|
||||
|
||||
case TabType::Gifs: {
|
||||
if (scrollBottom > _scroll->scrollTopMax()) {
|
||||
onInlineRequest();
|
||||
}
|
||||
} break;
|
||||
|
||||
default: Unexpected("Bad type value.");
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::setCurrentSectionIcon(DBIEmojiSection section) {
|
||||
_recent->setIconOverride((section == dbiesRecent) ? &st::emojiRecentActive : nullptr);
|
||||
_people->setIconOverride((section == dbiesPeople) ? &st::emojiPeopleActive : nullptr);
|
||||
_nature->setIconOverride((section == dbiesNature) ? &st::emojiNatureActive : nullptr);
|
||||
_food->setIconOverride((section == dbiesFood) ? &st::emojiFoodActive : nullptr);
|
||||
_activity->setIconOverride((section == dbiesActivity) ? &st::emojiActivityActive : nullptr);
|
||||
_travel->setIconOverride((section == dbiesTravel) ? &st::emojiTravelActive : nullptr);
|
||||
_objects->setIconOverride((section == dbiesObjects) ? &st::emojiObjectsActive : nullptr);
|
||||
_symbols->setIconOverride((section == dbiesSymbols) ? &st::emojiSymbolsActive : nullptr);
|
||||
}
|
||||
|
||||
void EmojiPanel::validateSelectedIcon(ValidateIconAnimations animations) {
|
||||
auto setId = stickers()->currentSet(_scroll->scrollTop());
|
||||
auto newSel = 0;
|
||||
for (auto i = 0, l = _icons.size(); i != l; ++i) {
|
||||
if (_icons[i].setId == setId) {
|
||||
newSel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newSel != _iconSel) {
|
||||
_iconSel = newSel;
|
||||
auto iconSelXFinal = newSel * st::emojiCategory.width;
|
||||
if (animations == ValidateIconAnimations::Full) {
|
||||
_iconSelX.start(iconSelXFinal);
|
||||
} else {
|
||||
_iconSelX = anim::value(iconSelXFinal, iconSelXFinal);
|
||||
}
|
||||
auto iconsXFinal = snap((2 * newSel - 7) * int(st::emojiCategory.width) / 2, 0, _iconsMax);
|
||||
if (animations == ValidateIconAnimations::None) {
|
||||
_iconsX = anim::value(iconsXFinal, iconsXFinal);
|
||||
_a_icons.stop();
|
||||
} else {
|
||||
_iconsX.start(iconsXFinal);
|
||||
_iconsStartAnim = getms();
|
||||
_a_icons.start();
|
||||
}
|
||||
updateSelected();
|
||||
updateIcons();
|
||||
}
|
||||
}
|
||||
|
||||
style::margins EmojiPanel::innerPadding() const {
|
||||
@ -1230,19 +821,13 @@ void EmojiPanel::switchTab() {
|
||||
auto widget = _scroll->takeWidget<Inner>();
|
||||
widget->setParent(this);
|
||||
widget->hide();
|
||||
currentTab()->footer()->hide();
|
||||
currentTab()->returnWidget(std::move(widget));
|
||||
|
||||
_currentTabType = newTabType;
|
||||
if (_currentTabType != TabType::Gifs) {
|
||||
if (_currentTabType == TabType::Gifs) {
|
||||
Notify::clipStopperHidden(ClipStopperSavedGifsPanel);
|
||||
}
|
||||
if (_currentTabType == TabType::Stickers) {
|
||||
validateSelectedIcon(ValidateIconAnimations::None);
|
||||
}
|
||||
updateContentHeight();
|
||||
_iconOver = -1;
|
||||
_a_icons.stop();
|
||||
|
||||
setWidgetToScrollArea();
|
||||
|
||||
auto nowCache = grabForComplexAnimation(GrabType::Slide);
|
||||
@ -1261,7 +846,7 @@ void EmojiPanel::switchTab() {
|
||||
|
||||
hideForSliding();
|
||||
|
||||
getTab(wasTab)->widget()->hideFinish(false);
|
||||
getTab(wasTab)->widget()->hideFinished();
|
||||
|
||||
_a_slide.start([this] { update(); }, 0., 1., st::emojiPanSlideDuration, anim::linear);
|
||||
update();
|
||||
@ -1287,88 +872,15 @@ void EmojiPanel::setWidgetToScrollArea() {
|
||||
_scroll->disableScroll(false);
|
||||
currentTab()->widget()->moveToLeft(0, 0);
|
||||
currentTab()->widget()->show();
|
||||
_scroll->scrollToY(currentTab()->getScrollTop());
|
||||
scrollToY(currentTab()->getScrollTop());
|
||||
updateContentHeight();
|
||||
onScroll();
|
||||
}
|
||||
|
||||
void EmojiPanel::onDisplaySet(quint64 setId) {
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend()) {
|
||||
_displayingSetId = setId;
|
||||
auto box = Ui::show(Box<StickerSetBox>(Stickers::inputSetId(*it)), KeepOtherLayers);
|
||||
connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onDelayedHide()));
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::onInstallSet(quint64 setId) {
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend()) {
|
||||
request(MTPmessages_InstallStickerSet(Stickers::inputSetId(*it), MTP_bool(false))).done([this](const MTPmessages_StickerSetInstallResult &result) {
|
||||
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
|
||||
Stickers::applyArchivedResult(result.c_messages_stickerSetInstallResultArchive());
|
||||
}
|
||||
}).fail([this, setId](const RPCError &error) {
|
||||
stickers()->notInstalledLocally(setId);
|
||||
Stickers::undoInstallLocally(setId);
|
||||
}).send();
|
||||
|
||||
stickers()->installedLocally(setId);
|
||||
Stickers::installLocally(setId);
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::onRemoveSet(quint64 setId) {
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) {
|
||||
_removingSetId = it->id;
|
||||
auto text = lng_stickers_remove_pack(lt_sticker_pack, it->title);
|
||||
Ui::show(Box<ConfirmBox>(text, lang(lng_box_remove), base::lambda_guarded(this, [this] {
|
||||
Ui::hideLayer();
|
||||
auto &sets = Global::RefStickerSets();
|
||||
auto it = sets.find(_removingSetId);
|
||||
if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) {
|
||||
if (it->id && it->access) {
|
||||
request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)))).send();
|
||||
} else if (!it->shortName.isEmpty()) {
|
||||
request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(it->shortName)))).send();
|
||||
}
|
||||
bool writeRecent = false;
|
||||
RecentStickerPack &recent(cGetRecentStickers());
|
||||
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0) {
|
||||
i = recent.erase(i);
|
||||
writeRecent = true;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
it->flags &= ~MTPDstickerSet::Flag::f_installed;
|
||||
if (!(it->flags & MTPDstickerSet_ClientFlag::f_featured) && !(it->flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
sets.erase(it);
|
||||
}
|
||||
int removeIndex = Global::StickerSetsOrder().indexOf(_removingSetId);
|
||||
if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex);
|
||||
refreshStickers();
|
||||
Local::writeInstalledStickers();
|
||||
if (writeRecent) Local::writeUserSettings();
|
||||
}
|
||||
_removingSetId = 0;
|
||||
onDelayedHide();
|
||||
}), base::lambda_guarded(this, [this] {
|
||||
onDelayedHide();
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::onDelayedHide() {
|
||||
void EmojiPanel::onCheckForHide() {
|
||||
if (!rect().contains(mapFromGlobal(QCursor::pos()))) {
|
||||
_hideTimer.start(3000);
|
||||
}
|
||||
_removingSetId = 0;
|
||||
_displayingSetId = 0;
|
||||
}
|
||||
|
||||
void EmojiPanel::clearInlineBot() {
|
||||
@ -1525,11 +1037,18 @@ bool EmojiPanel::refreshInlineRows(int32 *added) {
|
||||
return (entry != nullptr);
|
||||
}
|
||||
|
||||
void EmojiPanel::scrollToY(int y) {
|
||||
_scroll->scrollToY(y);
|
||||
|
||||
// Qt render glitch workaround, shadow sometimes disappears if we just scroll to y.
|
||||
_topShadow->update();
|
||||
}
|
||||
|
||||
int32 EmojiPanel::showInlineRows(bool newResults) {
|
||||
int32 added = 0;
|
||||
bool clear = !refreshInlineRows(&added);
|
||||
if (newResults) {
|
||||
_scroll->scrollToY(0);
|
||||
scrollToY(0);
|
||||
}
|
||||
|
||||
auto hidden = isHidden();
|
||||
@ -1560,4 +1079,23 @@ void EmojiPanel::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::Inner::hideFinished() {
|
||||
processHideFinished();
|
||||
if (auto footer = getFooter()) {
|
||||
footer->processHideFinished();
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPanel::Inner::panelHideFinished() {
|
||||
hideFinished();
|
||||
processPanelHideFinished();
|
||||
if (auto footer = getFooter()) {
|
||||
footer->processPanelHideFinished();
|
||||
}
|
||||
}
|
||||
|
||||
EmojiPanel::InnerFooter::InnerFooter(QWidget *parent) : TWidget(parent) {
|
||||
resize(st::emojiPanWidth, st::emojiCategory.height);
|
||||
}
|
||||
|
||||
} // namespace ChatHelpers
|
||||
|
@ -21,7 +21,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#pragma once
|
||||
|
||||
#include "ui/twidget.h"
|
||||
#include "ui/abstract_button.h"
|
||||
#include "ui/effects/panel_animation.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "inline_bots/inline_bot_layout_item.h"
|
||||
@ -37,9 +36,6 @@ class Result;
|
||||
namespace Ui {
|
||||
class PlainShadow;
|
||||
class ScrollArea;
|
||||
class IconButton;
|
||||
class LinkButton;
|
||||
class RoundButton;
|
||||
class RippleAnimation;
|
||||
class SettingsSlider;
|
||||
} // namesapce Ui
|
||||
@ -60,18 +56,6 @@ struct InlineCacheEntry {
|
||||
InlineResults results;
|
||||
};
|
||||
|
||||
struct StickerIcon {
|
||||
StickerIcon(uint64 setId) : setId(setId) {
|
||||
}
|
||||
StickerIcon(uint64 setId, DocumentData *sticker, int32 pixw, int32 pixh) : setId(setId), sticker(sticker), pixw(pixw), pixh(pixh) {
|
||||
}
|
||||
uint64 setId = 0;
|
||||
DocumentData *sticker = nullptr;
|
||||
int pixw = 0;
|
||||
int pixh = 0;
|
||||
|
||||
};
|
||||
|
||||
class EmojiPanel : public TWidget, private MTP::Sender {
|
||||
Q_OBJECT
|
||||
|
||||
@ -87,10 +71,6 @@ public:
|
||||
return _hiding || _hideTimer.isActive();
|
||||
}
|
||||
|
||||
void step_icons(TimeMs ms, bool timer);
|
||||
|
||||
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
||||
|
||||
void stickersInstalled(uint64 setId);
|
||||
|
||||
void queryInlineBot(UserData *bot, PeerData *peer, QString query);
|
||||
@ -106,6 +86,7 @@ public:
|
||||
~EmojiPanel();
|
||||
|
||||
class Inner;
|
||||
class InnerFooter;
|
||||
|
||||
protected:
|
||||
void enterEventHook(QEvent *e) override;
|
||||
@ -113,30 +94,20 @@ protected:
|
||||
void otherEnter();
|
||||
void otherLeave();
|
||||
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
bool event(QEvent *e) override;
|
||||
bool eventFilter(QObject *obj, QEvent *e) override;
|
||||
|
||||
public slots:
|
||||
void refreshStickers();
|
||||
|
||||
private slots:
|
||||
private slots:
|
||||
void hideByTimerOrLeave();
|
||||
void refreshSavedGifs();
|
||||
|
||||
void onWndActiveChanged();
|
||||
void onScroll();
|
||||
|
||||
void onDisplaySet(quint64 setId);
|
||||
void onInstallSet(quint64 setId);
|
||||
void onRemoveSet(quint64 setId);
|
||||
void onDelayedHide();
|
||||
|
||||
void onRefreshIcons(bool scrollAnimation);
|
||||
void onCheckForHide();
|
||||
|
||||
void onSaveConfig();
|
||||
void onSaveConfigDelayed(int delay);
|
||||
@ -169,6 +140,9 @@ private:
|
||||
gsl::not_null<Inner*> widget() const {
|
||||
return _weak;
|
||||
}
|
||||
gsl::not_null<InnerFooter*> footer() const {
|
||||
return _footer;
|
||||
}
|
||||
|
||||
void saveScrollTop();
|
||||
void saveScrollTop(int scrollTop) {
|
||||
@ -182,6 +156,7 @@ private:
|
||||
TabType _type = TabType::Emoji;
|
||||
object_ptr<Inner> _widget = { nullptr };
|
||||
QPointer<Inner> _weak;
|
||||
object_ptr<InnerFooter> _footer;
|
||||
int _scrollTop = 0;
|
||||
|
||||
};
|
||||
@ -215,31 +190,16 @@ private:
|
||||
void startOpacityAnimation(bool hiding);
|
||||
void prepareCache();
|
||||
|
||||
void scrollToY(int y);
|
||||
|
||||
void opacityAnimationCallback();
|
||||
|
||||
void hideFinished();
|
||||
void showStarted();
|
||||
|
||||
bool preventAutoHide() const;
|
||||
void setActiveSection(DBIEmojiSection section);
|
||||
void setCurrentSectionIcon(DBIEmojiSection section);
|
||||
|
||||
void paintStickerSettingsIcon(Painter &p) const;
|
||||
void paintFeaturedStickerSetsBadge(Painter &p, int iconLeft) const;
|
||||
|
||||
enum class ValidateIconAnimations {
|
||||
Full,
|
||||
Scroll,
|
||||
None,
|
||||
};
|
||||
void validateSelectedIcon(ValidateIconAnimations animations);
|
||||
void updateContentHeight();
|
||||
|
||||
void updateSelected();
|
||||
void updateIcons();
|
||||
|
||||
void prepareSection(int &left, int top, int _width, Ui::IconButton *sectionIcon, DBIEmojiSection section);
|
||||
|
||||
void showAll();
|
||||
void hideForSliding();
|
||||
|
||||
@ -266,11 +226,11 @@ private:
|
||||
int _minBottom = 0;
|
||||
int _contentMaxHeight = 0;
|
||||
int _contentHeight = 0;
|
||||
bool _horizontal = false;
|
||||
|
||||
int _width = 0;
|
||||
int _height = 0;
|
||||
int _bottom = 0;
|
||||
int _footerTop = 0;
|
||||
|
||||
std::unique_ptr<Ui::PanelAnimation> _showAnimation;
|
||||
Animation _a_show;
|
||||
@ -286,30 +246,6 @@ private:
|
||||
std::unique_ptr<SlideAnimation> _slideAnimation;
|
||||
Animation _a_slide;
|
||||
|
||||
object_ptr<Ui::IconButton> _recent;
|
||||
object_ptr<Ui::IconButton> _people;
|
||||
object_ptr<Ui::IconButton> _nature;
|
||||
object_ptr<Ui::IconButton> _food;
|
||||
object_ptr<Ui::IconButton> _activity;
|
||||
object_ptr<Ui::IconButton> _travel;
|
||||
object_ptr<Ui::IconButton> _objects;
|
||||
object_ptr<Ui::IconButton> _symbols;
|
||||
|
||||
QList<StickerIcon> _icons;
|
||||
int _iconOver = -1;
|
||||
int _iconSel = 0;
|
||||
int _iconDown = -1;
|
||||
bool _iconsDragging = false;
|
||||
BasicAnimation _a_icons;
|
||||
QPoint _iconsMousePos, _iconsMouseDown;
|
||||
int _iconsLeft = 0;
|
||||
int _iconsTop = 0;
|
||||
int _iconsStartX = 0;
|
||||
int _iconsMax = 0;
|
||||
anim::value _iconsX;
|
||||
anim::value _iconSelX;
|
||||
TimeMs _iconsStartAnim = 0;
|
||||
|
||||
object_ptr<Ui::SettingsSlider> _tabsSlider = { nullptr };
|
||||
object_ptr<Ui::PlainShadow> _topShadow;
|
||||
object_ptr<Ui::PlainShadow> _bottomShadow;
|
||||
@ -317,9 +253,6 @@ private:
|
||||
std::array<Tab, Tab::kCount> _tabs;
|
||||
TabType _currentTabType = TabType::Emoji;
|
||||
|
||||
uint64 _displayingSetId = 0;
|
||||
uint64 _removingSetId = 0;
|
||||
|
||||
QTimer _saveConfigTimer;
|
||||
|
||||
// inline bots
|
||||
@ -355,10 +288,11 @@ public:
|
||||
virtual void refreshRecent() = 0;
|
||||
virtual void preloadImages() {
|
||||
}
|
||||
virtual void hideFinish(bool completely) = 0;
|
||||
void hideFinished();
|
||||
void panelHideFinished();
|
||||
virtual void clearSelection() = 0;
|
||||
|
||||
virtual object_ptr<TWidget> createController() = 0;
|
||||
virtual object_ptr<InnerFooter> createFooter() = 0;
|
||||
|
||||
signals:
|
||||
void scrollToY(int y);
|
||||
@ -367,6 +301,11 @@ signals:
|
||||
|
||||
protected:
|
||||
virtual int countHeight() = 0;
|
||||
virtual InnerFooter *getFooter() const = 0;
|
||||
virtual void processHideFinished() {
|
||||
}
|
||||
virtual void processPanelHideFinished() {
|
||||
}
|
||||
|
||||
private:
|
||||
int _visibleTop = 0;
|
||||
@ -374,4 +313,17 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class EmojiPanel::InnerFooter : public TWidget {
|
||||
public:
|
||||
InnerFooter(QWidget *parent);
|
||||
|
||||
protected:
|
||||
virtual void processHideFinished() {
|
||||
}
|
||||
virtual void processPanelHideFinished() {
|
||||
}
|
||||
friend class Inner;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ChatHelpers
|
||||
|
@ -39,19 +39,26 @@ constexpr auto kInlineItemsMaxPerRow = 5;
|
||||
|
||||
} // namespace
|
||||
|
||||
class GifsListWidget::Controller : public TWidget {
|
||||
class GifsListWidget::Footer : public EmojiPanel::InnerFooter {
|
||||
public:
|
||||
Controller(gsl::not_null<GifsListWidget*> parent);
|
||||
Footer(gsl::not_null<GifsListWidget*> parent);
|
||||
|
||||
protected:
|
||||
void processPanelHideFinished() override;
|
||||
|
||||
private:
|
||||
gsl::not_null<GifsListWidget*> _pan;
|
||||
|
||||
};
|
||||
|
||||
GifsListWidget::Controller::Controller(gsl::not_null<GifsListWidget*> parent) : TWidget(parent)
|
||||
GifsListWidget::Footer::Footer(gsl::not_null<GifsListWidget*> parent) : InnerFooter(parent)
|
||||
, _pan(parent) {
|
||||
}
|
||||
|
||||
void GifsListWidget::Footer::processPanelHideFinished() {
|
||||
// TODO Clear search
|
||||
}
|
||||
|
||||
GifsListWidget::GifsListWidget(QWidget *parent) : Inner(parent)
|
||||
, _section(Section::Gifs) {
|
||||
resize(st::emojiPanWidth - st::emojiScroll.width - st::buttonRadius, countHeight());
|
||||
@ -70,8 +77,11 @@ GifsListWidget::GifsListWidget(QWidget *parent) : Inner(parent)
|
||||
});
|
||||
}
|
||||
|
||||
object_ptr<TWidget> GifsListWidget::createController() {
|
||||
return object_ptr<Controller>(this);
|
||||
object_ptr<EmojiPanel::InnerFooter> GifsListWidget::createFooter() {
|
||||
Expects(_footer == nullptr);
|
||||
auto result = object_ptr<Footer>(this);
|
||||
_footer = result;
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
void GifsListWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
||||
@ -80,6 +90,10 @@ void GifsListWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
||||
if (top != getVisibleTop()) {
|
||||
_lastScrolled = getms();
|
||||
}
|
||||
auto visibleHeight = (visibleBottom - visibleTop);
|
||||
if (visibleBottom + visibleHeight > height()) {
|
||||
// onInlineRequest(); // TODO
|
||||
}
|
||||
}
|
||||
|
||||
int GifsListWidget::countHeight() {
|
||||
@ -252,27 +266,32 @@ void GifsListWidget::clearSelection() {
|
||||
update();
|
||||
}
|
||||
|
||||
void GifsListWidget::hideFinish(bool completely) {
|
||||
EmojiPanel::InnerFooter *GifsListWidget::getFooter() const {
|
||||
return _footer;
|
||||
}
|
||||
|
||||
void GifsListWidget::processHideFinished() {
|
||||
clearSelection();
|
||||
if (completely) {
|
||||
auto itemForget = [](auto &item) {
|
||||
if (auto document = item->getDocument()) {
|
||||
document->forget();
|
||||
}
|
||||
if (auto photo = item->getPhoto()) {
|
||||
photo->forget();
|
||||
}
|
||||
if (auto result = item->getResult()) {
|
||||
result->forget();
|
||||
}
|
||||
};
|
||||
clearInlineRows(false);
|
||||
for_const (auto &item, _gifLayouts) {
|
||||
itemForget(item.second);
|
||||
}
|
||||
|
||||
void GifsListWidget::processPanelHideFinished() {
|
||||
auto itemForget = [](auto &item) {
|
||||
if (auto document = item->getDocument()) {
|
||||
document->forget();
|
||||
}
|
||||
for_const (auto &item, _inlineLayouts) {
|
||||
itemForget(item.second);
|
||||
if (auto photo = item->getPhoto()) {
|
||||
photo->forget();
|
||||
}
|
||||
if (auto result = item->getResult()) {
|
||||
result->forget();
|
||||
}
|
||||
};
|
||||
clearInlineRows(false);
|
||||
for_const (auto &item, _gifLayouts) {
|
||||
itemForget(item.second);
|
||||
}
|
||||
for_const (auto &item, _inlineLayouts) {
|
||||
itemForget(item.second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,7 +522,8 @@ int GifsListWidget::refreshInlineRows(UserData *bot, const InlineCacheEntry *ent
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (clearResults()) {
|
||||
auto clearResultsResult = clearResults();
|
||||
if (clearResultsResult) {
|
||||
if (resultsDeleted) {
|
||||
clearInlineRows(true);
|
||||
deleteUnusedInlineLayouts();
|
||||
|
@ -22,6 +22,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "stickers/emoji_panel.h"
|
||||
|
||||
namespace Ui {
|
||||
class RoundButton;
|
||||
} // namespace Ui
|
||||
|
||||
namespace ChatHelpers {
|
||||
|
||||
class GifsListWidget : public EmojiPanel::Inner, public InlineBots::Layout::Context, private base::Subscriber {
|
||||
@ -32,9 +36,8 @@ public:
|
||||
|
||||
void refreshRecent() override;
|
||||
void preloadImages() override;
|
||||
void hideFinish(bool completely) override;
|
||||
void clearSelection() override;
|
||||
object_ptr<TWidget> createController() override;
|
||||
object_ptr<EmojiPanel::InnerFooter> createFooter() override;
|
||||
|
||||
void refreshSavedGifs();
|
||||
int refreshInlineRows(UserData *bot, const InlineCacheEntry *results, bool resultsDeleted);
|
||||
@ -58,6 +61,10 @@ protected:
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
||||
void enterFromChildEvent(QEvent *e, QWidget *child) override;
|
||||
|
||||
EmojiPanel::InnerFooter *getFooter() const override;
|
||||
void processHideFinished() override;
|
||||
void processPanelHideFinished() override;
|
||||
int countHeight() override;
|
||||
|
||||
private slots:
|
||||
@ -78,7 +85,7 @@ private:
|
||||
Inlines,
|
||||
Gifs,
|
||||
};
|
||||
class Controller;
|
||||
class Footer;
|
||||
|
||||
void updateSelected();
|
||||
void paintInlineItems(Painter &p, QRect clip);
|
||||
@ -120,6 +127,8 @@ private:
|
||||
int validateExistingInlineRows(const InlineResults &results);
|
||||
void selectInlineResult(int row, int column);
|
||||
|
||||
Footer *_footer = nullptr;
|
||||
|
||||
int _selected = -1;
|
||||
int _pressed = -1;
|
||||
QPoint _lastMousePos;
|
||||
|
@ -153,10 +153,10 @@ emojiPanPadding: 12px;
|
||||
emojiPanSize: size(45px, 41px);
|
||||
emojiPanWidth: 345px;
|
||||
emojiPanMaxHeight: 366px;
|
||||
emojiPanShowDuration: 2000;
|
||||
emojiPanDuration: 2000;
|
||||
emojiPanShowDuration: 200;
|
||||
emojiPanDuration: 200;
|
||||
emojiPanHover: windowBgOver;
|
||||
emojiPanSlideDuration: 2000;
|
||||
emojiPanSlideDuration: 200;
|
||||
|
||||
emojiPanHeader: 42px;
|
||||
emojiPanHeaderFont: semiboldFont;
|
||||
@ -173,21 +173,6 @@ emojiSwitchColor: windowActiveTextFg;
|
||||
emojiSwitchStickers: icon {{ "emoji_switch", emojiSwitchColor }};
|
||||
emojiSwitchEmoji: icon {{ "emoji_switch-flip_horizontal", emojiSwitchColor }};
|
||||
|
||||
stickerPanSize: size(64px, 64px);
|
||||
stickerPanPadding: 11px;
|
||||
stickerPanDelete: icon {
|
||||
{ "emoji_delete_bg", stickerPanDeleteBg },
|
||||
{ "emoji_delete", stickerPanDeleteFg },
|
||||
};
|
||||
stickerPanDeleteOpacity: 0.5;
|
||||
stickerIconPadding: 5px;
|
||||
stickerIconOpacity: 0.7;
|
||||
stickerIconSel: 2px;
|
||||
stickerIconSelColor: emojiIconFgActive;
|
||||
stickerIconMove: 400;
|
||||
stickerPreviewDuration: 150;
|
||||
stickerPreviewMin: 0.1;
|
||||
|
||||
hashtagClose: IconButton {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
@ -203,6 +188,22 @@ hashtagClose: IconButton {
|
||||
}
|
||||
}
|
||||
|
||||
stickerPanSize: size(64px, 64px);
|
||||
stickerPanPadding: 11px;
|
||||
stickerPanDelete: icon {
|
||||
{ "emoji_delete_bg", stickerPanDeleteBg },
|
||||
{ "emoji_delete", stickerPanDeleteFg },
|
||||
};
|
||||
stickerPanDeleteOpacity: 0.5;
|
||||
stickerPanRemoveSet: hashtagClose;
|
||||
stickerIconPadding: 5px;
|
||||
stickerIconOpacity: 0.7;
|
||||
stickerIconSel: 2px;
|
||||
stickerIconSelColor: emojiIconFgActive;
|
||||
stickerIconMove: 400;
|
||||
stickerPreviewDuration: 150;
|
||||
stickerPreviewMin: 0.1;
|
||||
|
||||
stickersToastMaxWidth: 340px;
|
||||
stickersToastPadding: margins(16px, 13px, 16px, 12px);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,10 +21,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#pragma once
|
||||
|
||||
#include "stickers/emoji_panel.h"
|
||||
#include "core/variant.h"
|
||||
|
||||
namespace Ui {
|
||||
class LinkButton;
|
||||
} // namespace Ui
|
||||
|
||||
namespace ChatHelpers {
|
||||
|
||||
class StickersListWidget : public EmojiPanel::Inner, private base::Subscriber {
|
||||
struct StickerIcon;
|
||||
|
||||
class StickersListWidget : public EmojiPanel::Inner, private base::Subscriber, private MTP::Sender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@ -32,9 +39,8 @@ public:
|
||||
|
||||
void refreshRecent() override;
|
||||
void preloadImages() override;
|
||||
void hideFinish(bool completely) override;
|
||||
void clearSelection() override;
|
||||
object_ptr<TWidget> createController() override;
|
||||
object_ptr<EmojiPanel::InnerFooter> createFooter() override;
|
||||
|
||||
void showStickerSet(uint64 setId);
|
||||
|
||||
@ -42,6 +48,7 @@ public:
|
||||
void refreshRecentStickers(bool resize = true);
|
||||
|
||||
void fillIcons(QList<StickerIcon> &icons);
|
||||
bool preventAutoHide();
|
||||
|
||||
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||
|
||||
@ -60,6 +67,10 @@ protected:
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
||||
void enterFromChildEvent(QEvent *e, QWidget *child) override;
|
||||
|
||||
EmojiPanel::InnerFooter *getFooter() const override;
|
||||
void processHideFinished() override;
|
||||
void processPanelHideFinished() override;
|
||||
int countHeight() override;
|
||||
|
||||
private slots:
|
||||
@ -68,23 +79,38 @@ private slots:
|
||||
|
||||
signals:
|
||||
void selected(DocumentData *sticker);
|
||||
|
||||
void displaySet(quint64 setId);
|
||||
void installSet(quint64 setId);
|
||||
void removeSet(quint64 setId);
|
||||
|
||||
void refreshIcons(bool scrollAnimation);
|
||||
void scrollUpdated();
|
||||
void checkForHide();
|
||||
|
||||
private:
|
||||
class Footer;
|
||||
|
||||
enum class Section {
|
||||
Featured,
|
||||
Stickers,
|
||||
};
|
||||
class Controller;
|
||||
|
||||
static constexpr auto kRefreshIconsScrollAnimation = true;
|
||||
static constexpr auto kRefreshIconsNoAnimation = false;
|
||||
struct OverSticker {
|
||||
int section;
|
||||
int index;
|
||||
bool overDelete;
|
||||
};
|
||||
struct OverSet {
|
||||
int section;
|
||||
};
|
||||
struct OverButton {
|
||||
int section;
|
||||
};
|
||||
friend inline bool operator==(OverSticker a, OverSticker b) {
|
||||
return (a.section == b.section) && (a.index == b.index) && (a.overDelete == b.overDelete);
|
||||
}
|
||||
friend inline bool operator==(OverSet a, OverSet b) {
|
||||
return (a.section == b.section);
|
||||
}
|
||||
friend inline bool operator==(OverButton a, OverButton b) {
|
||||
return (a.section == b.section);
|
||||
}
|
||||
using OverState = base::optional_variant<OverSticker, OverSet, OverButton>;
|
||||
|
||||
struct SectionInfo {
|
||||
int section = 0;
|
||||
@ -99,10 +125,22 @@ private:
|
||||
SectionInfo sectionInfo(int section) const;
|
||||
SectionInfo sectionInfoByOffset(int yOffset) const;
|
||||
|
||||
void updateSelected();
|
||||
void setSelected(int newSelected, int newSelectedFeaturedSet, int newSelectedFeaturedSetAdd);
|
||||
void displaySet(quint64 setId);
|
||||
void installSet(quint64 setId);
|
||||
void removeSet(quint64 setId);
|
||||
|
||||
void setPressedFeaturedSetAdd(int newPressedFeaturedSetAdd);
|
||||
void updateSelected();
|
||||
void setSelected(OverState newSelected);
|
||||
void setPressed(OverState newPressed);
|
||||
QSharedPointer<Ui::RippleAnimation> createButtonRipple(int section);
|
||||
QPoint buttonRippleTopLeft(int section) const;
|
||||
|
||||
enum class ValidateIconAnimations {
|
||||
Full,
|
||||
Scroll,
|
||||
None,
|
||||
};
|
||||
void validateSelectedIcon(ValidateIconAnimations animations);
|
||||
|
||||
struct Set {
|
||||
Set(uint64 id, MTPDstickerSet::Flags flags, const QString &title, int32 hoversSize, const StickerPack &pack = StickerPack()) : id(id), flags(flags), title(title), pack(pack) {
|
||||
@ -126,9 +164,12 @@ private:
|
||||
void paintFeaturedStickers(Painter &p, QRect clip);
|
||||
void paintStickers(Painter &p, QRect clip);
|
||||
void paintSticker(Painter &p, Set &set, int y, int index, bool selected, bool deleteSelected);
|
||||
|
||||
int stickersRight() const;
|
||||
bool featuredHasAddButton(int index) const;
|
||||
int featuredContentWidth() const;
|
||||
QRect featuredAddRect(int y) const;
|
||||
QRect featuredAddRect(int index) const;
|
||||
bool hasRemoveButton(int index) const;
|
||||
QRect removeButtonRect(int index) const;
|
||||
|
||||
enum class AppendSkip {
|
||||
Archived,
|
||||
@ -140,6 +181,8 @@ private:
|
||||
int stickersLeft() const;
|
||||
QRect stickerRect(int section, int sel);
|
||||
|
||||
void removeRecentSticker(int section, int index);
|
||||
|
||||
Sets _mySets;
|
||||
Sets _featuredSets;
|
||||
OrderedSet<uint64> _installedLocallySets;
|
||||
@ -147,15 +190,14 @@ private:
|
||||
|
||||
Section _section = Section::Stickers;
|
||||
|
||||
void removeRecentSticker(int section, int index);
|
||||
uint64 _displayingSetId = 0;
|
||||
uint64 _removingSetId = 0;
|
||||
|
||||
int _selected = -1;
|
||||
int _pressed = -1;
|
||||
int _selectedFeaturedSet = -1;
|
||||
int _pressedFeaturedSet = -1;
|
||||
int _selectedFeaturedSetAdd = -1;
|
||||
int _pressedFeaturedSetAdd = -1;
|
||||
QPoint _lastMousePos;
|
||||
Footer *_footer = nullptr;
|
||||
|
||||
OverState _selected = nullptr;
|
||||
OverState _pressed = nullptr;
|
||||
QPoint _lastMousePosition;
|
||||
|
||||
QString _addText;
|
||||
int _addWidth;
|
||||
|
@ -15239,23 +15239,32 @@ void Init() {
|
||||
Items.emplace_back(internal::ComputeId(0xd83c, 0xddff, 0xd83c, 0xddfc), 6, 54, false, false, nullptr, tag);
|
||||
}
|
||||
|
||||
int GetPackCount(DBIEmojiSection tab) {
|
||||
switch (tab) {
|
||||
case dbiesPeople: return 291;
|
||||
case dbiesNature: return 159;
|
||||
case dbiesFood: return 86;
|
||||
case dbiesActivity: return 80;
|
||||
case dbiesTravel: return 119;
|
||||
case dbiesObjects: return 173;
|
||||
case dbiesSymbols: return 524;
|
||||
case dbiesRecent: return GetRecent().size();
|
||||
int GetSectionCount(Section section) {
|
||||
switch (section) {
|
||||
case Section::Recent: return GetRecent().size();
|
||||
case Section::People: return 291;
|
||||
case Section::Nature: return 159;
|
||||
case Section::Food: return 86;
|
||||
case Section::Activity: return 80;
|
||||
case Section::Travel: return 119;
|
||||
case Section::Objects: return 173;
|
||||
case Section::Symbols: return 524;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EmojiPack GetPack(DBIEmojiSection tab) {
|
||||
switch (tab) {
|
||||
case dbiesPeople: {
|
||||
EmojiPack GetSection(Section section) {
|
||||
switch (section) {
|
||||
case Section::Recent: {
|
||||
auto result = EmojiPack();
|
||||
result.reserve(GetRecent().size());
|
||||
for (auto &item : GetRecent()) {
|
||||
result.push_back(item.first);
|
||||
}
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case Section::People: {
|
||||
static auto result = EmojiPack();
|
||||
if (result.isEmpty()) {
|
||||
result.reserve(291);
|
||||
@ -15554,7 +15563,7 @@ EmojiPack GetPack(DBIEmojiSection tab) {
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case dbiesNature: {
|
||||
case Section::Nature: {
|
||||
static auto result = EmojiPack();
|
||||
if (result.isEmpty()) {
|
||||
result.reserve(159);
|
||||
@ -15721,7 +15730,7 @@ EmojiPack GetPack(DBIEmojiSection tab) {
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case dbiesFood: {
|
||||
case Section::Food: {
|
||||
static auto result = EmojiPack();
|
||||
if (result.isEmpty()) {
|
||||
result.reserve(86);
|
||||
@ -15815,7 +15824,7 @@ EmojiPack GetPack(DBIEmojiSection tab) {
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case dbiesActivity: {
|
||||
case Section::Activity: {
|
||||
static auto result = EmojiPack();
|
||||
if (result.isEmpty()) {
|
||||
result.reserve(80);
|
||||
@ -15903,7 +15912,7 @@ EmojiPack GetPack(DBIEmojiSection tab) {
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case dbiesTravel: {
|
||||
case Section::Travel: {
|
||||
static auto result = EmojiPack();
|
||||
if (result.isEmpty()) {
|
||||
result.reserve(119);
|
||||
@ -16030,7 +16039,7 @@ EmojiPack GetPack(DBIEmojiSection tab) {
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case dbiesObjects: {
|
||||
case Section::Objects: {
|
||||
static auto result = EmojiPack();
|
||||
if (result.isEmpty()) {
|
||||
result.reserve(173);
|
||||
@ -16211,7 +16220,7 @@ EmojiPack GetPack(DBIEmojiSection tab) {
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case dbiesSymbols: {
|
||||
case Section::Symbols: {
|
||||
static auto result = EmojiPack();
|
||||
if (result.isEmpty()) {
|
||||
result.reserve(524);
|
||||
@ -16742,15 +16751,6 @@ EmojiPack GetPack(DBIEmojiSection tab) {
|
||||
}
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case dbiesRecent: {
|
||||
auto result = EmojiPack();
|
||||
result.reserve(GetRecent().size());
|
||||
for (auto &item : GetRecent()) {
|
||||
result.push_back(item.first);
|
||||
}
|
||||
return result;
|
||||
} break;
|
||||
}
|
||||
return EmojiPack();
|
||||
}
|
||||
|
@ -24,6 +24,22 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
namespace Ui {
|
||||
namespace Emoji {
|
||||
|
||||
constexpr auto kPostfix = static_cast<ushort>(0xFE0F);
|
||||
constexpr auto kPanelPerRow = 7;
|
||||
constexpr auto kPanelRowsPerPage = 6;
|
||||
|
||||
enum class Section {
|
||||
Recent,
|
||||
People,
|
||||
Nature,
|
||||
Food,
|
||||
Activity,
|
||||
Travel,
|
||||
Objects,
|
||||
Symbols,
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
EmojiPtr ByIndex(int index);
|
||||
@ -50,10 +66,6 @@ EmojiPtr FindReplace(const QChar *ch, const QChar *end, int *outLength = nullptr
|
||||
|
||||
void Init();
|
||||
|
||||
constexpr auto kPostfix = static_cast<ushort>(0xFE0F);
|
||||
constexpr auto kPanelPerRow = 7;
|
||||
constexpr auto kPanelRowsPerPage = 6;
|
||||
|
||||
class One {
|
||||
struct CreationTag {
|
||||
};
|
||||
@ -221,8 +233,8 @@ inline QString Filename(int index = Index()) {
|
||||
return QString::fromLatin1(EmojiNames[index]);
|
||||
}
|
||||
|
||||
int GetPackCount(DBIEmojiSection tab);
|
||||
EmojiPack GetPack(DBIEmojiSection tab);
|
||||
int GetSectionCount(Section section);
|
||||
EmojiPack GetSection(Section section);
|
||||
|
||||
inline void appendPartToResult(QString &result, const QChar *start, const QChar *from, const QChar *to, EntitiesInText *inOutEntities) {
|
||||
if (to > from) {
|
||||
|
Loading…
Reference in New Issue
Block a user