added stickers preview

This commit is contained in:
John Preston 2015-12-07 16:05:00 +03:00
parent 6b565acbd6
commit e312adb786
17 changed files with 448 additions and 129 deletions

View File

@ -1940,6 +1940,9 @@ stickerIconSelColor: #58b2ed;
stickerIconLeft: sprite(342px, 72px, 40px, 1px);
stickerIconRight: sprite(342px, 73px, 40px, 1px);
stickerIconMove: 400;
stickerPreviewDuration: 150;
stickerPreviewBg: #FFFFFFB0;
stickerPreviewMin: 0.1;
verifiedCheckProfile: sprite(285px, 235px, 18px, 18px);
verifiedCheckProfilePos: point(7px, 6px);

View File

@ -2805,79 +2805,4 @@ namespace App {
WallPapers gServerBackgrounds;
void sendBotCommand(const QString &cmd, MsgId replyTo) {
if (MainWidget *m = main()) m->sendBotCommand(cmd, replyTo);
}
void insertBotCommand(const QString &cmd) {
if (MainWidget *m = main()) m->insertBotCommand(cmd);
}
void searchByHashtag(const QString &tag, PeerData *inPeer) {
if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel()) ? inPeer : 0);
}
void openPeerByName(const QString &username, bool toProfile, const QString &startToken) {
if (MainWidget *m = main()) m->openPeerByName(username, toProfile, startToken);
}
void joinGroupByHash(const QString &hash) {
if (MainWidget *m = main()) m->joinGroupByHash(hash);
}
void stickersBox(const QString &name) {
if (MainWidget *m = main()) m->stickersBox(MTP_inputStickerSetShortName(MTP_string(name)));
}
void openLocalUrl(const QString &url) {
if (MainWidget *m = main()) m->openLocalUrl(url);
}
bool forward(const PeerId &peer, ForwardWhatMessages what) {
if (MainWidget *m = main()) return m->onForward(peer, what);
return false;
}
void removeDialog(History *history) {
if (MainWidget *m = main()) m->removeDialog(history);
}
void showSettings() {
if (Window *win = wnd()) win->showSettings();
}
void showLayer(LayeredWidget *w, bool forceFast) {
if (Window *win = wnd()) win->showLayer(w, forceFast);
}
void replaceLayer(LayeredWidget *w) {
if (Window *win = wnd()) win->replaceLayer(w);
}
void showLayerLast(LayeredWidget *w) {
if (Window *win = wnd()) win->showLayerLast(w);
}
}
namespace Notify {
void userIsBotChanged(UserData *user) {
if (MainWidget *m = App::main()) {
m->notifyUserIsBotChanged(user);
}
}
void botCommandsChanged(UserData *user) {
if (MainWidget *m = App::main()) {
m->notifyBotCommandsChanged(user);
}
}
void migrateUpdated(PeerData *peer) {
if (MainWidget *m = App::main()) {
m->notifyMigrateUpdated(peer);
}
}
}

View File

@ -80,13 +80,6 @@ enum RoundCorners {
RoundCornersCount
};
enum ForwardWhatMessages {
ForwardSelectedMessages,
ForwardContextMessage,
ForwardPressedMessage,
ForwardPressedLinkMessage
};
class LayeredWidget;
namespace App {
@ -233,7 +226,7 @@ namespace App {
bool quiting();
void setQuiting();
QImage readImage(QByteArray data, QByteArray *format = 0, bool opaque = true, bool *animated = 0);
QImage readImage(QByteArray data, QByteArray *format = 0, bool opaque = true, bool *animated = 0);
QImage readImage(const QString &file, QByteArray *format = 0, bool opaque = true, bool *animated = 0, QByteArray *content = 0);
void regVideoItem(VideoData *data, HistoryItem *item);
@ -300,28 +293,6 @@ namespace App {
typedef QList<WallPaper> WallPapers;
DeclareSetting(WallPapers, ServerBackgrounds);
void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
void insertBotCommand(const QString &cmd);
void searchByHashtag(const QString &tag, PeerData *inPeer);
void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
void joinGroupByHash(const QString &hash);
void stickersBox(const QString &name);
void openLocalUrl(const QString &url);
bool forward(const PeerId &peer, ForwardWhatMessages what);
void removeDialog(History *history);
void showSettings();
void showLayer(LayeredWidget *w, bool forceFast = false);
void replaceLayer(LayeredWidget *w);
void showLayerLast(LayeredWidget *w);
};
namespace Notify {
void userIsBotChanged(UserData *user);
void botCommandsChanged(UserData *user);
void migrateUpdated(PeerData *peer);
};
inline int32 stickersCountHash(bool checkOfficial = false) {
@ -344,3 +315,5 @@ inline int32 stickersCountHash(bool checkOfficial = false) {
}
return (!checkOfficial || (!foundBad && foundOfficial)) ? int32(acc & 0x7FFFFFFF) : 0;
}
#include "facades.h"

View File

@ -1200,7 +1200,8 @@ StickerPanInner::StickerPanInner() : TWidget()
, _top(0)
, _selected(-1)
, _pressedSel(-1)
, _settings(this, lang(lng_stickers_you_have)) {
, _settings(this, lang(lng_stickers_you_have))
, _previewShown(false) {
setMaxHeight(st::emojiPanMaxHeight);
setMouseTracking(true);
@ -1210,6 +1211,9 @@ StickerPanInner::StickerPanInner() : TWidget()
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
connect(&_settings, SIGNAL(clicked()), this, SLOT(onSettings()));
_previewTimer.setSingleShot(true);
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
refreshStickers();
}
@ -1349,15 +1353,23 @@ void StickerPanInner::mousePressEvent(QMouseEvent *e) {
updateSelected();
_pressedSel = _selected;
_previewTimer.start(QApplication::startDragTime());
}
void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
_previewTimer.stop();
int32 pressed = _pressedSel;
_pressedSel = -1;
_lastMousePos = e->globalPos();
updateSelected();
if (_previewShown) {
_previewShown = false;
return;
}
if (_selected < 0 || _selected != pressed) return;
if (_selected >= MatrixRowShift * _sets.size()) {
return;
@ -1638,7 +1650,7 @@ void StickerPanInner::refreshPanels(QVector<EmojiPanel*> &panels) {
}
void StickerPanInner::updateSelected() {
if (_pressedSel >= 0) return;
if (_pressedSel >= 0 && !_previewShown) return;
int32 selIndex = -1;
QPoint p(mapFromGlobal(_lastMousePos));
@ -1715,6 +1727,12 @@ void StickerPanInner::updateSelected() {
}
}
_selected = selIndex;
if (_pressedSel >= 0 && _selected >= 0 && _pressedSel != _selected) {
_pressedSel = _selected;
if (newSel >= 0 && xNewSel < 0) {
Ui::showStickerPreview(_sets.at(newSelTab).pack.at(newSel % MatrixRowShift));
}
}
if (startanim) anim::start(this);
}
@ -1722,6 +1740,16 @@ void StickerPanInner::onSettings() {
App::showLayer(new StickersBox());
}
void StickerPanInner::onPreview() {
if (_pressedSel >= 0 && _pressedSel < MatrixRowShift * _sets.size()) {
int tab = (_pressedSel / MatrixRowShift), sel = _pressedSel % MatrixRowShift;
if (sel < _sets.at(tab).pack.size()) {
Ui::showStickerPreview(_sets.at(tab).pack.at(sel));
_previewShown = true;
}
}
}
bool StickerPanInner::animStep(float64 ms) {
uint64 now = getms();
QRegion toUpdate;

View File

@ -349,6 +349,7 @@ public slots:
void updateSelected();
void onSettings();
void onPreview();
signals:
@ -394,6 +395,9 @@ private:
QPoint _lastMousePos;
LinkButton _settings;
QTimer _previewTimer;
bool _previewShown;
};
class EmojiPanel : public TWidget {

View File

@ -0,0 +1,109 @@
/*
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-2015 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "window.h"
#include "mainwidget.h"
namespace App {
void sendBotCommand(const QString &cmd, MsgId replyTo) {
if (MainWidget *m = main()) m->sendBotCommand(cmd, replyTo);
}
void insertBotCommand(const QString &cmd) {
if (MainWidget *m = main()) m->insertBotCommand(cmd);
}
void searchByHashtag(const QString &tag, PeerData *inPeer) {
if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel()) ? inPeer : 0);
}
void openPeerByName(const QString &username, bool toProfile, const QString &startToken) {
if (MainWidget *m = main()) m->openPeerByName(username, toProfile, startToken);
}
void joinGroupByHash(const QString &hash) {
if (MainWidget *m = main()) m->joinGroupByHash(hash);
}
void stickersBox(const QString &name) {
if (MainWidget *m = main()) m->stickersBox(MTP_inputStickerSetShortName(MTP_string(name)));
}
void openLocalUrl(const QString &url) {
if (MainWidget *m = main()) m->openLocalUrl(url);
}
bool forward(const PeerId &peer, ForwardWhatMessages what) {
if (MainWidget *m = main()) return m->onForward(peer, what);
return false;
}
void removeDialog(History *history) {
if (MainWidget *m = main()) m->removeDialog(history);
}
void showSettings() {
if (Window *win = wnd()) win->showSettings();
}
void showLayer(LayeredWidget *widget, bool forceFast) {
if (Window *w = wnd()) w->showLayer(widget, forceFast);
}
void replaceLayer(LayeredWidget *widget) {
if (Window *w = wnd()) w->replaceLayer(widget);
}
void showLayerLast(LayeredWidget *widget) {
if (Window *w = wnd()) w->showLayerLast(widget);
}
}
namespace Ui {
void showStickerPreview(DocumentData *sticker) {
if (MainWidget *m = App::main()) m->ui_showStickerPreview(sticker);
}
void hideStickerPreview() {
if (MainWidget *m = App::main()) m->ui_hideStickerPreview();
}
}
namespace Notify {
void userIsBotChanged(UserData *user) {
if (MainWidget *m = App::main()) m->notifyUserIsBotChanged(user);
}
void botCommandsChanged(UserData *user) {
if (MainWidget *m = App::main()) m->notifyBotCommandsChanged(user);
}
void migrateUpdated(PeerData *peer) {
if (MainWidget *m = App::main()) m->notifyMigrateUpdated(peer);
}
}

View File

@ -0,0 +1,56 @@
/*
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-2015 John Preston, https://desktop.telegram.org
*/
#pragma once
class LayeredWidget;
namespace App {
void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
void insertBotCommand(const QString &cmd);
void searchByHashtag(const QString &tag, PeerData *inPeer);
void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
void joinGroupByHash(const QString &hash);
void stickersBox(const QString &name);
void openLocalUrl(const QString &url);
bool forward(const PeerId &peer, ForwardWhatMessages what);
void removeDialog(History *history);
void showSettings();
void showLayer(LayeredWidget *w, bool forceFast = false);
void replaceLayer(LayeredWidget *w);
void showLayerLast(LayeredWidget *w);
};
namespace Ui { // it doesn't allow me to use UI :(
void showStickerPreview(DocumentData *sticker);
void hideStickerPreview();
};
namespace Notify {
void userIsBotChanged(UserData *user);
void botCommandsChanged(UserData *user);
void migrateUpdated(PeerData *peer);
};

View File

@ -27,8 +27,12 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "mainwidget.h"
#include "gui/filedialog.h"
BackgroundWidget::BackgroundWidget(QWidget *parent, LayeredWidget *w) : QWidget(parent), w(w),
aBackground(0), aBackgroundFunc(anim::easeOutCirc), hiding(false), shadow(st::boxShadow) {
BackgroundWidget::BackgroundWidget(QWidget *parent, LayeredWidget *w) : TWidget(parent)
, w(w)
, aBackground(0)
, aBackgroundFunc(anim::easeOutCirc)
, hiding(false)
, shadow(st::boxShadow) {
w->setParent(this);
if (App::app()) App::app()->mtpPause();
setGeometry(0, 0, App::wnd()->width(), App::wnd()->height());
@ -189,3 +193,115 @@ BackgroundWidget::~BackgroundWidget() {
(*i)->deleteLater();
}
}
StickerPreviewWidget::StickerPreviewWidget(QWidget *parent) : TWidget(parent)
, a_shown(0, 0)
, _a_shown(animFunc(this, &StickerPreviewWidget::animStep_shown))
, _doc(0)
, _cacheStatus(CacheNotLoaded) {
setAttribute(Qt::WA_TransparentForMouseEvents);
}
void StickerPreviewWidget::paintEvent(QPaintEvent *e) {
Painter p(this);
QRect r(e->rect());
const QPixmap &draw(currentImage());
uint32 w = draw.width() / cIntRetinaFactor(), h = draw.height() / cIntRetinaFactor();
if (_a_shown.animating()) {
float64 shown = a_shown.current();
p.setOpacity(shown);
// w = qMax(qRound(w * (st::stickerPreviewMin + ((1. - st::stickerPreviewMin) * shown)) / 2.) * 2 + int(w % 2), 1);
// h = qMax(qRound(h * (st::stickerPreviewMin + ((1. - st::stickerPreviewMin) * shown)) / 2.) * 2 + int(h % 2), 1);
}
p.fillRect(r, st::stickerPreviewBg);
p.drawPixmap((width() - w) / 2, (height() - h) / 2, draw);
}
void StickerPreviewWidget::resizeEvent(QResizeEvent *e) {
update();
}
bool StickerPreviewWidget::animStep_shown(float64 ms) {
float64 dt = ms / st::stickerPreviewDuration;
if (dt >= 1) {
a_shown.finish();
_a_shown.stop();
if (a_shown.current() < 0.5) hide();
} else {
a_shown.update(dt, anim::linear);
}
update();
return true;
}
void StickerPreviewWidget::showPreview(DocumentData *sticker) {
if (sticker && !sticker->sticker()) sticker = 0;
if (sticker) {
_cache = QPixmap();
if (isHidden() || _a_shown.animating()) {
if (isHidden()) show();
a_shown.start(1);
_a_shown.start();
} else {
update();
}
} else if (isHidden()) {
return;
} else {
a_shown.start(0);
_a_shown.start();
}
_doc = sticker;
_cacheStatus = CacheNotLoaded;
}
void StickerPreviewWidget::hidePreview() {
showPreview(0);
}
QSize StickerPreviewWidget::currentDimensions() const {
if (!_doc) return QSize(_cache.width() / cIntRetinaFactor(), _cache.height() / cIntRetinaFactor());
QSize result(qMax(_doc->dimensions.width(), 1), qMax(_doc->dimensions.height(), 1));
if (result.width() > st::maxStickerSize) {
result.setHeight(qMax(qRound((st::maxStickerSize * result.height()) / result.width()), 1));
result.setWidth(st::maxStickerSize);
}
if (result.height() > st::maxStickerSize) {
result.setWidth(qMax(qRound((st::maxStickerSize * result.width()) / result.height()), 1));
result.setHeight(st::maxStickerSize);
}
return result;
}
QPixmap StickerPreviewWidget::currentImage() const {
if (_doc && _cacheStatus != CacheLoaded) {
bool already = !_doc->already().isEmpty(), hasdata = !_doc->data.isEmpty();
if (!_doc->loader && _doc->status != FileFailed && !already && !hasdata) {
_doc->save(QString());
}
if (_doc->sticker()->img->isNull() && (already || hasdata)) {
if (already) {
_doc->sticker()->img = ImagePtr(_doc->already());
} else {
_doc->sticker()->img = ImagePtr(_doc->data);
}
}
if (_doc->sticker()->img->isNull()) {
if (_cacheStatus != CacheThumbLoaded) {
QSize s = currentDimensions();
_cache = _doc->thumb->pixBlurred(s.width(), s.height());
_cacheStatus = CacheThumbLoaded;
}
} else {
QSize s = currentDimensions();
_cache = _doc->sticker()->img->pix(s.width(), s.height());
_cacheStatus = CacheLoaded;
}
}
return _cache;
}
StickerPreviewWidget::~StickerPreviewWidget() {
}

View File

@ -57,7 +57,7 @@ signals:
};
class BackgroundWidget : public QWidget, public Animated {
class BackgroundWidget : public TWidget, public Animated {
Q_OBJECT
public:
@ -104,3 +104,39 @@ private:
BoxShadow shadow;
};
class StickerPreviewWidget : public TWidget {
Q_OBJECT
public:
StickerPreviewWidget(QWidget *parent);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
bool animStep_shown(float64 ms);
void showPreview(DocumentData *sticker);
void hidePreview();
~StickerPreviewWidget();
private:
QSize currentDimensions() const;
QPixmap currentImage() const;
anim::fvalue a_shown;
Animation _a_shown;
DocumentData *_doc;
enum CacheStatus {
CacheNotLoaded,
CacheThumbLoaded,
CacheLoaded,
};
mutable CacheStatus _cacheStatus;
mutable QPixmap _cache;
};

View File

@ -395,6 +395,7 @@ MainWidget::MainWidget(Window *window) : TWidget(window)
, _hider(0)
, _peerInStack(0)
, _msgIdInStack(0)
, _stickerPreview(0)
, _playerHeight(0)
, _contentScrollAddToY(0)
, _mediaType(this)
@ -744,6 +745,20 @@ QPixmap MainWidget::grabTopBar() {
}
}
void MainWidget::ui_showStickerPreview(DocumentData *sticker) {
if (!sticker || !sticker->sticker()) return;
if (!_stickerPreview) {
_stickerPreview = new StickerPreviewWidget(this);
resizeEvent(0);
}
_stickerPreview->showPreview(sticker);
}
void MainWidget::ui_hideStickerPreview() {
if (!_stickerPreview) return;
_stickerPreview->hidePreview();
}
void MainWidget::noHider(HistoryHider *destroyed) {
if (_hider == destroyed) {
_hider = 0;
@ -2566,6 +2581,7 @@ void MainWidget::orderWidgets() {
dialogs.raise();
_mediaType.raise();
if (_hider) _hider->raise();
if (_stickerPreview) _stickerPreview->raise();
}
QRect MainWidget::historyRect() const {
@ -2826,6 +2842,7 @@ void MainWidget::resizeEvent(QResizeEvent *e) {
_mediaType.moveToLeft(width() - _mediaType.width(), _playerHeight + st::topBarHeight);
if (profile) profile->setGeometry(history.geometry());
if (overview) overview->setGeometry(history.geometry());
if (_stickerPreview) _stickerPreview->setGeometry(rect());
_contentScrollAddToY = 0;
}

View File

@ -178,6 +178,8 @@ public:
}
};
class StickerPreviewWidget;
class MainWidget : public TWidget, public RPCSender {
Q_OBJECT
@ -412,6 +414,9 @@ public:
QPixmap grabTopBar();
QPixmap grabInner();
void ui_showStickerPreview(DocumentData *sticker);
void ui_hideStickerPreview();
~MainWidget();
signals:
@ -565,6 +570,8 @@ private:
PeerData *_peerInStack;
MsgId _msgIdInStack;
StickerPreviewWidget *_stickerPreview;
int32 _playerHeight;
int32 _contentScrollAddToY;

View File

@ -0,0 +1,41 @@
/*
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-2015 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
void aesEncrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
uchar aes_key[32], aes_iv[32];
memcpy(aes_key, key, 32);
memcpy(aes_iv, iv, 32);
AES_KEY aes;
AES_set_encrypt_key(aes_key, 256, &aes);
AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_ENCRYPT);
}
void aesDecrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
uchar aes_key[32], aes_iv[32];
memcpy(aes_key, key, 32);
memcpy(aes_iv, iv, 32);
AES_KEY aes;
AES_set_decrypt_key(aes_key, 256, &aes);
AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_DECRYPT);
}

View File

@ -112,15 +112,8 @@ inline bool operator==(const mtpAuthKey &a, const mtpAuthKey &b) {
typedef QSharedPointer<mtpAuthKey> mtpAuthKeyPtr;
typedef QVector<mtpAuthKeyPtr> mtpKeysMap;
inline void aesEncrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
uchar aes_key[32], aes_iv[32];
memcpy(aes_key, key, 32);
memcpy(aes_iv, iv, 32);
AES_KEY aes;
AES_set_encrypt_key(aes_key, 256, &aes);
AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_ENCRYPT);
}
void aesEncrypt(const void *src, void *dst, uint32 len, void *key, void *iv);
void aesDecrypt(const void *src, void *dst, uint32 len, void *key, void *iv);
inline void aesEncrypt(const void *src, void *dst, uint32 len, const mtpAuthKeyPtr &authKey, const MTPint128 &msgKey) {
MTPint256 aesKey, aesIV;
@ -136,16 +129,6 @@ inline void aesEncryptLocal(const void *src, void *dst, uint32 len, const mtpAut
return aesEncrypt(src, dst, len, &aesKey, &aesIV);
}
inline void aesDecrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
uchar aes_key[32], aes_iv[32];
memcpy(aes_key, key, 32);
memcpy(aes_iv, iv, 32);
AES_KEY aes;
AES_set_decrypt_key(aes_key, 256, &aes);
AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_DECRYPT);
}
inline void aesDecrypt(const void *src, void *dst, uint32 len, const mtpAuthKeyPtr &authKey, const MTPint128 &msgKey) {
MTPint256 aesKey, aesIV;
authKey->prepareAES(msgKey, aesKey, aesIV, false);

View File

@ -436,3 +436,10 @@ inline int32 ceilclamp(int32 value, int32 step, int32 lowest, int32 highest) {
inline int32 ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) {
return qMax(qMin(qCeil(value / step), highest), lowest);
}
enum ForwardWhatMessages {
ForwardSelectedMessages,
ForwardContextMessage,
ForwardPressedMessage,
ForwardPressedLinkMessage
};

View File

@ -987,6 +987,8 @@ bool Window::eventFilter(QObject *obj, QEvent *evt) {
psUserActionDone();
main->checkIdleFinish();
}
} else if (t == QEvent::MouseButtonRelease) {
Ui::hideStickerPreview();
}
if (obj == App::app()) {
if (t == QEvent::ApplicationActivate) {

View File

@ -992,6 +992,7 @@
<ClCompile Include="SourceFiles\boxes\usernamebox.cpp" />
<ClCompile Include="SourceFiles\dialogswidget.cpp" />
<ClCompile Include="SourceFiles\dropdown.cpp" />
<ClCompile Include="SourceFiles\facades.cpp" />
<ClCompile Include="SourceFiles\fileuploader.cpp" />
<ClCompile Include="SourceFiles\gui\animation.cpp" />
<ClCompile Include="SourceFiles\gui\boxshadow.cpp" />
@ -1029,6 +1030,7 @@
<ClCompile Include="SourceFiles\mainwidget.cpp" />
<ClCompile Include="SourceFiles\mediaview.cpp" />
<ClCompile Include="SourceFiles\mtproto\mtp.cpp" />
<ClCompile Include="SourceFiles\mtproto\mtpAuthKey.cpp" />
<ClCompile Include="SourceFiles\mtproto\mtpConnection.cpp" />
<ClCompile Include="SourceFiles\mtproto\mtpCoreTypes.cpp" />
<ClCompile Include="SourceFiles\mtproto\mtpDC.cpp" />
@ -1552,6 +1554,7 @@
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
</CustomBuild>
<ClInclude Include="SourceFiles\facades.h" />
<ClInclude Include="SourceFiles\gui\boxshadow.h" />
<CustomBuild Include="SourceFiles\gui\popupmenu.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>

View File

@ -900,6 +900,12 @@
<ClCompile Include="SourceFiles\gui\popupmenu.cpp">
<Filter>gui</Filter>
</ClCompile>
<ClCompile Include="SourceFiles\facades.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SourceFiles\mtproto\mtpAuthKey.cpp">
<Filter>mtproto</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="SourceFiles\stdafx.h">
@ -989,6 +995,9 @@
<ClInclude Include="SourceFiles\config.h">
<Filter>Version</Filter>
</ClInclude>
<ClInclude Include="SourceFiles\facades.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="SourceFiles\mtproto\mtpConnection.h">