Featured stickers section done in StickersPanel.

EmojiPan moved to a separate module stickers/emoji_pan.
FFmpeg linked by msvs linker flags in GYP to use ".a" extension.
This commit is contained in:
John Preston 2016-09-09 18:52:46 +03:00
parent 82d92d21f6
commit ff657347b8
19 changed files with 4703 additions and 4252 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

After

Width:  |  Height:  |  Size: 241 KiB

View File

@ -1866,6 +1866,8 @@ emojiSymbolsActive: sprite(287px, 286px, 21px, 22px);
stickersSettings: sprite(140px, 124px, 21px, 22px);
savedGifsOver: sprite(329px, 286px, 21px, 22px);
savedGifsActive: sprite(350px, 286px, 21px, 22px);
featuredStickersOver: sprite(329px, 264px, 21px, 22px);
featuredStickersActive: sprite(350px, 264px, 21px, 22px);
stickersSettingsUnreadSize: 17px;
stickersSettingsUnreadPosition: point(4px, 5px);

View File

@ -684,6 +684,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_switch_stickers" = "Stickers";
"lng_switch_stickers_gifs" = "GIFs & Stickers";
"lng_switch_emoji" = "Emoji";
"lng_stickers_featured_add" = "Add";
"lng_saved_gifs" = "Saved GIFs";
"lng_inline_bot_results" = "Results from {inline_bot}";

View File

@ -959,17 +959,17 @@ void AppClass::killDownloadSessions() {
void AppClass::photoUpdated(const FullMsgId &msgId, bool silent, const MTPInputFile &file) {
if (!App::self()) return;
QMap<FullMsgId, PeerId>::iterator i = photoUpdates.find(msgId);
auto i = photoUpdates.find(msgId);
if (i != photoUpdates.end()) {
PeerId id = i.value();
auto id = i.value();
if (MTP::authedId() && peerToUser(id) == MTP::authedId()) {
MTP::send(MTPphotos_UploadProfilePhoto(file, MTP_string(""), MTP_inputGeoPointEmpty(), MTP_inputPhotoCrop(MTP_double(0), MTP_double(0), MTP_double(100))), rpcDone(&AppClass::selfPhotoDone), rpcFail(&AppClass::peerPhotoFail, id));
} else if (peerIsChat(id)) {
History *hist = App::history(id);
hist->sendRequestId = MTP::send(MTPmessages_EditChatPhoto(hist->peer->asChat()->inputChat, MTP_inputChatUploadedPhoto(file, MTP_inputPhotoCrop(MTP_double(0), MTP_double(0), MTP_double(100)))), rpcDone(&AppClass::chatPhotoDone, id), rpcFail(&AppClass::peerPhotoFail, id), 0, 0, hist->sendRequestId);
auto history = App::history(id);
history->sendRequestId = MTP::send(MTPmessages_EditChatPhoto(history->peer->asChat()->inputChat, MTP_inputChatUploadedPhoto(file, MTP_inputPhotoCrop(MTP_double(0), MTP_double(0), MTP_double(100)))), rpcDone(&AppClass::chatPhotoDone, id), rpcFail(&AppClass::peerPhotoFail, id), 0, 0, history->sendRequestId);
} else if (peerIsChannel(id)) {
History *hist = App::history(id);
hist->sendRequestId = MTP::send(MTPchannels_EditPhoto(hist->peer->asChannel()->inputChannel, MTP_inputChatUploadedPhoto(file, MTP_inputPhotoCrop(MTP_double(0), MTP_double(0), MTP_double(100)))), rpcDone(&AppClass::chatPhotoDone, id), rpcFail(&AppClass::peerPhotoFail, id), 0, 0, hist->sendRequestId);
auto history = App::history(id);
history->sendRequestId = MTP::send(MTPchannels_EditPhoto(history->peer->asChannel()->inputChannel, MTP_inputChatUploadedPhoto(file, MTP_inputPhotoCrop(MTP_double(0), MTP_double(0), MTP_double(100)))), rpcDone(&AppClass::chatPhotoDone, id), rpcFail(&AppClass::peerPhotoFail, id), 0, 0, history->sendRequestId);
}
}
}

View File

@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stickersetbox.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "stickers/stickers.h"
#include "boxes/confirmbox.h"
#include "apiwrap.h"
#include "localstorage.h"
@ -37,54 +38,6 @@ constexpr int kArchivedLimitPerPage = 30;
} // namespace
namespace Stickers {
void applyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
auto &v = d.vsets.c_vector().v;
auto &order = Global::RefStickerSetsOrder();
Stickers::Order archived;
archived.reserve(v.size());
QMap<uint64, uint64> setsToRequest;
for_const (auto &stickerSet, v) {
const MTPDstickerSet *setData = nullptr;
switch (stickerSet.type()) {
case mtpc_stickerSetCovered: {
auto &d = stickerSet.c_stickerSetCovered();
if (d.vset.type() == mtpc_stickerSet) {
setData = &d.vset.c_stickerSet();
}
} break;
case mtpc_stickerSetMultiCovered: {
auto &d = stickerSet.c_stickerSetMultiCovered();
if (d.vset.type() == mtpc_stickerSet) {
setData = &d.vset.c_stickerSet();
}
} break;
}
if (setData) {
auto set = Stickers::feedSet(*setData);
if (set->stickers.isEmpty()) {
setsToRequest.insert(set->id, set->access);
}
auto index = order.indexOf(set->id);
if (index >= 0) {
order.removeAt(index);
}
archived.push_back(set->id);
}
}
if (!setsToRequest.isEmpty()) {
for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
App::api()->scheduleStickerSetRequest(i.key(), i.value());
}
App::api()->requestStickerSets();
}
Local::writeArchivedStickers();
Ui::showLayer(new StickersBox(archived), KeepOtherLayers);
}
} // namespace Stickers
StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : TWidget()
, _input(set) {
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
@ -215,12 +168,13 @@ void StickerSetInner::installDone(const MTPmessages_StickerSetInstallResult &res
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
Stickers::applyArchivedResult(result.c_messages_stickerSetInstallResultArchive());
} else if (wasArchived) {
Local::writeArchivedStickers();
} else {
if (wasArchived) {
Local::writeArchivedStickers();
}
Local::writeInstalledStickers();
emit App::main()->stickersUpdated();
}
Local::writeInstalledStickers();
emit App::main()->stickersUpdated();
emit installed(_setId);
}
@ -864,59 +818,13 @@ void StickersInner::installSet(uint64 setId) {
MTP::send(MTPmessages_InstallStickerSet(Stickers::inputSetId(*it), MTP_boolFalse()), rpcDone(&StickersInner::installDone), rpcFail(&StickersInner::installFail, setId));
auto flags = it->flags;
it->flags &= ~(MTPDstickerSet::Flag::f_archived | MTPDstickerSet_ClientFlag::f_unread);
it->flags |= MTPDstickerSet::Flag::f_installed;
auto changedFlags = flags ^ it->flags;
auto &order = Global::RefStickerSetsOrder();
int insertAtIndex = 0, currentIndex = order.indexOf(setId);
if (currentIndex != insertAtIndex) {
if (currentIndex > 0) {
order.removeAt(currentIndex);
}
order.insert(insertAtIndex, setId);
}
auto custom = sets.find(Stickers::CustomSetId);
if (custom != sets.cend()) {
for_const (auto sticker, it->stickers) {
int removeIndex = custom->stickers.indexOf(sticker);
if (removeIndex >= 0) custom->stickers.removeAt(removeIndex);
}
if (custom->stickers.isEmpty()) {
sets.erase(custom);
}
}
Local::writeInstalledStickers();
if (changedFlags & MTPDstickerSet_ClientFlag::f_unread) Local::writeFeaturedStickers();
if (changedFlags & MTPDstickerSet::Flag::f_archived) {
auto index = Global::RefArchivedStickerSetsOrder().indexOf(setId);
if (index >= 0) {
Global::RefArchivedStickerSetsOrder().removeAt(index);
Local::writeArchivedStickers();
}
}
emit App::main()->stickersUpdated();
Stickers::installLocally(setId);
}
void StickersInner::installDone(const MTPmessages_StickerSetInstallResult &result) {
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
Stickers::applyArchivedResult(result.c_messages_stickerSetInstallResultArchive());
Local::writeInstalledStickers();
Local::writeArchivedStickers();
emit App::main()->stickersUpdated();
}
// TEST DATA ONLY
//MTPVector<MTPStickerSet> v = MTP_vector<MTPStickerSet>(0);
//for (auto &set : Global::RefStickerSets()) {
// if (rand() < RAND_MAX / 2) {
// set.flags |= MTPDstickerSet::Flag::f_archived;
// v._vector().v.push_back(MTP_stickerSet(MTP_flags(set.flags), MTP_long(set.id), MTP_long(set.access), MTP_string(set.title), MTP_string(set.shortName), MTP_int(set.count), MTP_int(set.hash)));
// }
//}
//Stickers::applyArchivedResult(MTP_messages_stickerSetInstallResultArchive(v).c_messages_stickerSetInstallResultArchive());
}
bool StickersInner::installFail(uint64 setId, const RPCError &error) {
@ -929,19 +837,7 @@ bool StickersInner::installFail(uint64 setId, const RPCError &error) {
return true;
}
it->flags &= ~MTPDstickerSet::Flag::f_installed;
auto &order = Global::RefStickerSetsOrder();
int currentIndex = order.indexOf(setId);
if (currentIndex >= 0) {
order.removeAt(currentIndex);
}
Local::writeInstalledStickers();
emit App::main()->stickersUpdated();
Ui::showLayer(new InformBox(lang(lng_stickers_not_found)), KeepOtherLayers);
Stickers::undoInstallLocally(setId);
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,6 @@ class Dropdown : public TWidget {
Q_OBJECT
public:
Dropdown(QWidget *parent, const style::dropdown &st = st::dropdownDef);
IconedButton *addButton(IconedButton *button);
@ -61,11 +60,9 @@ public:
}
signals:
void hiding();
public slots:
void hideStart();
void hideFinish();
@ -75,20 +72,19 @@ public slots:
void buttonStateChanged(int oldState, ButtonStateChangeSource source);
private:
void adjustButtons();
bool _ignore;
bool _ignore = false;
typedef QVector<IconedButton*> Buttons;
Buttons _buttons;
int32 _selected;
int32 _selected = -1;
const style::dropdown &_st;
int32 _width, _height;
bool _hiding;
bool _hiding = false;
anim::fvalue a_opacity;
Animation _a_appearance;
@ -103,7 +99,6 @@ class DragArea : public TWidget {
Q_OBJECT
public:
DragArea(QWidget *parent);
void paintEvent(QPaintEvent *e);
@ -133,18 +128,15 @@ public:
}
signals:
void dropped(const QMimeData *data);
public slots:
void hideStart();
void hideFinish();
void showStart();
private:
bool _hiding, _in;
anim::fvalue a_opacity;
@ -156,588 +148,3 @@ private:
QString _text, _subtext;
};
namespace InlineBots {
namespace Layout {
class ItemBase;
} // namespace Layout
class Result;
} // namespace InlineBots
namespace internal {
constexpr int InlineItemsMaxPerRow = 5;
constexpr int EmojiColorsCount = 5;
using InlineResult = InlineBots::Result;
using InlineResults = QList<InlineBots::Result*>;
using InlineItem = InlineBots::Layout::ItemBase;
struct InlineCacheEntry {
~InlineCacheEntry() {
clearResults();
}
QString nextOffset;
QString switchPmText, switchPmStartToken;
InlineResults results; // owns this results list
void clearResults();
};
class EmojiColorPicker : public TWidget {
Q_OBJECT
public:
EmojiColorPicker();
void showEmoji(uint32 code);
void paintEvent(QPaintEvent *e);
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void step_appearance(float64 ms, bool timer);
void step_selected(uint64 ms, bool timer);
void showStart();
void clearSelection(bool fast = false);
public slots:
void hideStart(bool fast = false);
signals:
void emojiSelected(EmojiPtr emoji);
void hidden();
private:
void drawVariant(Painter &p, int variant);
void updateSelected();
bool _ignoreShow;
EmojiPtr _variants[EmojiColorsCount + 1];
typedef QMap<int32, uint64> EmojiAnimations; // index - showing, -index - hiding
EmojiAnimations _emojiAnimations;
Animation _a_selected;
float64 _hovers[EmojiColorsCount + 1];
int32 _selected, _pressedSel;
QPoint _lastMousePos;
bool _hiding;
QPixmap _cache;
anim::fvalue a_opacity;
Animation _a_appearance;
QTimer _hideTimer;
BoxShadow _shadow;
};
class EmojiPanel;
class EmojiPanInner : public TWidget {
Q_OBJECT
public:
EmojiPanInner();
void setMaxHeight(int32 h);
void paintEvent(QPaintEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void leaveEvent(QEvent *e) override;
void leaveToChildEvent(QEvent *e, QWidget *child) override;
void enterFromChildEvent(QEvent *e, QWidget *child) override;
void step_selected(uint64 ms, bool timer);
void hideFinish();
void showEmojiPack(DBIEmojiTab packIndex);
void clearSelection(bool fast = false);
DBIEmojiTab currentTab(int yOffset) const;
void refreshRecent();
void setScrollTop(int top);
void fillPanels(QVector<EmojiPanel*> &panels);
void refreshPanels(QVector<EmojiPanel*> &panels);
public slots:
void updateSelected();
void onShowPicker();
void onPickerHidden();
void onColorSelected(EmojiPtr emoji);
bool checkPickerHide();
signals:
void selected(EmojiPtr emoji);
void switchToStickers();
void scrollToY(int y);
void disableScroll(bool dis);
void needRefreshPanels();
void saveConfigDelayed(int32 delay);
private:
int32 _maxHeight;
int32 countHeight();
void selectEmoji(EmojiPtr emoji);
QRect emojiRect(int tab, int sel);
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
Animations _animations;
Animation _a_selected;
int32 _top, _counts[emojiTabCount];
QVector<EmojiPtr> _emojis[emojiTabCount];
QVector<float64> _hovers[emojiTabCount];
int32 _esize;
int32 _selected, _pressedSel, _pickerSel;
QPoint _lastMousePos;
EmojiColorPicker _picker;
QTimer _showPickerTimer;
};
struct StickerIcon {
StickerIcon(uint64 setId) : setId(setId), sticker(0), pixw(0), pixh(0) {
}
StickerIcon(uint64 setId, DocumentData *sticker, int32 pixw, int32 pixh) : setId(setId), sticker(sticker), pixw(pixw), pixh(pixh) {
}
uint64 setId;
DocumentData *sticker;
int32 pixw, pixh;
};
class StickerPanInner : public TWidget {
Q_OBJECT
public:
StickerPanInner();
void setMaxHeight(int32 h);
void paintEvent(QPaintEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void leaveEvent(QEvent *e) override;
void leaveToChildEvent(QEvent *e, QWidget *child) override;
void enterFromChildEvent(QEvent *e, QWidget *child) override;
void step_selected(uint64 ms, bool timer);
void hideFinish(bool completely);
void showFinish();
void showStickerSet(uint64 setId);
void updateShowingSavedGifs();
bool showSectionIcons() const;
void clearSelection(bool fast = false);
void refreshStickers();
void refreshRecentStickers(bool resize = true);
void refreshSavedGifs();
int refreshInlineRows(UserData *bot, const InlineCacheEntry *results, bool resultsDeleted);
void refreshRecent();
void inlineBotChanged();
void hideInlineRowsPanel();
void clearInlineRowsPanel();
void fillIcons(QList<StickerIcon> &icons);
void fillPanels(QVector<EmojiPanel*> &panels);
void refreshPanels(QVector<EmojiPanel*> &panels);
void setScrollTop(int top);
void preloadImages();
uint64 currentSet(int yOffset) const;
void notify_inlineItemLayoutChanged(const InlineItem *layout);
void ui_repaintInlineItem(const InlineItem *layout);
bool ui_isInlineItemVisible(const InlineItem *layout);
bool ui_isInlineItemBeingChosen();
bool inlineResultsShown() const {
return _showingInlineItems && !_showingSavedGifs;
}
int32 countHeight(bool plain = false);
~StickerPanInner();
private slots:
void updateSelected();
void onSettings();
void onPreview();
void onUpdateInlineItems();
void onSwitchPm();
signals:
void selected(DocumentData *sticker);
void selected(PhotoData *photo);
void selected(InlineBots::Result *result, UserData *bot);
void removing(quint64 setId);
void refreshIcons();
void emptyInlineRows();
void switchToEmoji();
void scrollToY(int y);
void scrollUpdated();
void disableScroll(bool dis);
void needRefreshPanels();
void saveConfigDelayed(int32 delay);
private:
void paintInlineItems(Painter &p, const QRect &r);
void paintStickers(Painter &p, const QRect &r);
void refreshSwitchPmButton(const InlineCacheEntry *entry);
void appendSet(uint64 setId);
void selectEmoji(EmojiPtr emoji);
QRect stickerRect(int tab, int sel);
int32 _maxHeight;
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
Animations _animations;
Animation _a_selected;
int32 _top;
struct DisplayedSet {
DisplayedSet(uint64 id, MTPDstickerSet::Flags flags, const QString &title, int32 hoversSize, const StickerPack &pack = StickerPack()) : id(id), flags(flags), title(title), hovers(hoversSize, 0), pack(pack) {
}
uint64 id;
MTPDstickerSet::Flags flags;
QString title;
QVector<float64> hovers;
StickerPack pack;
};
QList<DisplayedSet> _sets;
QList<bool> _custom;
bool _showingSavedGifs, _showingInlineItems;
bool _setGifCommand;
UserData *_inlineBot;
QString _inlineBotTitle;
uint64 _lastScrolled;
QTimer _updateInlineItems;
bool _inlineWithThumb;
std_::unique_ptr<BoxButton> _switchPmButton;
QString _switchPmStartToken;
typedef QVector<InlineItem*> InlineItems;
struct InlineRow {
InlineRow() : height(0) {
}
int32 height;
InlineItems items;
};
typedef QVector<InlineRow> InlineRows;
InlineRows _inlineRows;
void clearInlineRows(bool resultsDeleted);
using GifLayouts = QMap<DocumentData*, InlineItem*>;
GifLayouts _gifLayouts;
InlineItem *layoutPrepareSavedGif(DocumentData *doc, int32 position);
using InlineLayouts = QMap<InlineResult*, InlineItem*>;
InlineLayouts _inlineLayouts;
InlineItem *layoutPrepareInlineResult(InlineResult *result, int32 position);
bool inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, InlineRow &row, int32 &sumWidth);
bool inlineRowFinalize(InlineRow &row, int32 &sumWidth, bool force = false);
InlineRow &layoutInlineRow(InlineRow &row, int32 sumWidth = 0);
void deleteUnusedGifLayouts();
void deleteUnusedInlineLayouts();
int32 validateExistingInlineRows(const InlineResults &results);
int32 _selected, _pressedSel;
QPoint _lastMousePos;
LinkButton _settings;
QTimer _previewTimer;
bool _previewShown;
};
class EmojiPanel : public TWidget {
Q_OBJECT
public:
EmojiPanel(QWidget *parent, const QString &text, uint64 setId, bool special, int32 wantedY); // Stickers::NoneSetId if in emoji
void setText(const QString &text);
void setDeleteVisible(bool isVisible);
void paintEvent(QPaintEvent *e);
void mousePressEvent(QMouseEvent *e);
int32 wantedY() const {
return _wantedY;
}
void setWantedY(int32 y) {
_wantedY = y;
}
signals:
void deleteClicked(quint64 setId);
void mousePressed();
public slots:
void onDelete();
private:
void updateText();
int32 _wantedY;
QString _text, _fullText;
uint64 _setId;
bool _special, _deleteVisible;
IconedButton *_delete;
};
class EmojiSwitchButton : public Button {
public:
EmojiSwitchButton(QWidget *parent, bool toStickers); // otherwise toEmoji
void paintEvent(QPaintEvent *e);
void updateText(const QString &inlineBotUsername = QString());
protected:
bool _toStickers;
QString _text;
int32 _textWidth;
};
} // namespace internal
class EmojiPan : public TWidget, public RPCSender {
Q_OBJECT
public:
EmojiPan(QWidget *parent);
void setMaxHeight(int32 h);
void paintEvent(QPaintEvent *e);
void moveBottom(int32 bottom, bool force = false);
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
void otherEnter();
void otherLeave();
void mousePressEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
bool event(QEvent *e);
void fastHide();
bool hiding() const {
return _hiding || _hideTimer.isActive();
}
void step_appearance(float64 ms, bool timer);
void step_slide(float64 ms, bool timer);
void step_icons(uint64 ms, bool timer);
bool eventFilter(QObject *obj, QEvent *e);
void stickersInstalled(uint64 setId);
void queryInlineBot(UserData *bot, PeerData *peer, QString query);
void clearInlineBot();
bool overlaps(const QRect &globalRect) {
if (isHidden() || !_cache.isNull()) return false;
return QRect(st::dropdownDef.padding.left(),
st::dropdownDef.padding.top(),
_width - st::dropdownDef.padding.left() - st::dropdownDef.padding.right(),
_height - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom()
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
}
void notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
bool ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout);
bool ui_isInlineItemBeingChosen();
bool inlineResultsShown() const {
return s_inner.inlineResultsShown();
}
public slots:
void refreshStickers();
void refreshSavedGifs();
void hideStart();
void hideFinish();
void showStart();
void onWndActiveChanged();
void onTabChange();
void onScrollEmoji();
void onScrollStickers();
void onSwitch();
void onRemoveSet(quint64 setId);
void onRemoveSetSure();
void onDelayedHide();
void onRefreshIcons();
void onRefreshPanels();
void onSaveConfig();
void onSaveConfigDelayed(int32 delay);
void onInlineRequest();
void onEmptyInlineRows();
signals:
void emojiSelected(EmojiPtr emoji);
void stickerSelected(DocumentData *sticker);
void photoSelected(PhotoData *photo);
void inlineResultSelected(InlineBots::Result *result, UserData *bot);
void updateStickers();
private:
void paintStickerSettingsIcon(Painter &p) const;
void validateSelectedIcon(bool animated = false);
int32 _maxHeight, _contentMaxHeight, _contentHeight, _contentHeightEmoji, _contentHeightStickers;
bool _horizontal;
void updateContentHeight();
void leaveToChildEvent(QEvent *e, QWidget *child);
void hideAnimated();
void prepareShowHideCache();
void updateSelected();
void updateIcons();
void prepareTab(int32 &left, int32 top, int32 _width, FlatRadiobutton &tab);
void updatePanelsPositions(const QVector<internal::EmojiPanel*> &panels, int32 st);
void showAll();
void hideAll();
bool _noTabUpdate;
int32 _width, _height, _bottom;
bool _hiding;
QPixmap _cache;
anim::fvalue a_opacity;
Animation _a_appearance;
QTimer _hideTimer;
BoxShadow _shadow;
FlatRadiobutton _recent, _people, _nature, _food, _activity, _travel, _objects, _symbols;
QList<internal::StickerIcon> _icons;
QVector<float64> _iconHovers;
int32 _iconOver, _iconSel, _iconDown;
bool _iconsDragging;
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
Animations _iconAnimations;
Animation _a_icons;
QPoint _iconsMousePos, _iconsMouseDown;
int32 _iconsLeft, _iconsTop;
int32 _iconsStartX, _iconsMax;
anim::ivalue _iconsX, _iconSelX;
uint64 _iconsStartAnim;
bool _stickersShown, _shownFromInlineQuery;
QPixmap _fromCache, _toCache;
anim::ivalue a_fromCoord, a_toCoord;
anim::fvalue a_fromAlpha, a_toAlpha;
Animation _a_slide;
ScrollArea e_scroll;
internal::EmojiPanInner e_inner;
QVector<internal::EmojiPanel*> e_panels;
internal::EmojiSwitchButton e_switch;
ScrollArea s_scroll;
internal::StickerPanInner s_inner;
QVector<internal::EmojiPanel*> s_panels;
internal::EmojiSwitchButton s_switch;
uint64 _removingSetId;
QTimer _saveConfigTimer;
// inline bots
typedef QMap<QString, internal::InlineCacheEntry*> InlineCache;
InlineCache _inlineCache;
QTimer _inlineRequestTimer;
void inlineBotChanged();
int32 showInlineRows(bool newResults);
bool hideOnNoInlineResults();
void recountContentMaxHeight();
bool refreshInlineRows(int32 *added = 0);
UserData *_inlineBot;
PeerData *_inlineQueryPeer = nullptr;
QString _inlineQuery, _inlineNextQuery, _inlineNextOffset;
mtpRequestId _inlineRequestId;
void inlineResultsDone(const MTPmessages_BotResults &result);
bool inlineResultsFail(const RPCError &error);
};

View File

@ -193,11 +193,12 @@ enum Flags {
namespace Stickers {
static const uint64 DefaultSetId = 0; // for backward compatibility
static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL;
static const uint64 RecentSetId = 0xFFFFFFFFFFFFFFFEULL; // for emoji/stickers panel, should not appear in Sets
static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel, should not appear in Sets
static const uint64 CloudRecentSetId = 0xFFFFFFFFFFFFFFFCULL; // for cloud-stored recent stickers
constexpr uint64 DefaultSetId = 0; // for backward compatibility
constexpr uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL;
constexpr uint64 RecentSetId = 0xFFFFFFFFFFFFFFFEULL; // for emoji/stickers panel, should not appear in Sets
constexpr uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel, should not appear in Sets
constexpr uint64 CloudRecentSetId = 0xFFFFFFFFFFFFFFFCULL; // for cloud-stored recent stickers
constexpr uint64 FeaturedSetId = 0xFFFFFFFFFFFFFFFBULL; // for emoji/stickers panel, should not appear in Sets
struct Set {
Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags)
: id(id)

View File

@ -35,8 +35,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_service_layout.h"
#include "profile/profile_members_widget.h"
#include "core/click_handler_types.h"
#include "stickers/emoji_pan.h"
#include "lang.h"
#include "application.h"
#include "dropdown.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "passcodewidget.h"
@ -3055,11 +3057,11 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(&_field, SIGNAL(linksChanged()), this, SLOT(onPreviewCheck()));
connect(App::wnd()->windowHandle(), SIGNAL(visibleChanged(bool)), this, SLOT(onWindowVisibleChanged()));
connect(&_scrollTimer, SIGNAL(timeout()), this, SLOT(onScrollTimer()));
connect(&_emojiPan, SIGNAL(emojiSelected(EmojiPtr)), &_field, SLOT(onEmojiInsert(EmojiPtr)));
connect(&_emojiPan, SIGNAL(stickerSelected(DocumentData*)), this, SLOT(onStickerSend(DocumentData*)));
connect(&_emojiPan, SIGNAL(photoSelected(PhotoData*)), this, SLOT(onPhotoSend(PhotoData*)));
connect(&_emojiPan, SIGNAL(inlineResultSelected(InlineBots::Result*,UserData*)), this, SLOT(onInlineResultSend(InlineBots::Result*,UserData*)));
connect(&_emojiPan, SIGNAL(updateStickers()), this, SLOT(updateStickers()));
connect(_emojiPan, SIGNAL(emojiSelected(EmojiPtr)), &_field, SLOT(onEmojiInsert(EmojiPtr)));
connect(_emojiPan, SIGNAL(stickerSelected(DocumentData*)), this, SLOT(onStickerSend(DocumentData*)));
connect(_emojiPan, SIGNAL(photoSelected(PhotoData*)), this, SLOT(onPhotoSend(PhotoData*)));
connect(_emojiPan, SIGNAL(inlineResultSelected(InlineBots::Result*,UserData*)), this, SLOT(onInlineResultSend(InlineBots::Result*,UserData*)));
connect(_emojiPan, SIGNAL(updateStickers()), this, SLOT(updateStickers()));
connect(&_sendActionStopTimer, SIGNAL(timeout()), this, SLOT(onCancelSendAction()));
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreviewTimeout()));
if (audioCapture()) {
@ -3130,25 +3132,25 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
_silent.hide();
_cmdStart.hide();
_attachDocument.installEventFilter(&_attachType);
_attachPhoto.installEventFilter(&_attachType);
_attachEmoji.installEventFilter(&_emojiPan);
_attachDocument.installEventFilter(_attachType);
_attachPhoto.installEventFilter(_attachType);
_attachEmoji.installEventFilter(_emojiPan);
connect(&_kbShow, SIGNAL(clicked()), this, SLOT(onKbToggle()));
connect(&_kbHide, SIGNAL(clicked()), this, SLOT(onKbToggle()));
connect(&_cmdStart, SIGNAL(clicked()), this, SLOT(onCmdStart()));
connect(_attachType.addButton(new IconedButton(this, st::dropdownAttachDocument, lang(lng_attach_file))), SIGNAL(clicked()), this, SLOT(onDocumentSelect()));
connect(_attachType.addButton(new IconedButton(this, st::dropdownAttachPhoto, lang(lng_attach_photo))), SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
_attachType.hide();
_emojiPan.hide();
_attachDragDocument.hide();
_attachDragPhoto.hide();
connect(_attachType->addButton(new IconedButton(this, st::dropdownAttachDocument, lang(lng_attach_file))), SIGNAL(clicked()), this, SLOT(onDocumentSelect()));
connect(_attachType->addButton(new IconedButton(this, st::dropdownAttachPhoto, lang(lng_attach_photo))), SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
_attachType->hide();
_emojiPan->hide();
_attachDragDocument->hide();
_attachDragPhoto->hide();
_topShadow.hide();
connect(&_attachDragDocument, SIGNAL(dropped(const QMimeData*)), this, SLOT(onDocumentDrop(const QMimeData*)));
connect(&_attachDragPhoto, SIGNAL(dropped(const QMimeData*)), this, SLOT(onPhotoDrop(const QMimeData*)));
connect(_attachDragDocument, SIGNAL(dropped(const QMimeData*)), this, SLOT(onDocumentDrop(const QMimeData*)));
connect(_attachDragPhoto, SIGNAL(dropped(const QMimeData*)), this, SLOT(onPhotoDrop(const QMimeData*)));
connect(&_updateEditTimeLeftDisplay, SIGNAL(timeout()), this, SLOT(updateField()));
@ -3157,7 +3159,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
void HistoryWidget::start() {
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
connect(App::main(), SIGNAL(savedGifsUpdated()), &_emojiPan, SLOT(refreshSavedGifs()));
connect(App::main(), SIGNAL(savedGifsUpdated()), _emojiPan, SLOT(refreshSavedGifs()));
updateRecentStickers();
if (App::main()) emit App::main()->savedGifsUpdated();
@ -3166,7 +3168,7 @@ void HistoryWidget::start() {
}
void HistoryWidget::onStickersUpdated() {
_emojiPan.refreshStickers();
_emojiPan->refreshStickers();
updateStickersByEmoji();
}
@ -3228,9 +3230,9 @@ void HistoryWidget::applyInlineBotQuery(UserData *bot, const QString &query) {
inlineBotChanged();
}
if (_inlineBot->username == cInlineGifBotUsername() && query.isEmpty()) {
_emojiPan.clearInlineBot();
_emojiPan->clearInlineBot();
} else {
_emojiPan.queryInlineBot(_inlineBot, _peer, query);
_emojiPan->queryInlineBot(_inlineBot, _peer, query);
}
if (!_fieldAutocomplete->isHidden()) {
_fieldAutocomplete->hideStart();
@ -3450,11 +3452,11 @@ void HistoryWidget::updateSendAction(History *history, SendActionType type, int3
}
void HistoryWidget::updateRecentStickers() {
_emojiPan.refreshStickers();
_emojiPan->refreshStickers();
}
void HistoryWidget::stickersInstalled(uint64 setId) {
_emojiPan.stickersInstalled(setId);
_emojiPan->stickersInstalled(setId);
}
void HistoryWidget::sendActionDone(const MTPBool &result, mtpRequestId req) {
@ -4380,11 +4382,11 @@ void HistoryWidget::updateNotifySettings() {
}
bool HistoryWidget::contentOverlapped(const QRect &globalRect) {
return (_attachDragDocument.overlaps(globalRect) ||
_attachDragPhoto.overlaps(globalRect) ||
_attachType.overlaps(globalRect) ||
return (_attachDragDocument->overlaps(globalRect) ||
_attachDragPhoto->overlaps(globalRect) ||
_attachType->overlaps(globalRect) ||
_fieldAutocomplete->overlaps(globalRect) ||
_emojiPan.overlaps(globalRect));
_emojiPan->overlaps(globalRect));
}
void HistoryWidget::updateReportSpamStatus() {
@ -4516,8 +4518,8 @@ void HistoryWidget::updateControlsVisibility() {
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachType.hide();
_emojiPan.hide();
_attachType->hide();
_emojiPan->hide();
if (_pinnedBar) {
_pinnedBar->cancel.hide();
_pinnedBar->shadow.hide();
@ -4579,8 +4581,8 @@ void HistoryWidget::updateControlsVisibility() {
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachType.hide();
_emojiPan.hide();
_attachType->hide();
_emojiPan->hide();
if (!_field.isHidden()) {
_field.hide();
resizeEvent(0);
@ -4715,8 +4717,8 @@ void HistoryWidget::updateControlsVisibility() {
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachType.hide();
_emojiPan.hide();
_attachType->hide();
_emojiPan->hide();
_kbScroll.hide();
if (!_field.isHidden()) {
_field.hide();
@ -5257,8 +5259,8 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
onDraftSave();
if (!_fieldAutocomplete->isHidden()) _fieldAutocomplete->hideStart();
if (!_attachType.isHidden()) _attachType.hideStart();
if (!_emojiPan.isHidden()) _emojiPan.hideStart();
if (!_attachType->isHidden()) _attachType->hideStart();
if (!_emojiPan->isHidden()) _emojiPan->hideStart();
if (replyTo < 0) cancelReply(lastKeyboardUsed);
if (_previewData && _previewData->pendingTill) previewCancel();
@ -5586,7 +5588,7 @@ void HistoryWidget::onPhotoSelect() {
_attachDocument.clearState();
_attachDocument.hide();
_attachPhoto.show();
_attachType.fastHide();
_attachType->fastHide();
if (cDefaultAttach() != dbidaPhoto) {
cSetDefaultAttach(dbidaPhoto);
@ -5614,7 +5616,7 @@ void HistoryWidget::onDocumentSelect() {
_attachPhoto.clearState();
_attachPhoto.hide();
_attachDocument.show();
_attachType.fastHide();
_attachType->fastHide();
if (cDefaultAttach() != dbidaDocument) {
cSetDefaultAttach(dbidaDocument);
@ -5651,14 +5653,14 @@ void HistoryWidget::dragEnterEvent(QDragEnterEvent *e) {
}
void HistoryWidget::dragLeaveEvent(QDragLeaveEvent *e) {
if (_attachDrag != DragStateNone || !_attachDragPhoto.isHidden() || !_attachDragDocument.isHidden()) {
if (_attachDrag != DragStateNone || !_attachDragPhoto->isHidden() || !_attachDragDocument->isHidden()) {
_attachDrag = DragStateNone;
updateDragAreas();
}
}
void HistoryWidget::leaveEvent(QEvent *e) {
if (_attachDrag != DragStateNone || !_attachDragPhoto.isHidden() || !_attachDragDocument.isHidden()) {
if (_attachDrag != DragStateNone || !_attachDragPhoto->isHidden() || !_attachDragDocument->isHidden()) {
_attachDrag = DragStateNone;
updateDragAreas();
}
@ -5706,7 +5708,7 @@ void HistoryWidget::mouseReleaseEvent(QMouseEvent *e) {
_replyForwardPressed = false;
update(0, _field.y() - st::sendPadding - st::replyHeight, width(), st::replyHeight);
}
if (_attachDrag != DragStateNone || !_attachDragPhoto.isHidden() || !_attachDragDocument.isHidden()) {
if (_attachDrag != DragStateNone || !_attachDragPhoto->isHidden() || !_attachDragDocument->isHidden()) {
_attachDrag = DragStateNone;
updateDragAreas();
}
@ -5961,24 +5963,24 @@ void HistoryWidget::updateDragAreas() {
_field.setAcceptDrops(!_attachDrag);
switch (_attachDrag) {
case DragStateNone:
_attachDragDocument.otherLeave();
_attachDragPhoto.otherLeave();
_attachDragDocument->otherLeave();
_attachDragPhoto->otherLeave();
break;
case DragStateFiles:
_attachDragDocument.otherEnter();
_attachDragDocument.setText(lang(lng_drag_files_here), lang(lng_drag_to_send_files));
_attachDragPhoto.fastHide();
_attachDragDocument->otherEnter();
_attachDragDocument->setText(lang(lng_drag_files_here), lang(lng_drag_to_send_files));
_attachDragPhoto->fastHide();
break;
case DragStatePhotoFiles:
_attachDragDocument.otherEnter();
_attachDragDocument.setText(lang(lng_drag_images_here), lang(lng_drag_to_send_no_compression));
_attachDragPhoto.otherEnter();
_attachDragPhoto.setText(lang(lng_drag_photos_here), lang(lng_drag_to_send_quick));
_attachDragDocument->otherEnter();
_attachDragDocument->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_no_compression));
_attachDragPhoto->otherEnter();
_attachDragPhoto->setText(lang(lng_drag_photos_here), lang(lng_drag_to_send_quick));
break;
case DragStateImage:
_attachDragDocument.fastHide();
_attachDragPhoto.otherEnter();
_attachDragPhoto.setText(lang(lng_drag_images_here), lang(lng_drag_to_send_quick));
_attachDragDocument->fastHide();
_attachDragPhoto->otherEnter();
_attachDragPhoto->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_quick));
break;
};
resizeEvent(0);
@ -6460,8 +6462,8 @@ void HistoryWidget::moveFieldControls() {
right = w;
_fieldBarCancel.move(right - _fieldBarCancel.width(), _field.y() - st::sendPadding - _fieldBarCancel.height());
_attachType.move(0, _attachDocument.y() - _attachType.height());
_emojiPan.moveBottom(_attachEmoji.y());
_attachType->move(0, _attachDocument.y() - _attachType->height());
_emojiPan->moveBottom(_attachEmoji.y());
_botStart.setGeometry(0, bottom - _botStart.height(), w, _botStart.height());
_unblock.setGeometry(0, bottom - _unblock.height(), w, _unblock.height());
@ -6491,7 +6493,7 @@ void HistoryWidget::clearInlineBot() {
inlineBotChanged();
_field.finishPlaceholder();
}
_emojiPan.clearInlineBot();
_emojiPan->clearInlineBot();
onCheckFieldAutocomplete();
}
@ -6958,15 +6960,15 @@ void HistoryWidget::onUpdateHistoryItems() {
}
void HistoryWidget::ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout) {
_emojiPan.ui_repaintInlineItem(layout);
_emojiPan->ui_repaintInlineItem(layout);
}
bool HistoryWidget::ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout) {
return _emojiPan.ui_isInlineItemVisible(layout);
return _emojiPan->ui_isInlineItemVisible(layout);
}
bool HistoryWidget::ui_isInlineItemBeingChosen() {
return _emojiPan.ui_isInlineItemBeingChosen();
return _emojiPan->ui_isInlineItemBeingChosen();
}
PeerData *HistoryWidget::ui_getPeerForMouseAction() {
@ -6980,7 +6982,7 @@ void HistoryWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
}
void HistoryWidget::notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout) {
_emojiPan.notify_inlineItemLayoutChanged(layout);
_emojiPan->notify_inlineItemLayoutChanged(layout);
}
void HistoryWidget::notify_handlePendingHistoryUpdate() {
@ -7015,25 +7017,25 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
_historyToEnd->moveToRight(st::historyToDownPosition.x(), _scroll.y() + _scroll.height() - _historyToEnd->height() - st::historyToDownPosition.y());
_emojiPan.setMaxHeight(height() - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom() - _attachEmoji.height());
_emojiPan->setMaxHeight(height() - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom() - _attachEmoji.height());
if (_membersDropdown) {
_membersDropdown->setMaxHeight(countMembersDropdownHeightMax());
}
switch (_attachDrag) {
case DragStateFiles:
_attachDragDocument.resize(width() - st::dragMargin.left() - st::dragMargin.right(), height() - st::dragMargin.top() - st::dragMargin.bottom());
_attachDragDocument.move(st::dragMargin.left(), st::dragMargin.top());
_attachDragDocument->resize(width() - st::dragMargin.left() - st::dragMargin.right(), height() - st::dragMargin.top() - st::dragMargin.bottom());
_attachDragDocument->move(st::dragMargin.left(), st::dragMargin.top());
break;
case DragStatePhotoFiles:
_attachDragDocument.resize(width() - st::dragMargin.left() - st::dragMargin.right(), (height() - st::dragMargin.top() - st::dragMargin.bottom()) / 2);
_attachDragDocument.move(st::dragMargin.left(), st::dragMargin.top());
_attachDragPhoto.resize(_attachDragDocument.width(), _attachDragDocument.height());
_attachDragPhoto.move(st::dragMargin.left(), height() - _attachDragPhoto.height() - st::dragMargin.bottom());
_attachDragDocument->resize(width() - st::dragMargin.left() - st::dragMargin.right(), (height() - st::dragMargin.top() - st::dragMargin.bottom()) / 2);
_attachDragDocument->move(st::dragMargin.left(), st::dragMargin.top());
_attachDragPhoto->resize(_attachDragDocument->width(), _attachDragDocument->height());
_attachDragPhoto->move(st::dragMargin.left(), height() - _attachDragPhoto->height() - st::dragMargin.bottom());
break;
case DragStateImage:
_attachDragPhoto.resize(width() - st::dragMargin.left() - st::dragMargin.right(), height() - st::dragMargin.top() - st::dragMargin.bottom());
_attachDragPhoto.move(st::dragMargin.left(), st::dragMargin.top());
_attachDragPhoto->resize(width() - st::dragMargin.left() - st::dragMargin.right(), height() - st::dragMargin.top() - st::dragMargin.bottom());
_attachDragPhoto->move(st::dragMargin.left(), st::dragMargin.top());
break;
}
@ -7530,8 +7532,8 @@ void HistoryWidget::onInlineResultSend(InlineBots::Result *result, UserData *bot
}
if (!_fieldAutocomplete->isHidden()) _fieldAutocomplete->hideStart();
if (!_attachType.isHidden()) _attachType.hideStart();
if (!_emojiPan.isHidden()) _emojiPan.hideStart();
if (!_attachType->isHidden()) _attachType->hideStart();
if (!_emojiPan->isHidden()) _emojiPan->hideStart();
_field.setFocus();
}
@ -7600,10 +7602,10 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() {
if (_membersDropdown) {
_membersDropdown->raise();
}
_attachType.raise();
_emojiPan.raise();
_attachDragDocument.raise();
_attachDragPhoto.raise();
_attachType->raise();
_emojiPan->raise();
_attachDragDocument->raise();
_attachDragPhoto->raise();
updatePinnedBar();
result = true;
@ -7701,8 +7703,8 @@ void HistoryWidget::sendExistingDocument(DocumentData *doc, const QString &capti
}
if (!_fieldAutocomplete->isHidden()) _fieldAutocomplete->hideStart();
if (!_attachType.isHidden()) _attachType.hideStart();
if (!_emojiPan.isHidden()) _emojiPan.hideStart();
if (!_attachType->isHidden()) _attachType->hideStart();
if (!_emojiPan->isHidden()) _emojiPan->hideStart();
_field.setFocus();
}
@ -7747,8 +7749,8 @@ void HistoryWidget::sendExistingPhoto(PhotoData *photo, const QString &caption)
App::historyRegRandom(randomId, newId);
if (!_fieldAutocomplete->isHidden()) _fieldAutocomplete->hideStart();
if (!_attachType.isHidden()) _attachType.hideStart();
if (!_emojiPan.isHidden()) _emojiPan.hideStart();
if (!_attachType->isHidden()) _attachType->hideStart();
if (!_emojiPan->isHidden()) _emojiPan->hideStart();
_field.setFocus();
}

View File

@ -22,7 +22,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localimageloader.h"
#include "ui/boxshadow.h"
#include "dropdown.h"
#include "history/history_common.h"
#include "history/field_autocomplete.h"
#include "window/section_widget.h"
@ -39,6 +38,10 @@ class HistoryDownButton;
class InnerDropdown;
} // namespace Ui
class Dropdown;
class DragArea;
class EmojiPan;
class HistoryWidget;
class HistoryInner : public TWidget, public AbstractTooltipShower {
Q_OBJECT
@ -1124,10 +1127,10 @@ private:
ChildWidget<Ui::InnerDropdown> _membersDropdown = { nullptr };
QTimer _membersDropdownShowTimer;
Dropdown _attachType;
EmojiPan _emojiPan;
ChildWidget<Dropdown> _attachType;
ChildWidget<EmojiPan> _emojiPan;
DragState _attachDrag = DragStateNone;
DragArea _attachDragDocument, _attachDragPhoto;
ChildWidget<DragArea> _attachDragDocument, _attachDragPhoto;
int32 _selCount; // < 0 - text selected, focus list, not _field

View File

@ -28,6 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "window/section_widget.h"
#include "window/top_bar_widget.h"
#include "data/data_drafts.h"
#include "dropdown.h"
#include "observer_peer.h"
#include "apiwrap.h"
#include "dialogswidget.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,657 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/twidget.h"
#include "ui/boxshadow.h"
namespace InlineBots {
namespace Layout {
class ItemBase;
} // namespace Layout
class Result;
} // namespace InlineBots
namespace internal {
constexpr int InlineItemsMaxPerRow = 5;
constexpr int EmojiColorsCount = 5;
using InlineResult = InlineBots::Result;
using InlineResults = QList<InlineBots::Result*>;
using InlineItem = InlineBots::Layout::ItemBase;
struct InlineCacheEntry {
~InlineCacheEntry() {
clearResults();
}
QString nextOffset;
QString switchPmText, switchPmStartToken;
InlineResults results; // owns this results list
void clearResults();
};
class EmojiColorPicker : public TWidget {
Q_OBJECT
public:
EmojiColorPicker();
void showEmoji(uint32 code);
void paintEvent(QPaintEvent *e);
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void step_appearance(float64 ms, bool timer);
void step_selected(uint64 ms, bool timer);
void showStart();
void clearSelection(bool fast = false);
public slots:
void hideStart(bool fast = false);
signals:
void emojiSelected(EmojiPtr emoji);
void hidden();
private:
void drawVariant(Painter &p, int variant);
void updateSelected();
bool _ignoreShow = false;
EmojiPtr _variants[EmojiColorsCount + 1];
typedef QMap<int32, uint64> EmojiAnimations; // index - showing, -index - hiding
EmojiAnimations _emojiAnimations;
Animation _a_selected;
float64 _hovers[EmojiColorsCount + 1];
int _selected = -1;
int _pressedSel = -1;
QPoint _lastMousePos;
bool _hiding = false;
QPixmap _cache;
anim::fvalue a_opacity;
Animation _a_appearance;
QTimer _hideTimer;
BoxShadow _shadow;
};
class EmojiPanel;
class EmojiPanInner : public TWidget {
Q_OBJECT
public:
EmojiPanInner();
void setMaxHeight(int32 h);
void paintEvent(QPaintEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void leaveEvent(QEvent *e) override;
void leaveToChildEvent(QEvent *e, QWidget *child) override;
void enterFromChildEvent(QEvent *e, QWidget *child) override;
void step_selected(uint64 ms, bool timer);
void hideFinish();
void showEmojiPack(DBIEmojiTab packIndex);
void clearSelection(bool fast = false);
DBIEmojiTab currentTab(int yOffset) const;
void refreshRecent();
void setScrollTop(int top);
void fillPanels(QVector<EmojiPanel*> &panels);
void refreshPanels(QVector<EmojiPanel*> &panels);
public slots:
void updateSelected();
void onShowPicker();
void onPickerHidden();
void onColorSelected(EmojiPtr emoji);
bool checkPickerHide();
signals:
void selected(EmojiPtr emoji);
void switchToStickers();
void scrollToY(int y);
void disableScroll(bool dis);
void needRefreshPanels();
void saveConfigDelayed(int32 delay);
private:
int32 _maxHeight;
int countHeight();
void selectEmoji(EmojiPtr emoji);
QRect emojiRect(int tab, int sel);
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
Animations _animations;
Animation _a_selected;
int _top = 0, _counts[emojiTabCount];
QVector<EmojiPtr> _emojis[emojiTabCount];
QVector<float64> _hovers[emojiTabCount];
int32 _esize;
int _selected = -1;
int _pressedSel = -1;
int _pickerSel = -1;
QPoint _lastMousePos;
EmojiColorPicker _picker;
QTimer _showPickerTimer;
};
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;
DocumentData *sticker = nullptr;
int pixw = 0;
int pixh = 0;
};
class StickerPanInner : public TWidget {
Q_OBJECT
public:
StickerPanInner();
void setMaxHeight(int32 h);
void paintEvent(QPaintEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void leaveEvent(QEvent *e) override;
void leaveToChildEvent(QEvent *e, QWidget *child) override;
void enterFromChildEvent(QEvent *e, QWidget *child) override;
void step_selected(uint64 ms, bool timer);
void hideFinish(bool completely);
void showFinish();
void showStickerSet(uint64 setId);
void updateShowingSavedGifs();
bool showSectionIcons() const;
void clearSelection(bool fast = false);
void refreshStickers();
void refreshRecentStickers(bool resize = true);
void refreshSavedGifs();
int refreshInlineRows(UserData *bot, const InlineCacheEntry *results, bool resultsDeleted);
void refreshRecent();
void inlineBotChanged();
void hideInlineRowsPanel();
void clearInlineRowsPanel();
void fillIcons(QList<StickerIcon> &icons);
void fillPanels(QVector<EmojiPanel*> &panels);
void refreshPanels(QVector<EmojiPanel*> &panels);
void setScrollTop(int top);
void preloadImages();
uint64 currentSet(int yOffset) const;
void notify_inlineItemLayoutChanged(const InlineItem *layout);
void ui_repaintInlineItem(const InlineItem *layout);
bool ui_isInlineItemVisible(const InlineItem *layout);
bool ui_isInlineItemBeingChosen();
bool inlineResultsShown() const {
return (_section == Section::Inlines);
}
int countHeight(bool plain = false);
~StickerPanInner();
private slots:
void updateSelected();
void onSettings();
void onPreview();
void onUpdateInlineItems();
void onSwitchPm();
signals:
void selected(DocumentData *sticker);
void selected(PhotoData *photo);
void selected(InlineBots::Result *result, UserData *bot);
void displaySet(quint64 setId);
void installSet(quint64 setId);
void removeSet(quint64 setId);
void refreshIcons();
void emptyInlineRows();
void switchToEmoji();
void scrollToY(int y);
void scrollUpdated();
void disableScroll(bool dis);
void needRefreshPanels();
void saveConfigDelayed(int32 delay);
private:
struct Set {
Set(uint64 id, MTPDstickerSet::Flags flags, const QString &title, int32 hoversSize, const StickerPack &pack = StickerPack()) : id(id), flags(flags), title(title), hovers(hoversSize, 0), pack(pack) {
}
uint64 id;
MTPDstickerSet::Flags flags;
QString title;
QVector<float64> hovers;
StickerPack pack;
};
using Sets = QList<Set>;
Sets &shownSets() {
return (_section == Section::Featured) ? _featuredSets : _mySets;
}
const Sets &shownSets() const {
return const_cast<StickerPanInner*>(this)->shownSets();
}
int featuredRowHeight() const;
bool showingInlineItems() const { // Gifs or Inline results
return (_section == Section::Inlines) || (_section == Section::Gifs);
}
void paintInlineItems(Painter &p, const QRect &r);
void paintStickers(Painter &p, const QRect &r);
void paintSticker(Painter &p, Set &set, int y, int index);
bool featuredHasAddButton(int index) const;
int featuredContentWidth() const;
QRect featuredAddRect(int y) const;
void refreshSwitchPmButton(const InlineCacheEntry *entry);
void appendSet(Sets &to, uint64 setId);
void selectEmoji(EmojiPtr emoji);
QRect stickerRect(int tab, int sel);
int32 _maxHeight;
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
Animations _animations;
Animation _a_selected;
int _top = 0;
Sets _mySets;
Sets _featuredSets;
QList<bool> _custom;
enum class Section {
Inlines,
Gifs,
Featured,
Stickers,
};
Section _section = Section::Stickers;
bool _setGifCommand = false;
UserData *_inlineBot;
QString _inlineBotTitle;
uint64 _lastScrolled = 0;
QTimer _updateInlineItems;
bool _inlineWithThumb = false;
std_::unique_ptr<BoxButton> _switchPmButton;
QString _switchPmStartToken;
typedef QVector<InlineItem*> InlineItems;
struct InlineRow {
InlineRow() : height(0) {
}
int32 height;
InlineItems items;
};
typedef QVector<InlineRow> InlineRows;
InlineRows _inlineRows;
void clearInlineRows(bool resultsDeleted);
using GifLayouts = QMap<DocumentData*, InlineItem*>;
GifLayouts _gifLayouts;
InlineItem *layoutPrepareSavedGif(DocumentData *doc, int32 position);
using InlineLayouts = QMap<InlineResult*, InlineItem*>;
InlineLayouts _inlineLayouts;
InlineItem *layoutPrepareInlineResult(InlineResult *result, int32 position);
bool inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, InlineRow &row, int32 &sumWidth);
bool inlineRowFinalize(InlineRow &row, int32 &sumWidth, bool force = false);
InlineRow &layoutInlineRow(InlineRow &row, int32 sumWidth = 0);
void deleteUnusedGifLayouts();
void deleteUnusedInlineLayouts();
int validateExistingInlineRows(const InlineResults &results);
void selectInlineResult(int row, int column);
void removeRecentSticker(int tab, int index);
int _selected = -1;
int _pressed = -1;
int _selectedFeaturedSet = -1;
int _pressedFeaturedSet = -1;
int _selectedFeaturedSetAdd = -1;
int _pressedFeaturedSetAdd = -1;
QPoint _lastMousePos;
QString _addText;
int _addWidth;
LinkButton _settings;
QTimer _previewTimer;
bool _previewShown = false;
};
class EmojiPanel : public TWidget {
Q_OBJECT
public:
EmojiPanel(QWidget *parent, const QString &text, uint64 setId, bool special, int32 wantedY); // Stickers::NoneSetId if in emoji
void setText(const QString &text);
void setDeleteVisible(bool isVisible);
void paintEvent(QPaintEvent *e);
void mousePressEvent(QMouseEvent *e);
int32 wantedY() const {
return _wantedY;
}
void setWantedY(int32 y) {
_wantedY = y;
}
signals:
void deleteClicked(quint64 setId);
void mousePressed();
public slots:
void onDelete();
private:
void updateText();
int32 _wantedY;
QString _text, _fullText;
uint64 _setId;
bool _special, _deleteVisible;
IconedButton *_delete;
};
class EmojiSwitchButton : public Button {
public:
EmojiSwitchButton(QWidget *parent, bool toStickers); // otherwise toEmoji
void paintEvent(QPaintEvent *e);
void updateText(const QString &inlineBotUsername = QString());
protected:
bool _toStickers;
QString _text;
int32 _textWidth;
};
} // namespace internal
class EmojiPan : public TWidget, public RPCSender {
Q_OBJECT
public:
EmojiPan(QWidget *parent);
void setMaxHeight(int32 h);
void paintEvent(QPaintEvent *e);
void moveBottom(int32 bottom, bool force = false);
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
void otherEnter();
void otherLeave();
void mousePressEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
bool event(QEvent *e);
void fastHide();
bool hiding() const {
return _hiding || _hideTimer.isActive();
}
void step_appearance(float64 ms, bool timer);
void step_slide(float64 ms, bool timer);
void step_icons(uint64 ms, bool timer);
bool eventFilter(QObject *obj, QEvent *e);
void stickersInstalled(uint64 setId);
void queryInlineBot(UserData *bot, PeerData *peer, QString query);
void clearInlineBot();
bool overlaps(const QRect &globalRect) {
if (isHidden() || !_cache.isNull()) return false;
return QRect(st::dropdownDef.padding.left(),
st::dropdownDef.padding.top(),
_width - st::dropdownDef.padding.left() - st::dropdownDef.padding.right(),
_height - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom()
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
}
void notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
bool ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout);
bool ui_isInlineItemBeingChosen();
bool inlineResultsShown() const {
return s_inner.inlineResultsShown();
}
public slots:
void refreshStickers();
void refreshSavedGifs();
void hideStart();
void hideFinish();
void showStart();
void onWndActiveChanged();
void onTabChange();
void onScrollEmoji();
void onScrollStickers();
void onSwitch();
void onDisplaySet(quint64 setId);
void onInstallSet(quint64 setId);
void onRemoveSet(quint64 setId);
void onRemoveSetSure();
void onDelayedHide();
void onRefreshIcons();
void onRefreshPanels();
void onSaveConfig();
void onSaveConfigDelayed(int32 delay);
void onInlineRequest();
void onEmptyInlineRows();
signals:
void emojiSelected(EmojiPtr emoji);
void stickerSelected(DocumentData *sticker);
void photoSelected(PhotoData *photo);
void inlineResultSelected(InlineBots::Result *result, UserData *bot);
void updateStickers();
private:
bool preventAutoHide() const;
void installSetDone(const MTPmessages_StickerSetInstallResult &result);
bool installSetFail(uint64 setId, const RPCError &error);
void paintStickerSettingsIcon(Painter &p) const;
void paintFeaturedStickerSetsBadge(Painter &p, int iconLeft) const;
void validateSelectedIcon(bool animated = false);
void updateContentHeight();
void leaveToChildEvent(QEvent *e, QWidget *child);
void hideAnimated();
void prepareShowHideCache();
void updateSelected();
void updateIcons();
void prepareTab(int32 &left, int32 top, int32 _width, FlatRadiobutton &tab);
void updatePanelsPositions(const QVector<internal::EmojiPanel*> &panels, int32 st);
void showAll();
void hideAll();
int32 _maxHeight, _contentMaxHeight, _contentHeight, _contentHeightEmoji, _contentHeightStickers;
bool _horizontal = false;
bool _noTabUpdate = false;
int32 _width, _height, _bottom;
bool _hiding = false;
QPixmap _cache;
anim::fvalue a_opacity = { 0. };
Animation _a_appearance;
QTimer _hideTimer;
BoxShadow _shadow;
FlatRadiobutton _recent, _people, _nature, _food, _activity, _travel, _objects, _symbols;
QList<internal::StickerIcon> _icons;
QVector<float64> _iconHovers;
int _iconOver = -1;
int _iconSel = 0;
int _iconDown = -1;
bool _iconsDragging = false;
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
Animations _iconAnimations;
Animation _a_icons;
QPoint _iconsMousePos, _iconsMouseDown;
int _iconsLeft = 0;
int _iconsTop = 0;
int _iconsStartX = 0;
int _iconsMax = 0;
anim::ivalue _iconsX = { 0, 0 };
anim::ivalue _iconSelX = { 0, 0 };
uint64 _iconsStartAnim = 0;
bool _stickersShown = false;
bool _shownFromInlineQuery = false;
QPixmap _fromCache, _toCache;
anim::ivalue a_fromCoord, a_toCoord;
anim::fvalue a_fromAlpha, a_toAlpha;
Animation _a_slide;
ScrollArea e_scroll;
internal::EmojiPanInner e_inner;
QVector<internal::EmojiPanel*> e_panels;
internal::EmojiSwitchButton e_switch;
ScrollArea s_scroll;
internal::StickerPanInner s_inner;
QVector<internal::EmojiPanel*> s_panels;
internal::EmojiSwitchButton s_switch;
uint64 _displayingSetId = 0;
uint64 _removingSetId = 0;
QTimer _saveConfigTimer;
// inline bots
typedef QMap<QString, internal::InlineCacheEntry*> InlineCache;
InlineCache _inlineCache;
QTimer _inlineRequestTimer;
void inlineBotChanged();
int32 showInlineRows(bool newResults);
bool hideOnNoInlineResults();
void recountContentMaxHeight();
bool refreshInlineRows(int32 *added = 0);
UserData *_inlineBot = nullptr;
PeerData *_inlineQueryPeer = nullptr;
QString _inlineQuery, _inlineNextQuery, _inlineNextOffset;
mtpRequestId _inlineRequestId = 0;
void inlineResultsDone(const MTPmessages_BotResults &result);
bool inlineResultsFail(const RPCError &error);
};

View File

@ -0,0 +1,143 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "lang.h"
#include "boxes/stickersetbox.h"
#include "boxes/confirmbox.h"
#include "apiwrap.h"
#include "localstorage.h"
#include "mainwidget.h"
namespace Stickers {
void applyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
auto &v = d.vsets.c_vector().v;
auto &order = Global::RefStickerSetsOrder();
Stickers::Order archived;
archived.reserve(v.size());
QMap<uint64, uint64> setsToRequest;
for_const (auto &stickerSet, v) {
const MTPDstickerSet *setData = nullptr;
switch (stickerSet.type()) {
case mtpc_stickerSetCovered: {
auto &d = stickerSet.c_stickerSetCovered();
if (d.vset.type() == mtpc_stickerSet) {
setData = &d.vset.c_stickerSet();
}
} break;
case mtpc_stickerSetMultiCovered: {
auto &d = stickerSet.c_stickerSetMultiCovered();
if (d.vset.type() == mtpc_stickerSet) {
setData = &d.vset.c_stickerSet();
}
} break;
}
if (setData) {
auto set = Stickers::feedSet(*setData);
if (set->stickers.isEmpty()) {
setsToRequest.insert(set->id, set->access);
}
auto index = order.indexOf(set->id);
if (index >= 0) {
order.removeAt(index);
}
archived.push_back(set->id);
}
}
if (!setsToRequest.isEmpty()) {
for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
App::api()->scheduleStickerSetRequest(i.key(), i.value());
}
App::api()->requestStickerSets();
}
Local::writeInstalledStickers();
Local::writeArchivedStickers();
Ui::showLayer(new StickersBox(archived), KeepOtherLayers);
emit App::main()->stickersUpdated();
}
void installLocally(uint64 setId) {
auto &sets = Global::RefStickerSets();
auto it = sets.find(setId);
if (it == sets.end()) {
return;
}
auto flags = it->flags;
it->flags &= ~(MTPDstickerSet::Flag::f_archived | MTPDstickerSet_ClientFlag::f_unread);
it->flags |= MTPDstickerSet::Flag::f_installed;
auto changedFlags = flags ^ it->flags;
auto &order = Global::RefStickerSetsOrder();
int insertAtIndex = 0, currentIndex = order.indexOf(setId);
if (currentIndex != insertAtIndex) {
if (currentIndex > 0) {
order.removeAt(currentIndex);
}
order.insert(insertAtIndex, setId);
}
auto custom = sets.find(Stickers::CustomSetId);
if (custom != sets.cend()) {
for_const (auto sticker, it->stickers) {
int removeIndex = custom->stickers.indexOf(sticker);
if (removeIndex >= 0) custom->stickers.removeAt(removeIndex);
}
if (custom->stickers.isEmpty()) {
sets.erase(custom);
}
}
Local::writeInstalledStickers();
if (changedFlags & MTPDstickerSet_ClientFlag::f_unread) Local::writeFeaturedStickers();
if (changedFlags & MTPDstickerSet::Flag::f_archived) {
auto index = Global::RefArchivedStickerSetsOrder().indexOf(setId);
if (index >= 0) {
Global::RefArchivedStickerSetsOrder().removeAt(index);
Local::writeArchivedStickers();
}
}
emit App::main()->stickersUpdated();
}
void undoInstallLocally(uint64 setId) {
auto &sets = Global::RefStickerSets();
auto it = sets.find(setId);
if (it == sets.end()) {
return;
}
it->flags &= ~MTPDstickerSet::Flag::f_installed;
auto &order = Global::RefStickerSetsOrder();
int currentIndex = order.indexOf(setId);
if (currentIndex >= 0) {
order.removeAt(currentIndex);
}
Local::writeInstalledStickers();
emit App::main()->stickersUpdated();
Ui::showLayer(new InformBox(lang(lng_stickers_not_found)), KeepOtherLayers);
}
} // namespace Stickers

View File

@ -0,0 +1,29 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
namespace Stickers {
void applyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d);
void installLocally(uint64 setId);
void undoInstallLocally(uint64 setId);
} // namespace Stickers

View File

@ -0,0 +1,39 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
using "basic.style";
featuredStickersHeader: 45px;
featuredStickersSkip: 15px;
featuredStickersHeaderFont: semiboldFont;
featuredStickersHeaderFg: windowTextFg;
featuredStickersHeaderTop: 0px;
featuredStickersSubheaderFont: normalFont;
featuredStickersSubheaderFg: #777;
featuredStickersSubheaderTop: 20px;
featuredStickersAddTop: 3px;
featuredStickersAdd: RoundButton(defaultActiveButton) {
width: -17px;
height: 26px;
textTop: 4px;
downTextTop: 5px;
}

View File

@ -38,6 +38,7 @@
'<(src_loc)/overview/overview.style',
'<(src_loc)/profile/profile.style',
'<(src_loc)/settings/settings.style',
'<(src_loc)/stickers/stickers.style',
'<(src_loc)/ui/widgets/widgets.style',
],
'langpacks': [
@ -377,6 +378,10 @@
'<(src_loc)/settings/settings_scale_widget.h',
'<(src_loc)/settings/settings_widget.cpp',
'<(src_loc)/settings/settings_widget.h',
'<(src_loc)/stickers/emoji_pan.cpp',
'<(src_loc)/stickers/emoji_pan.h',
'<(src_loc)/stickers/stickers.cpp',
'<(src_loc)/stickers/stickers.h',
'<(src_loc)/ui/buttons/history_down_button.cpp',
'<(src_loc)/ui/buttons/history_down_button.h',
'<(src_loc)/ui/buttons/icon_button.cpp',

View File

@ -39,11 +39,6 @@
'lib_exif',
'OpenAL32',
'common',
'libavformat/libavformat.a',
'libavcodec/libavcodec.a',
'libavutil/libavutil.a',
'libswresample/libswresample.a',
'libswscale/libswscale.a',
'opus',
'celt',
'silk_common',
@ -52,6 +47,17 @@
'lib/exception_handler',
'lib/crash_generation_client',
],
'msvs_settings': {
'VCLinkerTool': {
'AdditionalOptions': [
'libavformat/libavformat.a',
'libavcodec/libavcodec.a',
'libavutil/libavutil.a',
'libswresample/libswresample.a',
'libswscale/libswscale.a',
],
},
},
'configurations': {
'Debug': {
'include_dirs': [