mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Removed Function<> and SharedCallback<>, using base::lambda_unique<>.
Also removed macro START_ANIMATION(anim,) using anim.start() instead.
This commit is contained in:
parent
866bc4ff8a
commit
453661d611
61 changed files with 322 additions and 502 deletions
|
@ -42,11 +42,10 @@ ApiWrap::ApiWrap(QObject *parent) : QObject(parent)
|
|||
void ApiWrap::init() {
|
||||
}
|
||||
|
||||
void ApiWrap::requestMessageData(ChannelData *channel, MsgId msgId, std_::unique_ptr<RequestMessageDataCallback> callback) {
|
||||
void ApiWrap::requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback &&callback) {
|
||||
MessageDataRequest &req(channel ? _channelMessageDataRequests[channel][msgId] : _messageDataRequests[msgId]);
|
||||
if (callback) {
|
||||
MessageDataRequest::CallbackPtr pcallback(callback.release());
|
||||
req.callbacks.append(pcallback);
|
||||
req.callbacks.append(std_::move(callback));
|
||||
}
|
||||
if (!req.req) _messageDataResolveDelayed->call();
|
||||
}
|
||||
|
@ -138,7 +137,7 @@ void ApiWrap::gotMessageDatas(ChannelData *channel, const MTPmessages_Messages &
|
|||
for (auto i = requests->begin(); i != requests->cend();) {
|
||||
if (i.value().req == req) {
|
||||
for_const (auto &callback, i.value().callbacks) {
|
||||
callback->call(channel, i.key());
|
||||
callback(channel, i.key());
|
||||
}
|
||||
i = requests->erase(i);
|
||||
} else {
|
||||
|
|
|
@ -28,8 +28,8 @@ public:
|
|||
ApiWrap(QObject *parent);
|
||||
void init();
|
||||
|
||||
using RequestMessageDataCallback = SharedCallback<void, ChannelData*, MsgId>;
|
||||
void requestMessageData(ChannelData *channel, MsgId msgId, std_::unique_ptr<RequestMessageDataCallback> callback);
|
||||
using RequestMessageDataCallback = base::lambda_wrap<void(ChannelData*, MsgId)>;
|
||||
void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback &&callback);
|
||||
|
||||
void requestFullPeer(PeerData *peer);
|
||||
void requestPeer(PeerData *peer);
|
||||
|
@ -82,11 +82,8 @@ private:
|
|||
|
||||
void gotMessageDatas(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req);
|
||||
struct MessageDataRequest {
|
||||
MessageDataRequest() : req(0) {
|
||||
}
|
||||
typedef SharedCallback<void, ChannelData*, MsgId>::Ptr CallbackPtr;
|
||||
typedef QList<CallbackPtr> Callbacks;
|
||||
mtpRequestId req;
|
||||
using Callbacks = QList<RequestMessageDataCallback>;
|
||||
mtpRequestId req = 0;
|
||||
Callbacks callbacks;
|
||||
};
|
||||
typedef QMap<MsgId, MessageDataRequest> MessageDataRequests;
|
||||
|
|
|
@ -227,9 +227,9 @@ void ShareBox::onMustScrollTo(int top, int bottom) {
|
|||
to = bottom - (scrollBottom - scrollTop);
|
||||
}
|
||||
if (from != to) {
|
||||
START_ANIMATION(_scrollAnimation, func([this]() {
|
||||
_scrollAnimation.start([this]() {
|
||||
scrollArea()->scrollToY(_scrollAnimation.current(scrollArea()->scrollTop()));
|
||||
}), from, to, st::shareScrollDuration, anim::sineInOut);
|
||||
}, from, to, st::shareScrollDuration, anim::sineInOut);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,9 +437,9 @@ void ShareInner::setActive(int active) {
|
|||
if (active != _active) {
|
||||
auto changeNameFg = [this](int index, style::color from, style::color to) {
|
||||
if (auto chat = getChatAtIndex(index)) {
|
||||
START_ANIMATION(chat->nameFg, func([this, chat] {
|
||||
chat->nameFg.start([this, chat] {
|
||||
repaintChat(chat->peer);
|
||||
}), from->c, to->c, st::shareActivateDuration, anim::linear);
|
||||
}, from->c, to->c, st::shareActivateDuration);
|
||||
}
|
||||
};
|
||||
changeNameFg(_active, st::shareNameActiveFg, st::shareNameFg);
|
||||
|
@ -459,16 +459,7 @@ void ShareInner::paintChat(Painter &p, Chat *chat, int index) {
|
|||
auto w = width();
|
||||
auto photoLeft = (_rowWidth - (st::sharePhotoRadius * 2)) / 2;
|
||||
auto photoTop = st::sharePhotoTop;
|
||||
if (chat->selection.isNull()) {
|
||||
if (!chat->wideUserpicCache.isNull()) {
|
||||
chat->wideUserpicCache = QPixmap();
|
||||
}
|
||||
auto userpicRadius = chat->selected ? st::sharePhotoSmallRadius : st::sharePhotoRadius;
|
||||
auto userpicShift = st::sharePhotoRadius - userpicRadius;
|
||||
auto userpicLeft = x + photoLeft + userpicShift;
|
||||
auto userpicTop = y + photoTop + userpicShift;
|
||||
chat->peer->paintUserpicLeft(p, userpicRadius * 2, userpicLeft, userpicTop, w);
|
||||
} else {
|
||||
if (chat->selection.animating()) {
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
auto userpicRadius = qRound(WideCacheScale * (st::sharePhotoRadius + (st::sharePhotoSmallRadius - st::sharePhotoRadius) * selectionLevel));
|
||||
auto userpicShift = WideCacheScale * st::sharePhotoRadius - userpicRadius;
|
||||
|
@ -478,6 +469,15 @@ void ShareInner::paintChat(Painter &p, Chat *chat, int index) {
|
|||
auto from = QRect(QPoint(0, 0), chat->wideUserpicCache.size());
|
||||
p.drawPixmapLeft(to, w, chat->wideUserpicCache, from);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
} else {
|
||||
if (!chat->wideUserpicCache.isNull()) {
|
||||
chat->wideUserpicCache = QPixmap();
|
||||
}
|
||||
auto userpicRadius = chat->selected ? st::sharePhotoSmallRadius : st::sharePhotoRadius;
|
||||
auto userpicShift = st::sharePhotoRadius - userpicRadius;
|
||||
auto userpicLeft = x + photoLeft + userpicShift;
|
||||
auto userpicTop = y + photoTop + userpicShift;
|
||||
chat->peer->paintUserpicLeft(p, userpicRadius * 2, userpicLeft, userpicTop, w);
|
||||
}
|
||||
|
||||
if (selectionLevel > 0) {
|
||||
|
@ -516,11 +516,12 @@ void ShareInner::paintChat(Painter &p, Chat *chat, int index) {
|
|||
p.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
p.setOpacity(1.);
|
||||
|
||||
if (chat->nameFg.isNull()) {
|
||||
p.setPen((index == _active) ? st::shareNameActiveFg : st::shareNameFg);
|
||||
} else {
|
||||
if (chat->nameFg.animating()) {
|
||||
p.setPen(chat->nameFg.current());
|
||||
} else {
|
||||
p.setPen((index == _active) ? st::shareNameActiveFg : st::shareNameFg);
|
||||
}
|
||||
|
||||
auto nameWidth = (_rowWidth - st::shareColumnSkip);
|
||||
auto nameLeft = st::shareColumnSkip / 2;
|
||||
auto nameTop = photoTop + st::sharePhotoRadius * 2 + st::shareNameTop;
|
||||
|
@ -670,21 +671,21 @@ void ShareInner::changeCheckState(Chat *chat) {
|
|||
if (chat->selected) {
|
||||
_selected.insert(chat->peer);
|
||||
chat->icons.push_back(Chat::Icon());
|
||||
START_ANIMATION(chat->icons.back().fadeIn, func([this, chat] {
|
||||
chat->icons.back().fadeIn.start([this, chat] {
|
||||
repaintChat(chat->peer);
|
||||
}), 0, 1, st::shareSelectDuration, anim::linear);
|
||||
}, 0, 1, st::shareSelectDuration);
|
||||
} else {
|
||||
_selected.remove(chat->peer);
|
||||
prepareWideCheckIconCache(&chat->icons.back());
|
||||
START_ANIMATION(chat->icons.back().fadeOut, func([this, chat] {
|
||||
removeFadeOutedIcons(chat);
|
||||
chat->icons.back().fadeOut.start([this, chat] {
|
||||
repaintChat(chat->peer);
|
||||
}), 1, 0, st::shareSelectDuration, anim::linear);
|
||||
removeFadeOutedIcons(chat); // this call can destroy current lambda
|
||||
}, 1, 0, st::shareSelectDuration);
|
||||
}
|
||||
prepareWideUserpicCache(chat);
|
||||
START_ANIMATION(chat->selection, func([this, chat] {
|
||||
chat->selection.start([this, chat] {
|
||||
repaintChat(chat->peer);
|
||||
}), chat->selected ? 0 : 1, chat->selected ? 1 : 0, st::shareSelectDuration, anim_bumpy);
|
||||
}, chat->selected ? 0 : 1, chat->selected ? 1 : 0, st::shareSelectDuration, anim_bumpy);
|
||||
if (chat->selected) {
|
||||
setActive(chatIndex(chat->peer));
|
||||
}
|
||||
|
@ -692,9 +693,9 @@ void ShareInner::changeCheckState(Chat *chat) {
|
|||
}
|
||||
|
||||
void ShareInner::removeFadeOutedIcons(Chat *chat) {
|
||||
while (!chat->icons.empty() && chat->icons.front().fadeIn.isNull() && chat->icons.front().fadeOut.isNull()) {
|
||||
while (!chat->icons.empty() && !chat->icons.front().fadeIn.animating() && !chat->icons.front().fadeOut.animating()) {
|
||||
if (chat->icons.size() > 1 || !chat->selected) {
|
||||
chat->icons.pop_front();
|
||||
chat->icons.erase(chat->icons.begin());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -1016,18 +1017,6 @@ void shareGameScoreFromItem(HistoryItem *item) {
|
|||
Ui::showLayer(new ShareBox(std_::move(copyCallback), std_::move(submitCallback)));
|
||||
}
|
||||
|
||||
class GameMessageResolvedCallback : public SharedCallback<void, ChannelData*, MsgId> {
|
||||
public:
|
||||
void call(ChannelData *channel, MsgId msgId) const override {
|
||||
if (auto item = App::histItemById(channel, msgId)) {
|
||||
shareGameScoreFromItem(item);
|
||||
} else {
|
||||
Ui::showLayer(new InformBox(lang(lng_edit_deleted)));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void shareGameScoreByHash(const QString &hash) {
|
||||
|
@ -1062,7 +1051,13 @@ void shareGameScoreByHash(const QString &hash) {
|
|||
} else if (App::api()) {
|
||||
auto channel = channelId ? App::channelLoaded(channelId) : nullptr;
|
||||
if (channel || !channelId) {
|
||||
App::api()->requestMessageData(channel, msgId, std_::make_unique<GameMessageResolvedCallback>());
|
||||
App::api()->requestMessageData(channel, msgId, [](ChannelData *channel, MsgId msgId) {
|
||||
if (auto item = App::histItemById(channel, msgId)) {
|
||||
shareGameScoreFromItem(item);
|
||||
} else {
|
||||
Ui::showLayer(new InformBox(lang(lng_edit_deleted)));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "abstractbox.h"
|
||||
#include "core/lambda_wrap.h"
|
||||
#include "core/observer.h"
|
||||
#include "core/vector_of_moveable.h"
|
||||
|
||||
namespace Dialogs {
|
||||
class Row;
|
||||
|
@ -163,7 +164,7 @@ private:
|
|||
FloatAnimation fadeOut;
|
||||
QPixmap wideCheckCache;
|
||||
};
|
||||
QList<Icon> icons;
|
||||
std_::vector_of_moveable<Icon> icons;
|
||||
};
|
||||
void paintChat(Painter &p, Chat *chat, int index);
|
||||
void updateChat(PeerData *peer);
|
||||
|
|
|
@ -62,8 +62,8 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) {
|
|||
_selected = -1;
|
||||
setCursor(style::cur_default);
|
||||
if (set.type() == mtpc_messages_stickerSet) {
|
||||
auto &d(set.c_messages_stickerSet());
|
||||
auto &v(d.vdocuments.c_vector().v);
|
||||
auto &d = set.c_messages_stickerSet();
|
||||
auto &v = d.vdocuments.c_vector().v;
|
||||
_pack.reserve(v.size());
|
||||
_packOvers.reserve(v.size());
|
||||
for (int i = 0, l = v.size(); i < l; ++i) {
|
||||
|
@ -247,13 +247,13 @@ void StickerSetInner::updateSelected() {
|
|||
|
||||
void StickerSetInner::startOverAnimation(int index, float64 from, float64 to) {
|
||||
if (index >= 0 && index < _packOvers.size()) {
|
||||
START_ANIMATION(_packOvers[index], func([this, index]() {
|
||||
_packOvers[index].start([this, index] {
|
||||
int row = index / StickerPanPerRow;
|
||||
int column = index % StickerPanPerRow;
|
||||
int left = st::stickersPadding.left() + column * st::stickersSize.width();
|
||||
int top = st::stickersPadding.top() + row * st::stickersSize.height();
|
||||
rtlupdate(left, top, st::stickersSize.width(), st::stickersSize.height());
|
||||
}), from, to, st::emojiPanDuration, anim::linear);
|
||||
}, from, to, st::emojiPanDuration);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#include "abstractbox.h"
|
||||
#include "core/vector_of_moveable.h"
|
||||
|
||||
class ConfirmBox;
|
||||
|
||||
|
@ -69,7 +70,7 @@ private:
|
|||
return (_setFlags & MTPDstickerSet::Flag::f_masks);
|
||||
}
|
||||
|
||||
QVector<FloatAnimation> _packOvers;
|
||||
std_::vector_of_moveable<FloatAnimation> _packOvers;
|
||||
StickerPack _pack;
|
||||
StickersByEmojiMap _emoji;
|
||||
bool _loaded = false;
|
||||
|
|
|
@ -20,6 +20,17 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include <QtCore/QReadWriteLock>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#ifndef OS_MAC_OLD
|
||||
#include <memory>
|
||||
#endif // OS_MAC_OLD
|
||||
|
||||
template <typename T>
|
||||
void deleteAndMark(T *&link) {
|
||||
delete link;
|
||||
|
@ -259,13 +270,6 @@ typedef float float32;
|
|||
typedef double float64;
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include <QtCore/QReadWriteLock>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
using std::string;
|
||||
using std::exception;
|
||||
#ifdef OS_MAC_OLD
|
||||
|
@ -1035,13 +1039,15 @@ struct ComponentWrapStruct {
|
|||
// global scope, so it will be filled by zeros from the start
|
||||
ComponentWrapStruct() {
|
||||
}
|
||||
ComponentWrapStruct(int size, ComponentConstruct construct, ComponentDestruct destruct, ComponentMove move)
|
||||
ComponentWrapStruct(std::size_t size, std::size_t align, ComponentConstruct construct, ComponentDestruct destruct, ComponentMove move)
|
||||
: Size(size)
|
||||
, Align(align)
|
||||
, Construct(construct)
|
||||
, Destruct(destruct)
|
||||
, Move(move) {
|
||||
}
|
||||
int Size;
|
||||
std::size_t Size;
|
||||
std::size_t Align;
|
||||
ComponentConstruct Construct;
|
||||
ComponentDestruct Destruct;
|
||||
ComponentMove Move;
|
||||
|
@ -1058,6 +1064,7 @@ extern QAtomicInt ComponentIndexLast;
|
|||
template <typename Type>
|
||||
struct BaseComponent {
|
||||
BaseComponent() {
|
||||
static_assert(alignof(Type) <= sizeof(SmallestSizeType), "Components should align to a pointer!");
|
||||
}
|
||||
BaseComponent(const BaseComponent &other) = delete;
|
||||
BaseComponent &operator=(const BaseComponent &other) = delete;
|
||||
|
@ -1075,8 +1082,11 @@ struct BaseComponent {
|
|||
t_assert(last < 64);
|
||||
if (_index.testAndSetOrdered(0, last + 1)) {
|
||||
ComponentWraps[last] = ComponentWrapStruct(
|
||||
CeilDivideMinimumOne<sizeof(Type), sizeof(uint64)>::Result * sizeof(uint64),
|
||||
Type::ComponentConstruct, Type::ComponentDestruct, Type::ComponentMove);
|
||||
CeilDivideMinimumOne<sizeof(Type), sizeof(SmallestSizeType)>::Result * sizeof(SmallestSizeType),
|
||||
alignof(Type),
|
||||
Type::ComponentConstruct,
|
||||
Type::ComponentDestruct,
|
||||
Type::ComponentMove);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1088,6 +1098,8 @@ struct BaseComponent {
|
|||
}
|
||||
|
||||
protected:
|
||||
using SmallestSizeType = void*;
|
||||
|
||||
static void ComponentConstruct(void *location, Composer *composer) {
|
||||
new (location) Type();
|
||||
}
|
||||
|
@ -1102,7 +1114,6 @@ protected:
|
|||
|
||||
class ComposerMetadata {
|
||||
public:
|
||||
|
||||
ComposerMetadata(uint64 mask) : size(0), last(64), _mask(mask) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
uint64 m = (1ULL << i);
|
||||
|
@ -1147,15 +1158,13 @@ const ComposerMetadata *GetComposerMetadata(uint64 mask);
|
|||
|
||||
class Composer {
|
||||
public:
|
||||
|
||||
Composer(uint64 mask = 0) : _data(zerodata()) {
|
||||
if (mask) {
|
||||
const ComposerMetadata *meta = GetComposerMetadata(mask);
|
||||
int size = sizeof(meta) + meta->size;
|
||||
void *data = operator new(size);
|
||||
if (!data) { // terminate if we can't allocate memory
|
||||
throw "Can't allocate memory!";
|
||||
}
|
||||
|
||||
auto data = operator new(size);
|
||||
t_assert(data != nullptr);
|
||||
|
||||
_data = data;
|
||||
_meta() = meta;
|
||||
|
@ -1163,7 +1172,13 @@ public:
|
|||
int offset = meta->offsets[i];
|
||||
if (offset >= 0) {
|
||||
try {
|
||||
ComponentWraps[i].Construct(_dataptrunsafe(offset), this);
|
||||
auto constructAt = _dataptrunsafe(offset);
|
||||
#ifndef OS_MAC_OLD
|
||||
auto space = ComponentWraps[i].Size;
|
||||
auto alignedAt = std::align(ComponentWraps[i].Align, space, constructAt, space);
|
||||
t_assert(alignedAt == constructAt);
|
||||
#endif // OS_MAC_OLD
|
||||
ComponentWraps[i].Construct(constructAt, this);
|
||||
} catch (...) {
|
||||
while (i > 0) {
|
||||
--i;
|
||||
|
@ -1182,7 +1197,7 @@ public:
|
|||
Composer &operator=(const Composer &other) = delete;
|
||||
~Composer() {
|
||||
if (_data != zerodata()) {
|
||||
const ComposerMetadata *meta = _meta();
|
||||
auto meta = _meta();
|
||||
for (int i = 0; i < meta->last; ++i) {
|
||||
int offset = meta->offsets[i];
|
||||
if (offset >= 0) {
|
||||
|
@ -1213,7 +1228,7 @@ protected:
|
|||
Composer tmp(mask);
|
||||
tmp.swap(*this);
|
||||
if (_data != zerodata() && tmp._data != zerodata()) {
|
||||
const ComposerMetadata *meta = _meta(), *wasmeta = tmp._meta();
|
||||
auto meta = _meta(), wasmeta = tmp._meta();
|
||||
for (int i = 0; i < meta->last; ++i) {
|
||||
int offset = meta->offsets[i], wasoffset = wasmeta->offsets[i];
|
||||
if (offset >= 0 && wasoffset >= 0) {
|
||||
|
@ -1252,103 +1267,3 @@ private:
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class SharedCallback {
|
||||
public:
|
||||
virtual R call(Args... args) const = 0;
|
||||
virtual ~SharedCallback() {
|
||||
}
|
||||
using Ptr = QSharedPointer<SharedCallback<R, Args...>>;
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class FunctionImplementation {
|
||||
public:
|
||||
virtual R call(Args... args) = 0;
|
||||
virtual void destroy() { delete this; }
|
||||
virtual ~FunctionImplementation() {}
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class NullFunctionImplementation : public FunctionImplementation<R, Args...> {
|
||||
public:
|
||||
R call(Args... args) override { return R(); }
|
||||
void destroy() override {}
|
||||
static NullFunctionImplementation<R, Args...> SharedInstance;
|
||||
|
||||
};
|
||||
template <typename R, typename... Args>
|
||||
NullFunctionImplementation<R, Args...> NullFunctionImplementation<R, Args...>::SharedInstance;
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class Function {
|
||||
public:
|
||||
Function() : _implementation(nullImpl()) {}
|
||||
Function(FunctionImplementation<R, Args...> *implementation) : _implementation(implementation) {}
|
||||
Function(const Function<R, Args...> &other) = delete;
|
||||
Function<R, Args...> &operator=(const Function<R, Args...> &other) = delete;
|
||||
Function(Function<R, Args...> &&other) : _implementation(other._implementation) {
|
||||
other._implementation = nullImpl();
|
||||
}
|
||||
Function<R, Args...> &operator=(Function<R, Args...> &&other) {
|
||||
std::swap(_implementation, other._implementation);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return (_implementation == nullImpl());
|
||||
}
|
||||
|
||||
R call(Args... args) { return _implementation->call(args...); }
|
||||
~Function() {
|
||||
if (_implementation) {
|
||||
_implementation->destroy();
|
||||
_implementation = nullptr;
|
||||
}
|
||||
deleteAndMark(_implementation);
|
||||
}
|
||||
|
||||
private:
|
||||
static FunctionImplementation<R, Args...> *nullImpl() {
|
||||
return &NullFunctionImplementation<R, Args...>::SharedInstance;
|
||||
}
|
||||
|
||||
FunctionImplementation<R, Args...> *_implementation;
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class WrappedFunction : public FunctionImplementation<R, Args...> {
|
||||
public:
|
||||
using Method = R(*)(Args... args);
|
||||
WrappedFunction(Method method) : _method(method) {}
|
||||
R call(Args... args) override { return (*_method)(args...); }
|
||||
|
||||
private:
|
||||
Method _method;
|
||||
|
||||
};
|
||||
template <typename R, typename... Args>
|
||||
inline Function<R, Args...> func(R(*method)(Args... args)) {
|
||||
return Function<R, Args...>(new WrappedFunction<R, Args...>(method));
|
||||
}
|
||||
|
||||
template <typename O, typename I, typename R, typename... Args>
|
||||
class ObjectFunction : public FunctionImplementation<R, Args...> {
|
||||
public:
|
||||
using Method = R(I::*)(Args... args);
|
||||
ObjectFunction(O *obj, Method method) : _obj(obj), _method(method) {}
|
||||
R call(Args... args) override { return (_obj->*_method)(args...); }
|
||||
|
||||
private:
|
||||
O *_obj;
|
||||
Method _method;
|
||||
|
||||
};
|
||||
template <typename O, typename I, typename R, typename... Args>
|
||||
inline Function<R, Args...> func(O *obj, R(I::*method)(Args...)) {
|
||||
return Function<R, Args...>(new ObjectFunction<O, I, R, Args...>(obj, method));
|
||||
}
|
||||
|
|
|
@ -373,48 +373,20 @@ public:
|
|||
|
||||
} // namespace base
|
||||
|
||||
// While we still use Function<>
|
||||
// While we still use rpcDone() and rpcFail()
|
||||
|
||||
#include "mtproto/rpc_sender.h"
|
||||
|
||||
template <typename FunctionType>
|
||||
struct LambdaFunctionHelper;
|
||||
struct LambdaUniqueHelper;
|
||||
|
||||
template <typename Lambda, typename R, typename ...Args>
|
||||
struct LambdaFunctionHelper<R(Lambda::*)(Args...) const> {
|
||||
using FunctionType = Function<R, Args...>;
|
||||
struct LambdaUniqueHelper<R(Lambda::*)(Args...) const> {
|
||||
using UniqueType = base::lambda_unique<R(Args...)>;
|
||||
};
|
||||
|
||||
template <typename FunctionType>
|
||||
using LambdaGetFunction = typename LambdaFunctionHelper<FunctionType>::FunctionType;
|
||||
|
||||
template <typename FunctionType>
|
||||
using LambdaGetUnique = typename LambdaFunctionHelper<FunctionType>::UniqueType;
|
||||
|
||||
template <typename R, typename ...Args>
|
||||
class LambdaFunctionImplementation : public FunctionImplementation<R, Args...> {
|
||||
public:
|
||||
LambdaFunctionImplementation(base::lambda_unique<R(Args...)> &&lambda) : _lambda(std_::move(lambda)) {
|
||||
}
|
||||
R call(Args... args) override { return _lambda(std_::forward<Args>(args)...); }
|
||||
|
||||
private:
|
||||
base::lambda_unique<R(Args...)> _lambda;
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename ...Args>
|
||||
inline Function<R, Args...> func_lambda_wrap_helper(base::lambda_unique<R(Args...)> &&lambda) {
|
||||
return Function<R, Args...>(new LambdaFunctionImplementation<R, Args...>(std_::move(lambda)));
|
||||
}
|
||||
|
||||
template <typename Lambda, typename = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>>
|
||||
inline LambdaGetFunction<decltype(&Lambda::operator())> func(Lambda &&lambda) {
|
||||
return func_lambda_wrap_helper(LambdaGetUnique<decltype(&Lambda::operator())>(std_::move(lambda)));
|
||||
}
|
||||
|
||||
// While we still use rpcDone() and rpcFail()
|
||||
|
||||
#include "mtproto/rpc_sender.h"
|
||||
using LambdaGetUnique = typename LambdaUniqueHelper<FunctionType>::UniqueType;
|
||||
|
||||
template <typename Base, typename FunctionType>
|
||||
class RPCHandlerImplementation : public Base {
|
||||
|
|
|
@ -58,7 +58,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
// Handler is one of Function<> instantiations.
|
||||
// Handler is one of base::lambda_unique<> instantiations.
|
||||
template <typename Flags, typename Handler>
|
||||
struct ObserversList {
|
||||
struct Entry {
|
||||
|
@ -109,8 +109,8 @@ public:
|
|||
// entries list while the loop is still running.
|
||||
for (int i = 0; i < entries.size(); ++i) {
|
||||
auto &entry = entries[i];
|
||||
if (!entry.handler.isNull() && (flags & entry.flags)) {
|
||||
entry.handler.call(std_::forward<Args>(args)...);
|
||||
if (entry.handler && (flags & entry.flags)) {
|
||||
entry.handler(std_::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ private:
|
|||
if (entries.size() <= connectionIndex) return;
|
||||
|
||||
if (entries.size() == connectionIndex + 1) {
|
||||
for (entries.pop_back(); !entries.isEmpty() && entries.back().handler.isNull();) {
|
||||
for (entries.pop_back(); !entries.isEmpty() && !entries.back().handler;) {
|
||||
entries.pop_back();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -93,6 +93,7 @@ public:
|
|||
*prev = std_::move(*next);
|
||||
}
|
||||
--_size;
|
||||
end()->~T();
|
||||
return it;
|
||||
}
|
||||
|
||||
|
@ -143,15 +144,21 @@ public:
|
|||
}
|
||||
inline const T &at(int index) const {
|
||||
if (index < 0 || index >= _size) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
|
||||
throw std::exception();
|
||||
#else // QT_VERSION < 5.5.0
|
||||
#ifndef OS_MAC_OLD
|
||||
throw std::out_of_range("");
|
||||
#endif // QT_VERSION < 5.5.0
|
||||
#else // OS_MAC_OLD
|
||||
throw std::exception();
|
||||
#endif // OS_MAC_OLD
|
||||
}
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
void reserve(int newCapacity) {
|
||||
if (newCapacity > _capacity) {
|
||||
reallocate(newCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
inline ~vector_of_moveable() {
|
||||
clear();
|
||||
}
|
||||
|
|
|
@ -2644,10 +2644,12 @@ void HistoryMessageReplyMarkup::create(const MTPReplyMarkup &markup) {
|
|||
}
|
||||
}
|
||||
|
||||
void HistoryDependentItemCallback::call(ChannelData *channel, MsgId msgId) const {
|
||||
if (HistoryItem *item = App::histItemById(_dependent)) {
|
||||
item->updateDependencyItem();
|
||||
}
|
||||
ApiWrap::RequestMessageDataCallback historyDependentItemCallback(const FullMsgId &msgId) {
|
||||
return [dependent = msgId](ChannelData *channel, MsgId msgId) {
|
||||
if (HistoryItem *item = App::histItemById(dependent)) {
|
||||
item->updateDependencyItem();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void HistoryMessageUnreadBar::init(int count) {
|
||||
|
@ -4910,7 +4912,9 @@ bool HistoryGif::playInline(bool autoplay) {
|
|||
if (!cAutoPlayGif()) {
|
||||
App::stopGifItems();
|
||||
}
|
||||
_gif = new Media::Clip::Reader(_data->location(), _data->data(), func(_parent, &HistoryItem::clipCallback));
|
||||
_gif = new Media::Clip::Reader(_data->location(), _data->data(), [this](Media::Clip::Notification notification) {
|
||||
_parent->clipCallback(notification);
|
||||
});
|
||||
App::regGifItem(_gif, _parent);
|
||||
if (gif()) _gif->setAutoplay();
|
||||
}
|
||||
|
@ -6837,7 +6841,7 @@ void HistoryMessage::createComponents(const CreateConfig &config) {
|
|||
if (auto reply = Get<HistoryMessageReply>()) {
|
||||
reply->replyToMsgId = config.replyTo;
|
||||
if (!reply->updateData(this) && App::api()) {
|
||||
App::api()->requestMessageData(history()->peer->asChannel(), reply->replyToMsgId, std_::make_unique<HistoryDependentItemCallback>(fullId()));
|
||||
App::api()->requestMessageData(history()->peer->asChannel(), reply->replyToMsgId, historyDependentItemCallback(fullId()));
|
||||
}
|
||||
}
|
||||
if (auto via = Get<HistoryMessageVia>()) {
|
||||
|
@ -8388,7 +8392,7 @@ void HistoryService::createFromMtp(const MTPDmessageService &message) {
|
|||
if (auto dependent = GetDependentData()) {
|
||||
dependent->msgId = message.vreply_to_msg_id.v;
|
||||
if (!updateDependent() && App::api()) {
|
||||
App::api()->requestMessageData(history()->peer->asChannel(), dependent->msgId, std_::make_unique<HistoryDependentItemCallback>(fullId()));
|
||||
App::api()->requestMessageData(history()->peer->asChannel(), dependent->msgId, historyDependentItemCallback(fullId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -935,17 +935,6 @@ private:
|
|||
StylePtr _st;
|
||||
};
|
||||
|
||||
class HistoryDependentItemCallback : public SharedCallback<void, ChannelData*, MsgId> {
|
||||
public:
|
||||
HistoryDependentItemCallback(FullMsgId dependent) : _dependent(dependent) {
|
||||
}
|
||||
void call(ChannelData *channel, MsgId msgId) const override;
|
||||
|
||||
private:
|
||||
FullMsgId _dependent;
|
||||
|
||||
};
|
||||
|
||||
// any HistoryItem can have this Interface for
|
||||
// displaying the day mark above the message
|
||||
struct HistoryMessageDate : public BaseComponent<HistoryMessageDate> {
|
||||
|
|
|
@ -101,6 +101,14 @@ public:
|
|||
|
||||
constexpr int ScrollDateHideTimeout = 1000;
|
||||
|
||||
ApiWrap::RequestMessageDataCallback replyEditMessageDataCallback() {
|
||||
return [](ChannelData *channel, MsgId msgId) {
|
||||
if (App::main()) {
|
||||
App::main()->messageDataReceived(channel, msgId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html
|
||||
|
@ -1684,7 +1692,7 @@ void HistoryInner::toggleScrollDateShown() {
|
|||
_scrollDateShown = !_scrollDateShown;
|
||||
auto from = _scrollDateShown ? 0. : 1.;
|
||||
auto to = _scrollDateShown ? 1. : 0.;
|
||||
START_ANIMATION(_scrollDateOpacity, func(this, &HistoryInner::repaintScrollDateCallback), from, to, st::btnAttachEmoji.duration, anim::linear);
|
||||
_scrollDateOpacity.start([this] { repaintScrollDateCallback(); }, from, to, st::btnAttachEmoji.duration);
|
||||
}
|
||||
|
||||
void HistoryInner::repaintScrollDateCallback() {
|
||||
|
@ -4117,7 +4125,7 @@ void HistoryWidget::applyDraft(bool parseLinks) {
|
|||
if (_editMsgId || _replyToId) {
|
||||
updateReplyEditTexts();
|
||||
if (!_replyEditMsg && App::api()) {
|
||||
App::api()->requestMessageData(_peer->asChannel(), _editMsgId ? _editMsgId : _replyToId, std_::make_unique<ReplyEditMessageDataCallback>());
|
||||
App::api()->requestMessageData(_peer->asChannel(), _editMsgId ? _editMsgId : _replyToId, replyEditMessageDataCallback());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7633,7 +7641,7 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() {
|
|||
update();
|
||||
}
|
||||
if (!_pinnedBar->msg && App::api()) {
|
||||
App::api()->requestMessageData(_peer->asChannel(), _pinnedBar->msgId, std_::make_unique<ReplyEditMessageDataCallback>());
|
||||
App::api()->requestMessageData(_peer->asChannel(), _pinnedBar->msgId, replyEditMessageDataCallback());
|
||||
}
|
||||
} else if (_pinnedBar) {
|
||||
destroyPinnedBar();
|
||||
|
@ -7652,12 +7660,6 @@ void HistoryWidget::destroyPinnedBar() {
|
|||
_inPinnedMsg = false;
|
||||
}
|
||||
|
||||
void HistoryWidget::ReplyEditMessageDataCallback::call(ChannelData *channel, MsgId msgId) const {
|
||||
if (App::main()) {
|
||||
App::main()->messageDataReceived(channel, msgId);
|
||||
}
|
||||
}
|
||||
|
||||
bool HistoryWidget::sendExistingDocument(DocumentData *doc, const QString &caption) {
|
||||
if (!_history || !doc || !canSendMessages(_peer)) {
|
||||
return false;
|
||||
|
|
|
@ -908,11 +908,6 @@ private:
|
|||
void destroyPinnedBar();
|
||||
void unpinDone(const MTPUpdates &updates);
|
||||
|
||||
class ReplyEditMessageDataCallback : public SharedCallback<void, ChannelData*, MsgId> {
|
||||
public:
|
||||
void call(ChannelData *channel, MsgId msgId) const override;
|
||||
};
|
||||
|
||||
bool sendExistingDocument(DocumentData *doc, const QString &caption);
|
||||
void sendExistingPhoto(PhotoData *photo, const QString &caption);
|
||||
|
||||
|
|
|
@ -134,7 +134,9 @@ void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) cons
|
|||
bool loaded = document->loaded(), loading = document->loading(), displayLoading = document->displayLoading();
|
||||
if (loaded && !gif() && _gif != Media::Clip::BadReader) {
|
||||
Gif *that = const_cast<Gif*>(this);
|
||||
that->_gif = new Media::Clip::Reader(document->location(), document->data(), func(that, &Gif::clipCallback));
|
||||
that->_gif = new Media::Clip::Reader(document->location(), document->data(), [that](Media::Clip::Notification notification) {
|
||||
that->clipCallback(notification);
|
||||
});
|
||||
if (gif()) _gif->setAutoplay();
|
||||
}
|
||||
|
||||
|
@ -164,9 +166,9 @@ void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) cons
|
|||
}
|
||||
|
||||
if (radial || (!_gif && !loaded && !loading) || (_gif == Media::Clip::BadReader)) {
|
||||
float64 radialOpacity = (radial && loaded) ? _animation->radial.opacity() : 1;
|
||||
auto radialOpacity = (radial && loaded) ? _animation->radial.opacity() : 1.;
|
||||
if (_animation && _animation->_a_over.animating(context->ms)) {
|
||||
float64 over = _animation->_a_over.current();
|
||||
auto over = _animation->_a_over.current();
|
||||
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
|
||||
p.fillRect(r, st::black);
|
||||
} else {
|
||||
|
@ -218,7 +220,7 @@ void Gif::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
|||
bool wasactive = (_state & StateFlag::DeleteOver);
|
||||
if (active != wasactive) {
|
||||
auto from = active ? 0. : 1., to = active ? 1. : 0.;
|
||||
START_ANIMATION(_a_deleteOver, func(this, &Gif::update), from, to, st::stickersRowDuration, anim::linear);
|
||||
_a_deleteOver.start([this] { update(); }, from, to, st::stickersRowDuration);
|
||||
if (active) {
|
||||
_state |= StateFlag::DeleteOver;
|
||||
} else {
|
||||
|
@ -232,7 +234,7 @@ void Gif::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
|||
if (!getShownDocument()->loaded()) {
|
||||
ensureAnimation();
|
||||
auto from = active ? 0. : 1., to = active ? 1. : 0.;
|
||||
START_ANIMATION(_animation->_a_over, func(this, &Gif::update), from, to, st::stickersRowDuration, anim::linear);
|
||||
_animation->_a_over.start([this] { update(); }, from, to, st::stickersRowDuration);
|
||||
}
|
||||
if (active) {
|
||||
_state |= StateFlag::Over;
|
||||
|
@ -385,7 +387,7 @@ void Sticker::preload() const {
|
|||
void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
bool loaded = getShownDocument()->loaded();
|
||||
|
||||
float64 over = _a_over.isNull() ? (_active ? 1 : 0) : _a_over.current();
|
||||
auto over = _a_over.current(_active ? 1. : 0.);
|
||||
if (over > 0) {
|
||||
p.setOpacity(over);
|
||||
App::roundRect(p, QRect(QPoint(0, 0), st::stickerPanSize), st::emojiPanHover, StickerHoverCorners);
|
||||
|
@ -414,7 +416,7 @@ void Sticker::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
|||
_active = active;
|
||||
|
||||
auto from = active ? 0. : 1., to = active ? 1. : 0.;
|
||||
START_ANIMATION(_a_over, func(this, &Sticker::update), from, to, st::stickersRowDuration, anim::linear);
|
||||
_a_over.start([this] { update(); }, from, to, st::stickersRowDuration);
|
||||
}
|
||||
}
|
||||
ItemBase::clickHandlerActiveChanged(p, active);
|
||||
|
|
|
@ -638,7 +638,9 @@ QPixmap MediaPreviewWidget::currentImage() const {
|
|||
if (_document->loaded()) {
|
||||
if (!_gif && _gif != Media::Clip::BadReader) {
|
||||
auto that = const_cast<MediaPreviewWidget*>(this);
|
||||
that->_gif = new Media::Clip::Reader(_document->location(), _document->data(), func(that, &MediaPreviewWidget::clipCallback));
|
||||
that->_gif = new Media::Clip::Reader(_document->location(), _document->data(), [this, that](Media::Clip::Notification notification) {
|
||||
that->clipCallback(notification);
|
||||
});
|
||||
if (gif()) _gif->setAutoplay();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4020,7 +4020,7 @@ DataIsLoadedResult allDataLoadedForMessage(const MTPMessage &msg) {
|
|||
void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
||||
switch (updates.type()) {
|
||||
case mtpc_updates: {
|
||||
const auto &d(updates.c_updates());
|
||||
auto &d = updates.c_updates();
|
||||
if (d.vseq.v) {
|
||||
if (d.vseq.v <= updSeq) return;
|
||||
if (d.vseq.v > updSeq + 1) {
|
||||
|
@ -4037,7 +4037,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
} break;
|
||||
|
||||
case mtpc_updatesCombined: {
|
||||
const auto &d(updates.c_updatesCombined());
|
||||
auto &d = updates.c_updatesCombined();
|
||||
if (d.vseq_start.v) {
|
||||
if (d.vseq_start.v <= updSeq) return;
|
||||
if (d.vseq_start.v > updSeq + 1) {
|
||||
|
@ -4054,15 +4054,14 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
} break;
|
||||
|
||||
case mtpc_updateShort: {
|
||||
const auto &d(updates.c_updateShort());
|
||||
|
||||
auto &d = updates.c_updateShort();
|
||||
feedUpdate(d.vupdate);
|
||||
|
||||
updSetState(0, d.vdate.v, updQts, updSeq);
|
||||
} break;
|
||||
|
||||
case mtpc_updateShortMessage: {
|
||||
const auto &d(updates.c_updateShortMessage());
|
||||
auto &d = updates.c_updateShortMessage();
|
||||
if (!App::userLoaded(d.vuser_id.v)
|
||||
|| (d.has_via_bot_id() && !App::userLoaded(d.vvia_bot_id.v))
|
||||
|| (d.has_entities() && !mentionUsersLoaded(d.ventities))
|
||||
|
@ -4076,7 +4075,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
|
||||
// update before applying skipped
|
||||
MTPDmessage::Flags flags = mtpCastFlags(d.vflags.v) | MTPDmessage::Flag::f_from_id;
|
||||
HistoryItem *item = App::histories().addNewMessage(MTP_message(MTP_flags(flags), d.vid, d.is_out() ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(d.is_out() ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from, d.vvia_bot_id, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint(), MTPint()), NewMessageUnread);
|
||||
auto item = App::histories().addNewMessage(MTP_message(MTP_flags(flags), d.vid, d.is_out() ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(d.is_out() ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from, d.vvia_bot_id, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint(), MTPint()), NewMessageUnread);
|
||||
if (item) {
|
||||
_history->peerMessagesUpdated(item->history()->peer->id);
|
||||
}
|
||||
|
@ -4087,7 +4086,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
} break;
|
||||
|
||||
case mtpc_updateShortChatMessage: {
|
||||
const auto &d(updates.c_updateShortChatMessage());
|
||||
auto &d = updates.c_updateShortChatMessage();
|
||||
bool noFrom = !App::userLoaded(d.vfrom_id.v);
|
||||
if (!App::chatLoaded(d.vchat_id.v)
|
||||
|| noFrom
|
||||
|
@ -4104,7 +4103,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
|
||||
// update before applying skipped
|
||||
MTPDmessage::Flags flags = mtpCastFlags(d.vflags.v) | MTPDmessage::Flag::f_from_id;
|
||||
HistoryItem *item = App::histories().addNewMessage(MTP_message(MTP_flags(flags), d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from, d.vvia_bot_id, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint(), MTPint()), NewMessageUnread);
|
||||
auto item = App::histories().addNewMessage(MTP_message(MTP_flags(flags), d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from, d.vvia_bot_id, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint(), MTPint()), NewMessageUnread);
|
||||
if (item) {
|
||||
_history->peerMessagesUpdated(item->history()->peer->id);
|
||||
}
|
||||
|
@ -4115,7 +4114,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
} break;
|
||||
|
||||
case mtpc_updateShortSentMessage: {
|
||||
const auto &d(updates.c_updateShortSentMessage());
|
||||
auto &d = updates.c_updateShortSentMessage();
|
||||
if (randomId) {
|
||||
PeerId peerId = 0;
|
||||
QString text;
|
||||
|
@ -4125,7 +4124,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
if (peerId) {
|
||||
if (auto item = App::histItemById(peerToChannel(peerId), d.vid.v)) {
|
||||
if (d.has_entities() && !mentionUsersLoaded(d.ventities)) {
|
||||
api()->requestMessageData(item->history()->peer->asChannel(), item->id, nullptr);
|
||||
api()->requestMessageData(item->history()->peer->asChannel(), item->id, ApiWrap::RequestMessageDataCallback());
|
||||
}
|
||||
auto entities = d.has_entities() ? entitiesFromMTP(d.ventities.c_vector().v) : EntitiesInText();
|
||||
item->setText({ text, entities });
|
||||
|
|
|
@ -180,8 +180,8 @@ void Reader::moveToNextWrite() const {
|
|||
|
||||
void Reader::callback(Reader *reader, int32 threadIndex, Notification notification) {
|
||||
// check if reader is not deleted already
|
||||
if (managers.size() > threadIndex && managers.at(threadIndex)->carries(reader)) {
|
||||
reader->_callback.call(notification);
|
||||
if (managers.size() > threadIndex && managers.at(threadIndex)->carries(reader) && reader->_callback) {
|
||||
reader->_callback(notification);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ enum ReaderSteps {
|
|||
class ReaderPrivate;
|
||||
class Reader {
|
||||
public:
|
||||
using Callback = Function<void, Notification>;
|
||||
using Callback = base::lambda_unique<void(Notification)>;
|
||||
enum class Mode {
|
||||
Gif,
|
||||
Video,
|
||||
|
|
|
@ -41,8 +41,8 @@ Controller::Controller(QWidget *parent) : TWidget(parent)
|
|||
, _toPlayLeft(this, st::mediaviewPlayProgressLabel)
|
||||
, _fadeAnimation(std_::make_unique<Ui::FadeAnimation>(this)) {
|
||||
_fadeAnimation->show();
|
||||
_fadeAnimation->setFinishedCallback(func(this, &Controller::fadeFinished));
|
||||
_fadeAnimation->setUpdatedCallback(func(this, &Controller::fadeUpdated));
|
||||
_fadeAnimation->setFinishedCallback([this] { fadeFinished(); });
|
||||
_fadeAnimation->setUpdatedCallback([this](float64 opacity) { fadeUpdated(opacity); });
|
||||
|
||||
_volumeController->setVolume(Global::VideoVolume());
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ void Playback::setOver(bool over) {
|
|||
|
||||
_over = over;
|
||||
auto from = _over ? 0. : 1., to = _over ? 1. : 0.;
|
||||
START_ANIMATION(_a_over, func(this, &Playback::updateCallback), from, to, st::mediaviewOverDuration, anim::linear);
|
||||
_a_over.start([this] { update(); }, from, to, st::mediaviewOverDuration);
|
||||
}
|
||||
|
||||
} // namespace Clip
|
||||
|
|
|
@ -48,9 +48,6 @@ protected:
|
|||
|
||||
private:
|
||||
void step_progress(float64 ms, bool timer);
|
||||
void updateCallback() {
|
||||
update();
|
||||
}
|
||||
void setOver(bool over);
|
||||
|
||||
bool _over = false;
|
||||
|
|
|
@ -100,7 +100,7 @@ void VolumeController::setOver(bool over) {
|
|||
|
||||
_over = over;
|
||||
auto from = _over ? 0. : 1., to = _over ? 1. : 0.;
|
||||
START_ANIMATION(_a_over, func(this, &VolumeController::updateCallback), from, to, st::mediaviewOverDuration, anim::linear);
|
||||
_a_over.start([this] { update(); }, from, to, st::mediaviewOverDuration);
|
||||
}
|
||||
|
||||
} // namespace Clip
|
||||
|
|
|
@ -43,9 +43,6 @@ protected:
|
|||
void leaveEvent(QEvent *e) override;
|
||||
|
||||
private:
|
||||
void updateCallback() {
|
||||
update();
|
||||
}
|
||||
void setOver(bool over);
|
||||
void changeVolume(float64 newVolume);
|
||||
|
||||
|
|
|
@ -1368,7 +1368,9 @@ void MediaView::createClipReader() {
|
|||
_current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), ImagePixSmooth | ImagePixBlurred, st::mvDocIconSize, st::mvDocIconSize);
|
||||
}
|
||||
auto mode = _doc->isVideo() ? Media::Clip::Reader::Mode::Video : Media::Clip::Reader::Mode::Gif;
|
||||
_gif = std_::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), func(this, &MediaView::clipCallback), mode);
|
||||
_gif = std_::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), [this](Media::Clip::Notification notification) {
|
||||
clipCallback(notification);
|
||||
}, mode);
|
||||
|
||||
// Correct values will be set when gif gets inited.
|
||||
_videoPaused = _videoIsSilent = _videoStopped = false;
|
||||
|
@ -1439,7 +1441,9 @@ void MediaView::restartVideoAtSeekPosition(int64 positionMs) {
|
|||
if (_current.isNull()) {
|
||||
_current = _gif->current(_gif->width(), _gif->height(), _gif->width(), _gif->height(), getms());
|
||||
}
|
||||
_gif = std_::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), func(this, &MediaView::clipCallback), Media::Clip::Reader::Mode::Video, positionMs);
|
||||
_gif = std_::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), [this](Media::Clip::Notification notification) {
|
||||
clipCallback(notification);
|
||||
}, Media::Clip::Reader::Mode::Video, positionMs);
|
||||
|
||||
// Correct values will be set when gif gets inited.
|
||||
_videoPaused = _videoIsSilent = _videoStopped = false;
|
||||
|
|
|
@ -396,9 +396,10 @@ void reinitWebLoadManager();
|
|||
void stopWebLoadManager();
|
||||
|
||||
namespace FileDownload {
|
||||
|
||||
namespace internal {
|
||||
|
||||
using ImageLoadedHandler = Function<void>;
|
||||
using ImageLoadedHandler = base::lambda_unique<void()>;
|
||||
Notify::ConnectionId plainRegisterImageLoadedObserver(ImageLoadedHandler &&handler);
|
||||
|
||||
void notifyImageLoaded();
|
||||
|
@ -407,7 +408,9 @@ void notifyImageLoaded();
|
|||
|
||||
template <typename ObserverType>
|
||||
void registerImageLoadedObserver(ObserverType *observer, void (ObserverType::*handler)()) {
|
||||
auto connection = internal::plainRegisterImageLoadedObserver(func(observer, handler));
|
||||
auto connection = internal::plainRegisterImageLoadedObserver([observer, handler]() {
|
||||
(observer->*handler)();
|
||||
});
|
||||
Notify::observerRegistered(observer, connection);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,14 +91,16 @@ void peerUpdatedSendDelayed();
|
|||
|
||||
namespace internal {
|
||||
|
||||
using PeerUpdateHandler = Function<void, const PeerUpdate&>;
|
||||
using PeerUpdateHandler = base::lambda_unique<void(const PeerUpdate&)>;
|
||||
ConnectionId plainRegisterPeerObserver(PeerUpdate::Flags events, PeerUpdateHandler &&handler);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename ObserverType>
|
||||
void registerPeerObserver(PeerUpdate::Flags events, ObserverType *observer, void (ObserverType::*handler)(const PeerUpdate &)) {
|
||||
auto connection = internal::plainRegisterPeerObserver(events, func(observer, handler));
|
||||
auto connection = internal::plainRegisterPeerObserver(events, [observer, handler](const PeerUpdate &update) {
|
||||
(observer->*handler)(update);
|
||||
});
|
||||
observerRegistered(observer, connection);
|
||||
}
|
||||
|
||||
|
|
|
@ -285,7 +285,7 @@ void CoverWidget::dragEnterEvent(QDragEnterEvent *e) {
|
|||
|
||||
void CoverWidget::dragLeaveEvent(QDragLeaveEvent *e) {
|
||||
if (_dropArea && !_dropArea->hiding()) {
|
||||
_dropArea->hideAnimated(func(this, &CoverWidget::dropAreaHidden));
|
||||
_dropArea->hideAnimated([this](CoverDropArea *area) { dropAreaHidden(area); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,7 +306,7 @@ void CoverWidget::dropEvent(QDropEvent *e) {
|
|||
}
|
||||
|
||||
if (!_dropArea->hiding()) {
|
||||
_dropArea->hideAnimated(func(this, &CoverWidget::dropAreaHidden));
|
||||
_dropArea->hideAnimated([this](CoverDropArea *area) { dropAreaHidden(area); });
|
||||
}
|
||||
e->acceptProposedAction();
|
||||
|
||||
|
|
|
@ -57,7 +57,9 @@ void CoverDropArea::paintEvent(QPaintEvent *e) {
|
|||
_cache = QPixmap();
|
||||
if (_hiding) {
|
||||
hide();
|
||||
_hideFinishCallback.call(this);
|
||||
if (_hideFinishCallback) {
|
||||
_hideFinishCallback(this);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +95,7 @@ void CoverDropArea::setupAnimation() {
|
|||
_cache = myGrab(this);
|
||||
}
|
||||
auto from = _hiding ? 1. : 0., to = _hiding ? 0. : 1.;
|
||||
START_ANIMATION(_a_appearance, func(this, &CoverDropArea::refreshCallback), from, to, st::profileDropAreaDuration, anim::linear);
|
||||
_a_appearance.start([this]() { update(); }, from, to, st::profileDropAreaDuration);
|
||||
}
|
||||
|
||||
} // namespace Profile
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
|
||||
void showAnimated();
|
||||
|
||||
using HideFinishCallback = Function<void, CoverDropArea*>;
|
||||
using HideFinishCallback = base::lambda_unique<void(CoverDropArea*)>;
|
||||
void hideAnimated(HideFinishCallback &&callback);
|
||||
|
||||
bool hiding() const {
|
||||
|
@ -39,9 +39,6 @@ protected:
|
|||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
void refreshCallback() {
|
||||
update();
|
||||
}
|
||||
void setupAnimation();
|
||||
|
||||
QString _title, _subtitle;
|
||||
|
|
|
@ -149,15 +149,13 @@ void InfoWidget::refreshAbout() {
|
|||
textParseEntities(aboutText, TextParseLinks | TextParseMentions | TextParseHashtags | TextParseBotCommands, &aboutEntities);
|
||||
_about->setMarkedText({ aboutText, aboutEntities });
|
||||
_about->setSelectable(true);
|
||||
_about->setClickHandlerHook(func(this, &InfoWidget::aboutClickHandlerHook));
|
||||
_about->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) {
|
||||
BotCommandClickHandler::setPeerForCommand(peer());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool InfoWidget::aboutClickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button) {
|
||||
BotCommandClickHandler::setPeerForCommand(peer());
|
||||
return true;
|
||||
}
|
||||
|
||||
void InfoWidget::refreshMobileNumber() {
|
||||
TextWithEntities phoneText;
|
||||
if (auto user = peer()->asUser()) {
|
||||
|
|
|
@ -51,8 +51,6 @@ private:
|
|||
void refreshChannelLink();
|
||||
void refreshVisibility();
|
||||
|
||||
bool aboutClickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button);
|
||||
|
||||
// labelWidget may be nullptr.
|
||||
void setLabeledText(ChildWidget<FlatLabel> *labelWidget, const QString &label,
|
||||
ChildWidget<FlatLabel> *textWidget, const TextWithEntities &textWithEntities, const QString ©Text);
|
||||
|
|
|
@ -99,19 +99,17 @@ void InviteLinkWidget::refreshLink() {
|
|||
_link->setMarkedText(linkData);
|
||||
_link->setSelectable(true);
|
||||
_link->setContextCopyText(QString());
|
||||
_link->setClickHandlerHook(func(this, &InviteLinkWidget::clickHandlerHook));
|
||||
}
|
||||
}
|
||||
_link->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) {
|
||||
auto link = getInviteLink();
|
||||
if (link.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InviteLinkWidget::clickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button) {
|
||||
auto link = getInviteLink();
|
||||
if (link.isEmpty()) {
|
||||
return true;
|
||||
QApplication::clipboard()->setText(link);
|
||||
Ui::showLayer(new InformBox(lang(lng_group_invite_copied)));
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
QApplication::clipboard()->setText(link);
|
||||
Ui::showLayer(new InformBox(lang(lng_group_invite_copied)));
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Profile
|
||||
|
|
|
@ -46,8 +46,6 @@ private:
|
|||
void refreshLink();
|
||||
void refreshVisibility();
|
||||
|
||||
bool clickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button);
|
||||
|
||||
ChildWidget<FlatLabel> _link = { nullptr };
|
||||
|
||||
};
|
||||
|
|
|
@ -315,17 +315,15 @@ void MembersWidget::refreshLimitReached() {
|
|||
QString link = textRichPrepare(lang(lng_profile_migrate_learn_more));
|
||||
QString text = qsl("%1%2%3\n%4 [a href=\"https://telegram.org/blog/supergroups5k\"]%5[/a]").arg(textcmdStartSemibold()).arg(title).arg(textcmdStopSemibold()).arg(body).arg(link);
|
||||
_limitReachedInfo->setRichText(text);
|
||||
_limitReachedInfo->setClickHandlerHook(func(this, &MembersWidget::limitReachedHook));
|
||||
_limitReachedInfo->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) {
|
||||
Ui::showLayer(new ConvertToSupergroupBox(peer()->asChat()));
|
||||
return false;
|
||||
});
|
||||
} else if (!limitReachedShown && _limitReachedInfo) {
|
||||
_limitReachedInfo.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
bool MembersWidget::limitReachedHook(const ClickHandlerPtr &handler, Qt::MouseButton button) {
|
||||
Ui::showLayer(new ConvertToSupergroupBox(peer()->asChat()));
|
||||
return false;
|
||||
}
|
||||
|
||||
void MembersWidget::checkSelfAdmin(ChatData *chat) {
|
||||
if (chat->participants.isEmpty()) return;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ void UserpicButton::showFinished() {
|
|||
_notShownYet = false;
|
||||
if (!_waiting) {
|
||||
_a_appearance.finish();
|
||||
START_ANIMATION(_a_appearance, func(this, &UserpicButton::refreshCallback), 0, 1, st::profilePhotoDuration, anim::linear);
|
||||
_a_appearance.start([this] { update(); }, 0, 1, st::profilePhotoDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ void UserpicButton::startNewPhotoShowing() {
|
|||
}
|
||||
|
||||
_a_appearance.finish();
|
||||
START_ANIMATION(_a_appearance, func(this, &UserpicButton::refreshCallback), 0, 1, st::profilePhotoDuration, anim::linear);
|
||||
_a_appearance.start([this] { update(); }, 0, 1, st::profilePhotoDuration);
|
||||
update();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,10 +43,6 @@ private:
|
|||
void notifyPeerUpdated(const Notify::PeerUpdate &update);
|
||||
void notifyImageLoaded();
|
||||
|
||||
void refreshCallback() {
|
||||
update();
|
||||
}
|
||||
|
||||
void processPeerPhoto();
|
||||
void processNewPeerPhoto();
|
||||
void startNewPhotoShowing();
|
||||
|
|
|
@ -217,7 +217,7 @@ void CoverWidget::dragEnterEvent(QDragEnterEvent *e) {
|
|||
|
||||
void CoverWidget::dragLeaveEvent(QDragLeaveEvent *e) {
|
||||
if (_dropArea && !_dropArea->hiding()) {
|
||||
_dropArea->hideAnimated(func(this, &CoverWidget::dropAreaHidden));
|
||||
_dropArea->hideAnimated([this](Profile::CoverDropArea *area) { dropAreaHidden(area); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,7 @@ void CoverWidget::dropEvent(QDropEvent *e) {
|
|||
if (mimeData->hasImage()) {
|
||||
img = qvariant_cast<QImage>(mimeData->imageData());
|
||||
} else {
|
||||
const auto &urls = mimeData->urls();
|
||||
auto &urls = mimeData->urls();
|
||||
if (urls.size() == 1) {
|
||||
auto &url = urls.at(0);
|
||||
if (url.isLocalFile()) {
|
||||
|
@ -238,7 +238,7 @@ void CoverWidget::dropEvent(QDropEvent *e) {
|
|||
}
|
||||
|
||||
if (!_dropArea->hiding()) {
|
||||
_dropArea->hideAnimated(func(this, &CoverWidget::dropAreaHidden));
|
||||
_dropArea->hideAnimated([this](Profile::CoverDropArea *area) { dropAreaHidden(area); });
|
||||
}
|
||||
e->acceptProposedAction();
|
||||
|
||||
|
|
|
@ -81,7 +81,10 @@ void InfoWidget::refreshUsername() {
|
|||
usernameText.entities.push_back(EntityInText(EntityInTextCustomUrl, 0, usernameText.text.size(), qsl("https://telegram.me/") + self()->username));
|
||||
setLabeledText(_username, lang(lng_profile_username), usernameText, TextWithEntities(), copyText);
|
||||
if (auto text = _username->entity()->textLabel()) {
|
||||
text->setClickHandlerHook(func(this, &InfoWidget::usernameClickHandlerHook));
|
||||
text->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) {
|
||||
Ui::showLayer(new UsernameBox());
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,19 +99,20 @@ void InfoWidget::refreshLink() {
|
|||
}
|
||||
setLabeledText(_link, lang(lng_profile_link), linkText, linkTextShort, QString());
|
||||
if (auto text = _link->entity()->textLabel()) {
|
||||
text->setClickHandlerHook(func(this, &InfoWidget::usernameClickHandlerHook));
|
||||
text->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) {
|
||||
Ui::showLayer(new UsernameBox());
|
||||
return false;
|
||||
});
|
||||
}
|
||||
if (auto shortText = _link->entity()->shortTextLabel()) {
|
||||
shortText->setExpandLinksMode(ExpandLinksUrlOnly);
|
||||
shortText->setClickHandlerHook(func(this, &InfoWidget::usernameClickHandlerHook));
|
||||
shortText->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) {
|
||||
Ui::showLayer(new UsernameBox());
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool InfoWidget::usernameClickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button) {
|
||||
Ui::showLayer(new UsernameBox());
|
||||
return false;
|
||||
}
|
||||
|
||||
void InfoWidget::setLabeledText(ChildWidget<LabeledWrap> &row, const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString ©Text) {
|
||||
if (textWithEntities.text.isEmpty()) {
|
||||
row->slideUp();
|
||||
|
|
|
@ -38,8 +38,6 @@ private:
|
|||
// Observed notifications.
|
||||
void notifyPeerUpdated(const Notify::PeerUpdate &update);
|
||||
|
||||
bool usernameClickHandlerHook(const ClickHandlerPtr &handler, Qt::MouseButton button);
|
||||
|
||||
void createControls();
|
||||
void refreshControls();
|
||||
void refreshMobileNumber();
|
||||
|
|
|
@ -120,7 +120,7 @@ AnimationManager::AnimationManager() : _timer(this), _iterating(false) {
|
|||
|
||||
void AnimationManager::start(Animation *obj) {
|
||||
if (_iterating) {
|
||||
_starting.insert(obj, NullType());
|
||||
_starting.insert(obj);
|
||||
if (!_stopping.isEmpty()) {
|
||||
_stopping.remove(obj);
|
||||
}
|
||||
|
@ -128,21 +128,21 @@ void AnimationManager::start(Animation *obj) {
|
|||
if (_objects.isEmpty()) {
|
||||
_timer.start(AnimationTimerDelta);
|
||||
}
|
||||
_objects.insert(obj, NullType());
|
||||
_objects.insert(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationManager::stop(Animation *obj) {
|
||||
if (_iterating) {
|
||||
_stopping.insert(obj, NullType());
|
||||
_stopping.insert(obj);
|
||||
if (!_starting.isEmpty()) {
|
||||
_starting.remove(obj);
|
||||
}
|
||||
} else {
|
||||
AnimatingObjects::iterator i = _objects.find(obj);
|
||||
auto i = _objects.find(obj);
|
||||
if (i != _objects.cend()) {
|
||||
_objects.erase(i);
|
||||
if (_objects.isEmpty()) {
|
||||
if (_objects.empty()) {
|
||||
_timer.stop();
|
||||
}
|
||||
}
|
||||
|
@ -152,26 +152,26 @@ void AnimationManager::stop(Animation *obj) {
|
|||
void AnimationManager::timeout() {
|
||||
_iterating = true;
|
||||
uint64 ms = getms();
|
||||
for (AnimatingObjects::const_iterator i = _objects.begin(), e = _objects.end(); i != e; ++i) {
|
||||
if (!_stopping.contains(i.key())) {
|
||||
i.key()->step(ms, true);
|
||||
for_const (auto object, _objects) {
|
||||
if (!_stopping.contains(object)) {
|
||||
object->step(ms, true);
|
||||
}
|
||||
}
|
||||
_iterating = false;
|
||||
|
||||
if (!_starting.isEmpty()) {
|
||||
for (AnimatingObjects::iterator i = _starting.begin(), e = _starting.end(); i != e; ++i) {
|
||||
_objects.insert(i.key(), NullType());
|
||||
for_const (auto object, _starting) {
|
||||
_objects.insert(object);
|
||||
}
|
||||
_starting.clear();
|
||||
}
|
||||
if (!_stopping.isEmpty()) {
|
||||
for (AnimatingObjects::iterator i = _stopping.begin(), e = _stopping.end(); i != e; ++i) {
|
||||
_objects.remove(i.key());
|
||||
for_const (auto object, _stopping) {
|
||||
_objects.remove(object);
|
||||
}
|
||||
_stopping.clear();
|
||||
}
|
||||
if (!_objects.size()) {
|
||||
if (_objects.empty()) {
|
||||
_timer.stop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#include "core/basic_types.h"
|
||||
#include "core/lambda_wrap.h"
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QColor>
|
||||
|
||||
|
@ -57,6 +58,7 @@ namespace anim {
|
|||
|
||||
class fvalue { // float animated value
|
||||
public:
|
||||
using ValueType = float64;
|
||||
|
||||
fvalue() {
|
||||
}
|
||||
|
@ -88,15 +90,14 @@ namespace anim {
|
|||
_delta = 0;
|
||||
}
|
||||
|
||||
typedef float64 Type;
|
||||
|
||||
private:
|
||||
|
||||
float64 _cur, _from, _delta;
|
||||
|
||||
};
|
||||
|
||||
class ivalue { // int animated value
|
||||
public:
|
||||
using ValueType = int32;
|
||||
|
||||
ivalue() {
|
||||
}
|
||||
|
@ -128,16 +129,15 @@ namespace anim {
|
|||
_delta = 0;
|
||||
}
|
||||
|
||||
typedef int32 Type;
|
||||
|
||||
private:
|
||||
|
||||
int32 _cur;
|
||||
float64 _from, _delta;
|
||||
|
||||
};
|
||||
|
||||
class cvalue { // QColor animated value
|
||||
public:
|
||||
using ValueType = QColor;
|
||||
|
||||
cvalue() {
|
||||
}
|
||||
|
@ -199,12 +199,10 @@ namespace anim {
|
|||
_delta_r = _delta_g = _delta_b = _delta_a = 0;
|
||||
}
|
||||
|
||||
typedef QColor Type;
|
||||
|
||||
private:
|
||||
|
||||
QColor _cur;
|
||||
float64 _from_r, _from_g, _from_b, _from_a, _delta_r, _delta_g, _delta_b, _delta_a;
|
||||
|
||||
};
|
||||
|
||||
void startManager();
|
||||
|
@ -380,105 +378,81 @@ AnimationCallbacks animation(Param param, Type *obj, typename AnimationCallbacks
|
|||
template <typename AnimType>
|
||||
class SimpleAnimation {
|
||||
public:
|
||||
using Callback = Function<void>;
|
||||
using ValueType = typename AnimType::ValueType;
|
||||
using Callback = base::lambda_unique<void()>;
|
||||
|
||||
SimpleAnimation() {
|
||||
bool animating() const {
|
||||
if (_data) {
|
||||
if (_data->a_animation.animating()) {
|
||||
return true;
|
||||
}
|
||||
_data.reset();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool animating(uint64 ms) {
|
||||
if (_data && _data->_a.animating()) {
|
||||
_data->_a.step(ms);
|
||||
return _data && _data->_a.animating();
|
||||
if (animating()) {
|
||||
_data->a_animation.step(ms);
|
||||
return animating();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return !_data;
|
||||
ValueType current() const {
|
||||
t_assert(_data != nullptr);
|
||||
return _data->value.current();
|
||||
}
|
||||
|
||||
typename AnimType::Type current() {
|
||||
return _data ? _data->a.current() : typename AnimType::Type();
|
||||
ValueType current(const ValueType &def) const {
|
||||
return _data ? current() : def;
|
||||
}
|
||||
|
||||
typename AnimType::Type current(const typename AnimType::Type &def) {
|
||||
return _data ? _data->a.current() : def;
|
||||
}
|
||||
|
||||
typename AnimType::Type current(uint64 ms, const typename AnimType::Type &def) {
|
||||
ValueType current(uint64 ms, const ValueType &def) {
|
||||
return animating(ms) ? current() : def;
|
||||
}
|
||||
|
||||
void setup(const typename AnimType::Type &from, Callback &&update) {
|
||||
template <typename Lambda>
|
||||
void start(Lambda &&updateCallback, const ValueType &from, const ValueType &to, float64 duration, anim::transition transition = anim::linear) {
|
||||
if (!_data) {
|
||||
_data = new Data(from, std_::move(update), animation(this, &SimpleAnimation<AnimType>::step));
|
||||
} else {
|
||||
_data->a = AnimType(from, from);
|
||||
}
|
||||
}
|
||||
|
||||
void start(const typename AnimType::Type &to, float64 duration, anim::transition transition = anim::linear) {
|
||||
if (_data) {
|
||||
_data->a.start(to);
|
||||
_data->_a.start();
|
||||
_data->duration = duration;
|
||||
_data->transition = transition;
|
||||
_data = std_::make_unique<Data>(from, std_::move(updateCallback));
|
||||
}
|
||||
_data->value.start(to);
|
||||
_data->duration = duration;
|
||||
_data->transition = transition;
|
||||
_data->a_animation.start();
|
||||
}
|
||||
|
||||
void finish() {
|
||||
if (isNull()) {
|
||||
return;
|
||||
if (_data) {
|
||||
_data->value.finish();
|
||||
_data->a_animation.stop();
|
||||
_data.reset();
|
||||
}
|
||||
|
||||
_data->a.finish();
|
||||
_data->_a.stop();
|
||||
delete _data;
|
||||
_data = nullptr;
|
||||
}
|
||||
|
||||
~SimpleAnimation() {
|
||||
deleteAndMark(_data);
|
||||
}
|
||||
|
||||
private:
|
||||
struct Data {
|
||||
Data(const typename AnimType::Type &from, Callback &&update, AnimationCallbacks &&acb)
|
||||
: a(from, from)
|
||||
, _a(std_::move(acb))
|
||||
, update(std_::move(update))
|
||||
, duration(0)
|
||||
, transition(anim::linear) {
|
||||
Data(const ValueType &from, Callback &&updateCallback)
|
||||
: value(from, from)
|
||||
, a_animation(animation(this, &Data::step))
|
||||
, updateCallback(std_::move(updateCallback)) {
|
||||
}
|
||||
AnimType a;
|
||||
Animation _a;
|
||||
Callback update;
|
||||
float64 duration;
|
||||
anim::transition transition;
|
||||
void step(float64 ms, bool timer) {
|
||||
auto dt = (ms >= duration) ? 1. : (ms / duration);
|
||||
if (dt >= 1) {
|
||||
value.finish();
|
||||
a_animation.stop();
|
||||
} else {
|
||||
value.update(dt, transition);
|
||||
}
|
||||
updateCallback();
|
||||
}
|
||||
|
||||
AnimType value;
|
||||
Animation a_animation;
|
||||
Callback updateCallback;
|
||||
float64 duration = 0.;
|
||||
anim::transition transition = anim::linear;
|
||||
};
|
||||
Data *_data = nullptr;
|
||||
|
||||
void step(float64 ms, bool timer) {
|
||||
float64 dt = (ms >= _data->duration) ? 1 : (ms / _data->duration);
|
||||
if (dt >= 1) {
|
||||
_data->a.finish();
|
||||
_data->_a.stop();
|
||||
} else {
|
||||
_data->a.update(dt, _data->transition);
|
||||
}
|
||||
|
||||
Callback callbackCache, *toCall = &_data->update;
|
||||
if (!_data->_a.animating()) {
|
||||
callbackCache = std_::move(_data->update);
|
||||
toCall = &callbackCache;
|
||||
|
||||
delete _data;
|
||||
_data = nullptr;
|
||||
}
|
||||
if (timer) {
|
||||
toCall->call();
|
||||
}
|
||||
}
|
||||
mutable std_::unique_ptr<Data> _data;
|
||||
|
||||
};
|
||||
|
||||
|
@ -486,18 +460,8 @@ using FloatAnimation = SimpleAnimation<anim::fvalue>;
|
|||
using IntAnimation = SimpleAnimation<anim::ivalue>;
|
||||
using ColorAnimation = SimpleAnimation<anim::cvalue>;
|
||||
|
||||
// Macro allows us to lazily create updateCallback.
|
||||
#define ENSURE_ANIMATION(animation, updateCallback, from) \
|
||||
if ((animation).isNull()) { \
|
||||
(animation).setup((from), (updateCallback)); \
|
||||
}
|
||||
|
||||
#define START_ANIMATION(animation, updateCallback, from, to, duration, transition) \
|
||||
ENSURE_ANIMATION(animation, updateCallback, from); \
|
||||
(animation).start((to), (duration), (transition))
|
||||
|
||||
class AnimationManager : public QObject {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AnimationManager();
|
||||
|
@ -511,7 +475,7 @@ public slots:
|
|||
void clipCallback(Media::Clip::Reader *reader, qint32 threadIndex, qint32 notification);
|
||||
|
||||
private:
|
||||
typedef QMap<Animation*, NullType> AnimatingObjects;
|
||||
using AnimatingObjects = OrderedSet<Animation*>;
|
||||
AnimatingObjects _objects, _starting, _stopping;
|
||||
QTimer _timer;
|
||||
bool _iterating;
|
||||
|
|
|
@ -118,7 +118,7 @@ void HistoryDownButton::hideAnimated() {
|
|||
void HistoryDownButton::toggleAnimated() {
|
||||
_shown = !_shown;
|
||||
float64 from = _shown ? 0. : 1., to = _shown ? 1. : 0.;
|
||||
START_ANIMATION(_a_show, func(this, &HistoryDownButton::repaintCallback), from, to, st::btnAttachEmoji.duration, anim::linear);
|
||||
_a_show.start([this] { update(); }, from, to, st::btnAttachEmoji.duration);
|
||||
}
|
||||
|
||||
void HistoryDownButton::finishAnimation() {
|
||||
|
|
|
@ -47,9 +47,6 @@ protected:
|
|||
|
||||
private:
|
||||
void toggleAnimated();
|
||||
void repaintCallback() {
|
||||
update();
|
||||
}
|
||||
void step_arrowOver(float64 ms, bool timer);
|
||||
|
||||
QPixmap _cache;
|
||||
|
|
|
@ -49,7 +49,7 @@ void IconButton::onStateChanged(int oldState, ButtonStateChangeSource source) {
|
|||
if (over != (oldState & StateOver)) {
|
||||
auto from = over ? 0. : 1.;
|
||||
auto to = over ? 1. : 0.;
|
||||
START_ANIMATION(_a_over, func(this, &IconButton::updateCallback), from, to, _st.duration, anim::linear);
|
||||
_a_over.start([this] { update(); }, from, to, _st.duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,6 @@ protected:
|
|||
void onStateChanged(int oldState, ButtonStateChangeSource source) override;
|
||||
|
||||
private:
|
||||
void updateCallback() {
|
||||
update();
|
||||
}
|
||||
|
||||
const style::IconButton &_st;
|
||||
const style::icon *_iconOverride = nullptr;
|
||||
|
||||
|
|
|
@ -65,7 +65,9 @@ void FadeAnimation::stopAnimation() {
|
|||
_cache = QPixmap();
|
||||
updateCallback();
|
||||
_widget->showChildren();
|
||||
_finishedCallback.call();
|
||||
if (_finishedCallback) {
|
||||
_finishedCallback();
|
||||
}
|
||||
}
|
||||
if (_visible == _widget->isHidden()) {
|
||||
_widget->setVisible(_visible);
|
||||
|
@ -91,7 +93,9 @@ void FadeAnimation::startAnimation(int duration) {
|
|||
_cache = myGrab(_widget);
|
||||
_widget->hideChildren();
|
||||
}
|
||||
START_ANIMATION(_animation, func(this, &FadeAnimation::updateCallback), _visible ? 0. : 1., _visible ? 1. : 0., duration, anim::linear);
|
||||
auto from = _visible ? 0. : 1.;
|
||||
auto to = _visible ? 1. : 0.;
|
||||
_animation.start([this]() { updateCallback(); }, from, to, duration);
|
||||
updateCallback();
|
||||
if (_widget->isHidden()) {
|
||||
_widget->show();
|
||||
|
@ -101,7 +105,9 @@ void FadeAnimation::startAnimation(int duration) {
|
|||
void FadeAnimation::updateCallback() {
|
||||
if (_animation.animating(getms())) {
|
||||
_widget->update();
|
||||
_updatedCallback.call(_animation.current());
|
||||
if (_updatedCallback) {
|
||||
_updatedCallback(_animation.current(_visible ? 1. : 0.));
|
||||
}
|
||||
} else {
|
||||
stopAnimation();
|
||||
}
|
||||
|
|
|
@ -31,10 +31,10 @@ public:
|
|||
bool paint(Painter &p);
|
||||
void refreshCache();
|
||||
|
||||
using FinishedCallback = Function<void>;
|
||||
using FinishedCallback = base::lambda_unique<void()>;
|
||||
void setFinishedCallback(FinishedCallback &&callback);
|
||||
|
||||
using UpdatedCallback = Function<void, float64>;
|
||||
using UpdatedCallback = base::lambda_unique<void(float64)>;
|
||||
void setUpdatedCallback(UpdatedCallback &&callback);
|
||||
|
||||
void show();
|
||||
|
|
|
@ -65,14 +65,16 @@ bool processQuery();
|
|||
|
||||
namespace internal {
|
||||
|
||||
using QueryUpdateHandler = Function<void, const QueryUpdate&>;
|
||||
using QueryUpdateHandler = base::lambda_unique<void(const QueryUpdate&)>;
|
||||
Notify::ConnectionId plainRegisterObserver(QueryUpdateHandler &&handler);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename ObserverType>
|
||||
void registerObserver(ObserverType *observer, void (ObserverType::*handler)(const QueryUpdate &)) {
|
||||
auto connection = internal::plainRegisterObserver(func(observer, handler));
|
||||
auto connection = internal::plainRegisterObserver([observer, handler](const QueryUpdate &update) {
|
||||
(observer->*handler)(update);
|
||||
});
|
||||
Notify::observerRegistered(observer, connection);
|
||||
}
|
||||
|
||||
|
|
|
@ -332,7 +332,7 @@ void EmojiButton::setLoading(bool loading) {
|
|||
if (_loading != loading) {
|
||||
_loading = loading;
|
||||
auto from = loading ? 0. : 1., to = loading ? 1. : 0.;
|
||||
START_ANIMATION(a_loading, func(this, &EmojiButton::updateCallback), from, to, st::emojiCircleDuration, anim::linear);
|
||||
a_loading.start([this] { update(); }, from, to, st::emojiCircleDuration);
|
||||
if (loading) {
|
||||
_a_loading.start();
|
||||
} else {
|
||||
|
|
|
@ -147,12 +147,9 @@ private:
|
|||
|
||||
void step_loading(uint64 ms, bool timer) {
|
||||
if (timer) {
|
||||
updateCallback();
|
||||
update();
|
||||
}
|
||||
}
|
||||
void updateCallback() {
|
||||
update();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@ Text::StateResult FlatLabel::dragActionFinish(const QPoint &p, Qt::MouseButton b
|
|||
_selectionType = TextSelectType::Letters;
|
||||
|
||||
if (activated) {
|
||||
if (_clickHandlerHook.isNull() || _clickHandlerHook.call(activated, button)) {
|
||||
if (!_clickHandlerHook || _clickHandlerHook(activated, button)) {
|
||||
App::activateClickHandler(activated, button);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
|
||||
void setLink(uint16 lnkIndex, const ClickHandlerPtr &lnk);
|
||||
|
||||
using ClickHandlerHook = Function<bool, const ClickHandlerPtr &, Qt::MouseButton>;
|
||||
using ClickHandlerHook = base::lambda_unique<bool(const ClickHandlerPtr&,Qt::MouseButton)>;
|
||||
void setClickHandlerHook(ClickHandlerHook &&hook);
|
||||
|
||||
// ClickHandlerHost interface
|
||||
|
|
|
@ -160,12 +160,12 @@ void InnerDropdown::onHideStart() {
|
|||
void InnerDropdown::startAnimation() {
|
||||
auto from = _hiding ? 1. : 0.;
|
||||
auto to = _hiding ? 0. : 1.;
|
||||
if (_a_appearance.isNull()) {
|
||||
if (!_a_appearance.animating()) {
|
||||
showChildren();
|
||||
_cache = myGrab(this);
|
||||
}
|
||||
hideChildren();
|
||||
START_ANIMATION(_a_appearance, func(this, &InnerDropdown::repaintCallback), from, to, _st.duration, anim::linear);
|
||||
_a_appearance.start([this] { repaintCallback(); }, from, to, _st.duration);
|
||||
}
|
||||
|
||||
void InnerDropdown::hidingFinished() {
|
||||
|
@ -186,7 +186,7 @@ void InnerDropdown::showingStarted() {
|
|||
|
||||
void InnerDropdown::repaintCallback() {
|
||||
update();
|
||||
if (!_a_appearance.animating(getms()) && _hiding) {
|
||||
if (!_a_appearance.animating() && _hiding) {
|
||||
_hiding = false;
|
||||
hidingFinished();
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
void setOwnedWidget(ScrolledWidget *widget);
|
||||
|
||||
bool overlaps(const QRect &globalRect) {
|
||||
if (isHidden() || !_a_appearance.isNull()) return false;
|
||||
if (isHidden() || _a_appearance.animating()) return false;
|
||||
|
||||
return rect().marginsRemoved(_st.padding).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ enum class Mode {
|
|||
};
|
||||
void ToggleableShadow::setMode(Mode mode) {
|
||||
if (mode == Mode::ShownFast || mode == Mode::HiddenFast) {
|
||||
if (!_a_opacity.isNull()) {
|
||||
if (!_a_opacity.animating()) {
|
||||
_a_opacity.finish();
|
||||
update();
|
||||
}
|
||||
|
@ -94,18 +94,12 @@ void ToggleableShadow::setMode(Mode mode) {
|
|||
if (_shown && (mode == Mode::Hidden || mode == Mode::HiddenFast)) {
|
||||
_shown = false;
|
||||
if (mode == Mode::Hidden) {
|
||||
if (_a_opacity.isNull()) {
|
||||
_a_opacity.setup(1., func(this, &ToggleableShadow::repaintCallback));
|
||||
}
|
||||
_a_opacity.start(0., st::shadowToggleDuration);
|
||||
_a_opacity.start([this] { update(); }, 1., 0., st::shadowToggleDuration);
|
||||
}
|
||||
} else if (!_shown && (mode == Mode::Shown || mode == Mode::ShownFast)) {
|
||||
_shown = true;
|
||||
if (mode == Mode::Shown) {
|
||||
if (_a_opacity.isNull()) {
|
||||
_a_opacity.setup(0., func(this, &ToggleableShadow::repaintCallback));
|
||||
}
|
||||
_a_opacity.start(1., st::shadowToggleDuration);
|
||||
_a_opacity.start([this] { update(); }, 0., 1., st::shadowToggleDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -268,17 +268,13 @@ public:
|
|||
void setMode(Mode mode);
|
||||
|
||||
bool isFullyShown() const {
|
||||
return _shown && _a_opacity.isNull();
|
||||
return _shown && !_a_opacity.animating();
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
void repaintCallback() {
|
||||
update();
|
||||
}
|
||||
|
||||
const style::color &_color;
|
||||
FloatAnimation _a_opacity;
|
||||
bool _shown = true;
|
||||
|
|
|
@ -50,8 +50,8 @@ void SectionWidget::showAnimated(SlideDirection direction, const SectionSlidePar
|
|||
|
||||
_showAnimation = std_::make_unique<SlideAnimation>();
|
||||
_showAnimation->setDirection(direction);
|
||||
_showAnimation->setRepaintCallback(func(this, &SectionWidget::repaintCallback));
|
||||
_showAnimation->setFinishedCallback(func(this, &SectionWidget::showFinished));
|
||||
_showAnimation->setRepaintCallback([this] { update(); });
|
||||
_showAnimation->setFinishedCallback([this] { showFinished(); });
|
||||
_showAnimation->setPixmaps(params.oldContentCache, myContentCache);
|
||||
_showAnimation->setTopBarShadow(params.withTopBarShadow);
|
||||
_showAnimation->start();
|
||||
|
|
|
@ -89,10 +89,6 @@ protected:
|
|||
}
|
||||
|
||||
private:
|
||||
// QWidget::update() method is overloaded and we need template deduction.
|
||||
void repaintCallback() {
|
||||
update();
|
||||
}
|
||||
void showFinished();
|
||||
|
||||
std_::unique_ptr<SlideAnimation> _showAnimation;
|
||||
|
|
|
@ -92,7 +92,9 @@ void SlideAnimation::step(float64 ms, bool timer) {
|
|||
a_coordUnder.finish();
|
||||
a_coordOver.finish();
|
||||
|
||||
_finishedCallback.call();
|
||||
if (_finishedCallback) {
|
||||
_finishedCallback();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -100,8 +102,8 @@ void SlideAnimation::step(float64 ms, bool timer) {
|
|||
a_coordUnder.update(dt, st::slideFunction);
|
||||
a_coordOver.update(dt, st::slideFunction);
|
||||
a_progress.update(dt, st::slideFunction);
|
||||
if (timer) {
|
||||
_repaintCallback.call();
|
||||
if (timer && _repaintCallback) {
|
||||
_repaintCallback();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ public:
|
|||
void setPixmaps(const QPixmap &oldContentCache, const QPixmap &newContentCache);
|
||||
void setTopBarShadow(bool enabled);
|
||||
|
||||
using RepaintCallback = Function<void>;
|
||||
using RepaintCallback = base::lambda_unique<void()>;
|
||||
void setRepaintCallback(RepaintCallback &&callback);
|
||||
|
||||
using FinishedCallback = Function<void>;
|
||||
using FinishedCallback = base::lambda_unique<void()>;
|
||||
void setFinishedCallback(FinishedCallback &&callback);
|
||||
|
||||
void start();
|
||||
|
|
Loading…
Add table
Reference in a new issue