Use new animations engine for typings.

This commit is contained in:
John Preston 2019-04-01 18:53:18 +04:00
parent 3971f27c66
commit cd3c1c6dc0
15 changed files with 301 additions and 233 deletions

View File

@ -151,7 +151,9 @@ Session::Session(not_null<AuthSession*> session)
Local::cacheBigFilePath(), Local::cacheBigFilePath(),
Local::cacheBigFileSettings())) Local::cacheBigFileSettings()))
, _selfDestructTimer([=] { checkSelfDestructItems(); }) , _selfDestructTimer([=] { checkSelfDestructItems(); })
, _a_sendActions(animation(this, &Session::step_typings)) , _sendActionsAnimation([=](crl::time now) {
return sendActionsAnimationCallback(now);
})
, _groups(this) , _groups(this)
, _unmuteByFinishedTimer([=] { unmuteByFinished(); }) { , _unmuteByFinishedTimer([=] { unmuteByFinished(); }) {
_cache->open(Local::cacheKey()); _cache->open(Local::cacheKey());
@ -241,7 +243,8 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
return data.vid.v; return data.vid.v;
})); }));
auto minimal = false; auto minimal = false;
const MTPUserStatus *status = 0, emptyStatus = MTP_userStatusEmpty(); const MTPUserStatus *status = nullptr;
const MTPUserStatus emptyStatus = MTP_userStatusEmpty();
Notify::PeerUpdate update; Notify::PeerUpdate update;
using UpdateFlag = Notify::PeerUpdate::Flag; using UpdateFlag = Notify::PeerUpdate::Flag;
@ -749,22 +752,20 @@ void Session::registerSendAction(
const auto i = _sendActions.find(history); const auto i = _sendActions.find(history);
if (!_sendActions.contains(history)) { if (!_sendActions.contains(history)) {
_sendActions.emplace(history, crl::now()); _sendActions.emplace(history, crl::now());
_a_sendActions.start(); _sendActionsAnimation.start();
} }
} }
} }
void Session::step_typings(crl::time ms, bool timer) { bool Session::sendActionsAnimationCallback(crl::time now) {
for (auto i = begin(_sendActions); i != end(_sendActions);) { for (auto i = begin(_sendActions); i != end(_sendActions);) {
if (i->first->updateSendActionNeedsAnimating(ms)) { if (i->first->updateSendActionNeedsAnimating(now)) {
++i; ++i;
} else { } else {
i = _sendActions.erase(i); i = _sendActions.erase(i);
} }
} }
if (_sendActions.empty()) { return !_sendActions.empty();
_a_sendActions.stop();
}
} }
Storage::Cache::Database &Session::cache() { Storage::Cache::Database &Session::cache() {

View File

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_notify_settings.h" #include "data/data_notify_settings.h"
#include "history/history_location_manager.h" #include "history/history_location_manager.h"
#include "base/timer.h" #include "base/timer.h"
#include "ui/effects/animations.h"
class Image; class Image;
class HistoryItem; class HistoryItem;
@ -670,7 +671,7 @@ private:
const MTPMessageMedia &media, const MTPMessageMedia &media,
TimeId date); TimeId date);
void step_typings(crl::time ms, bool timer); bool sendActionsAnimationCallback(crl::time now);
void setWallpapers(const QVector<MTPWallPaper> &data, int32 hash); void setWallpapers(const QVector<MTPWallPaper> &data, int32 hash);
@ -733,7 +734,7 @@ private:
// When typing in this history started. // When typing in this history started.
base::flat_map<not_null<History*>, crl::time> _sendActions; base::flat_map<not_null<History*>, crl::time> _sendActions;
BasicAnimation _a_sendActions; Ui::Animations::Basic _sendActionsAnimation;
std::unordered_map< std::unordered_map<
PhotoId, PhotoId,

View File

@ -40,6 +40,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text_options.h" #include "ui/text_options.h"
#include "core/crash_reports.h" #include "core/crash_reports.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include <memory>
namespace { namespace {
@ -352,45 +353,78 @@ bool History::updateSendActionNeedsAnimating(
return false; return false;
} }
auto ms = crl::now(); const auto now = crl::now();
switch (action.type()) { const auto emplaceAction = [&](
case mtpc_sendMessageTypingAction: _typing.insert(user, ms + kStatusShowClientsideTyping); break; Type type,
case mtpc_sendMessageRecordVideoAction: _sendActions.insert(user, { Type::RecordVideo, ms + kStatusShowClientsideRecordVideo }); break; crl::time duration,
case mtpc_sendMessageUploadVideoAction: _sendActions.insert(user, { Type::UploadVideo, ms + kStatusShowClientsideUploadVideo, action.c_sendMessageUploadVideoAction().vprogress.v }); break; int progress = 0) {
case mtpc_sendMessageRecordAudioAction: _sendActions.insert(user, { Type::RecordVoice, ms + kStatusShowClientsideRecordVoice }); break; _sendActions.emplace(user, type, now + duration, progress);
case mtpc_sendMessageUploadAudioAction: _sendActions.insert(user, { Type::UploadVoice, ms + kStatusShowClientsideUploadVoice, action.c_sendMessageUploadAudioAction().vprogress.v }); break; };
case mtpc_sendMessageRecordRoundAction: _sendActions.insert(user, { Type::RecordRound, ms + kStatusShowClientsideRecordRound }); break; action.match([&](const MTPDsendMessageTypingAction &) {
case mtpc_sendMessageUploadRoundAction: _sendActions.insert(user, { Type::UploadRound, ms + kStatusShowClientsideUploadRound }); break; _typing.emplace(user, now + kStatusShowClientsideTyping);
case mtpc_sendMessageUploadPhotoAction: _sendActions.insert(user, { Type::UploadPhoto, ms + kStatusShowClientsideUploadPhoto, action.c_sendMessageUploadPhotoAction().vprogress.v }); break; }, [&](const MTPDsendMessageRecordVideoAction &) {
case mtpc_sendMessageUploadDocumentAction: _sendActions.insert(user, { Type::UploadFile, ms + kStatusShowClientsideUploadFile, action.c_sendMessageUploadDocumentAction().vprogress.v }); break; emplaceAction(Type::RecordVideo, kStatusShowClientsideRecordVideo);
case mtpc_sendMessageGeoLocationAction: _sendActions.insert(user, { Type::ChooseLocation, ms + kStatusShowClientsideChooseLocation }); break; }, [&](const MTPDsendMessageRecordAudioAction &) {
case mtpc_sendMessageChooseContactAction: _sendActions.insert(user, { Type::ChooseContact, ms + kStatusShowClientsideChooseContact }); break; emplaceAction(Type::RecordVoice, kStatusShowClientsideRecordVideo);
case mtpc_sendMessageGamePlayAction: { }, [&](const MTPDsendMessageRecordRoundAction &) {
auto it = _sendActions.find(user); emplaceAction(Type::RecordRound, kStatusShowClientsideRecordRound);
if (it == _sendActions.end() || it->type == Type::PlayGame || it->until <= ms) { }, [&](const MTPDsendMessageGeoLocationAction &) {
_sendActions.insert(user, { Type::PlayGame, ms + kStatusShowClientsidePlayGame }); emplaceAction(Type::ChooseLocation, kStatusShowClientsideChooseLocation);
}, [&](const MTPDsendMessageChooseContactAction &) {
emplaceAction(Type::ChooseContact, kStatusShowClientsideChooseContact);
}, [&](const MTPDsendMessageUploadVideoAction &data) {
emplaceAction(
Type::UploadVideo,
kStatusShowClientsideUploadVideo,
data.vprogress.v);
}, [&](const MTPDsendMessageUploadAudioAction &data) {
emplaceAction(
Type::UploadVoice,
kStatusShowClientsideUploadVoice,
data.vprogress.v);
}, [&](const MTPDsendMessageUploadRoundAction &data) {
emplaceAction(
Type::UploadRound,
kStatusShowClientsideUploadRound,
data.vprogress.v);
}, [&](const MTPDsendMessageUploadPhotoAction &data) {
emplaceAction(
Type::UploadPhoto,
kStatusShowClientsideUploadPhoto,
data.vprogress.v);
}, [&](const MTPDsendMessageUploadDocumentAction &data) {
emplaceAction(
Type::UploadFile,
kStatusShowClientsideUploadFile,
data.vprogress.v);
}, [&](const MTPDsendMessageGamePlayAction &) {
const auto i = _sendActions.find(user);
if ((i == end(_sendActions))
|| (i->second.type == Type::PlayGame)
|| (i->second.until <= now)) {
emplaceAction(Type::PlayGame, kStatusShowClientsidePlayGame);
} }
} break; }, [&](const MTPDsendMessageCancelAction &) {
default: return false; Unexpected("CancelAction here.");
} });
return updateSendActionNeedsAnimating(ms, true); return updateSendActionNeedsAnimating(now, true);
} }
bool History::mySendActionUpdated(SendAction::Type type, bool doing) { bool History::mySendActionUpdated(SendAction::Type type, bool doing) {
auto ms = crl::now(); const auto now = crl::now();
auto i = _mySendActions.find(type); const auto i = _mySendActions.find(type);
if (doing) { if (doing) {
if (i == _mySendActions.cend()) { if (i == end(_mySendActions)) {
_mySendActions.insert(type, ms + kSetMyActionForMs); _mySendActions.emplace(type, now + kSetMyActionForMs);
} else if (i.value() > ms + (kSetMyActionForMs / 2)) { } else if (i->second > now + (kSetMyActionForMs / 2)) {
return false; return false;
} else { } else {
i.value() = ms + kSetMyActionForMs; i->second = now + kSetMyActionForMs;
} }
} else { } else {
if (i == _mySendActions.cend()) { if (i == end(_mySendActions)) {
return false; return false;
} else if (i.value() <= ms) { } else if (i->second <= now) {
return false; return false;
} else { } else {
_mySendActions.erase(i); _mySendActions.erase(i);
@ -425,18 +459,18 @@ bool History::paintSendAction(
return false; return false;
} }
bool History::updateSendActionNeedsAnimating(crl::time ms, bool force) { bool History::updateSendActionNeedsAnimating(crl::time now, bool force) {
auto changed = force; auto changed = force;
for (auto i = _typing.begin(), e = _typing.end(); i != e;) { for (auto i = begin(_typing); i != end(_typing);) {
if (ms >= i.value()) { if (now >= i->second) {
i = _typing.erase(i); i = _typing.erase(i);
changed = true; changed = true;
} else { } else {
++i; ++i;
} }
} }
for (auto i = _sendActions.begin(); i != _sendActions.cend();) { for (auto i = begin(_sendActions); i != end(_sendActions);) {
if (ms >= i.value().until) { if (now >= i->second.until) {
i = _sendActions.erase(i); i = _sendActions.erase(i);
changed = true; changed = true;
} else { } else {
@ -449,10 +483,18 @@ bool History::updateSendActionNeedsAnimating(crl::time ms, bool force) {
if (typingCount > 2) { if (typingCount > 2) {
newTypingString = lng_many_typing(lt_count, typingCount); newTypingString = lng_many_typing(lt_count, typingCount);
} else if (typingCount > 1) { } else if (typingCount > 1) {
newTypingString = lng_users_typing(lt_user, _typing.begin().key()->firstName, lt_second_user, (_typing.end() - 1).key()->firstName); newTypingString = lng_users_typing(
lt_user,
begin(_typing)->first->firstName,
lt_second_user,
(end(_typing) - 1)->first->firstName);
} else if (typingCount) { } else if (typingCount) {
newTypingString = peer->isUser() ? lang(lng_typing) : lng_user_typing(lt_user, _typing.begin().key()->firstName); newTypingString = peer->isUser()
} else if (!_sendActions.isEmpty()) { ? lang(lng_typing)
: lng_user_typing(
lt_user,
begin(_typing)->first->firstName);
} else if (!_sendActions.empty()) {
// Handles all actions except game playing. // Handles all actions except game playing.
using Type = SendAction::Type; using Type = SendAction::Type;
auto sendActionString = [](Type type, const QString &name) -> QString { auto sendActionString = [](Type type, const QString &name) -> QString {
@ -471,10 +513,12 @@ bool History::updateSendActionNeedsAnimating(crl::time ms, bool force) {
}; };
return QString(); return QString();
}; };
for (auto i = _sendActions.cbegin(), e = _sendActions.cend(); i != e; ++i) { for (const auto [user, action] : _sendActions) {
newTypingString = sendActionString(i->type, peer->isUser() ? QString() : i.key()->firstName); newTypingString = sendActionString(
action.type,
peer->isUser() ? QString() : user->firstName);
if (!newTypingString.isEmpty()) { if (!newTypingString.isEmpty()) {
_sendActionAnimation.start(i->type); _sendActionAnimation.start(action.type);
break; break;
} }
} }
@ -483,11 +527,21 @@ bool History::updateSendActionNeedsAnimating(crl::time ms, bool force) {
if (newTypingString.isEmpty()) { if (newTypingString.isEmpty()) {
int playingCount = _sendActions.size(); int playingCount = _sendActions.size();
if (playingCount > 2) { if (playingCount > 2) {
newTypingString = lng_many_playing_game(lt_count, playingCount); newTypingString = lng_many_playing_game(
lt_count,
playingCount);
} else if (playingCount > 1) { } else if (playingCount > 1) {
newTypingString = lng_users_playing_game(lt_user, _sendActions.begin().key()->firstName, lt_second_user, (_sendActions.end() - 1).key()->firstName); newTypingString = lng_users_playing_game(
lt_user,
begin(_sendActions)->first->firstName,
lt_second_user,
(end(_sendActions) - 1)->first->firstName);
} else { } else {
newTypingString = peer->isUser() ? lang(lng_playing_game) : lng_user_playing_game(lt_user, _sendActions.begin().key()->firstName); newTypingString = peer->isUser()
? lang(lng_playing_game)
: lng_user_playing_game(
lt_user,
begin(_sendActions)->first->firstName);
} }
_sendActionAnimation.start(Type::PlayGame); _sendActionAnimation.start(Type::PlayGame);
} }
@ -505,7 +559,7 @@ bool History::updateSendActionNeedsAnimating(crl::time ms, bool force) {
Ui::NameTextOptions()); Ui::NameTextOptions());
} }
} }
auto result = (!_typing.isEmpty() || !_sendActions.isEmpty()); const auto result = (!_typing.empty() || !_sendActions.empty());
if (changed || (result && !anim::Disabled())) { if (changed || (result && !anim::Disabled())) {
_owner->updateSendActionAnimation({ _owner->updateSendActionAnimation({
this, this,
@ -547,7 +601,7 @@ std::vector<not_null<HistoryItem*>> History::createItems(
for (auto i = data.cend(), e = data.cbegin(); i != e;) { for (auto i = data.cend(), e = data.cbegin(); i != e;) {
const auto detachExistingItem = true; const auto detachExistingItem = true;
if (const auto item = createItem(*--i, detachExistingItem)) { if (const auto item = createItem(*--i, detachExistingItem)) {
result.push_back(item); result.emplace_back(item);
} }
} }
return result; return result;
@ -1064,7 +1118,8 @@ void History::applyServiceChanges(
photo->peer = peer; photo->peer = peer;
auto &smallSize = sizes.front(); auto &smallSize = sizes.front();
auto &bigSize = sizes.back(); auto &bigSize = sizes.back();
const MTPFileLocation *smallLoc = 0, *bigLoc = 0; const MTPFileLocation *smallLoc = nullptr;
const MTPFileLocation *bigLoc = nullptr;
switch (smallSize.type()) { switch (smallSize.type()) {
case mtpc_photoSize: smallLoc = &smallSize.c_photoSize().vlocation; break; case mtpc_photoSize: smallLoc = &smallSize.c_photoSize().vlocation; break;
case mtpc_photoCachedSize: smallLoc = &smallSize.c_photoCachedSize().vlocation; break; case mtpc_photoCachedSize: smallLoc = &smallSize.c_photoCachedSize().vlocation; break;
@ -1135,12 +1190,12 @@ void History::clearSendAction(not_null<UserData*> from) {
auto i = _typing.find(from); auto i = _typing.find(from);
if (i != _typing.cend()) { if (i != _typing.cend()) {
updateAtMs = crl::now(); updateAtMs = crl::now();
i.value() = updateAtMs; i->second = updateAtMs;
} }
auto j = _sendActions.find(from); auto j = _sendActions.find(from);
if (j != _sendActions.cend()) { if (j != _sendActions.cend()) {
if (!updateAtMs) updateAtMs = crl::now(); if (!updateAtMs) updateAtMs = crl::now();
j.value().until = updateAtMs; j->second.until = updateAtMs;
} }
if (updateAtMs) { if (updateAtMs) {
updateSendActionNeedsAnimating(updateAtMs, true); updateSendActionNeedsAnimating(updateAtMs, true);
@ -1977,7 +2032,7 @@ void History::startBuildingFrontBlock(int expectedItemsCount) {
Assert(!isBuildingFrontBlock()); Assert(!isBuildingFrontBlock());
Assert(expectedItemsCount > 0); Assert(expectedItemsCount > 0);
_buildingFrontBlock.reset(new BuildingBlock()); _buildingFrontBlock = std::make_unique<BuildingBlock>();
_buildingFrontBlock->expectedItemsCount = expectedItemsCount; _buildingFrontBlock->expectedItemsCount = expectedItemsCount;
} }
@ -2624,10 +2679,9 @@ History *History::migrateFrom() const {
MsgRange History::rangeForDifferenceRequest() const { MsgRange History::rangeForDifferenceRequest() const {
auto fromId = MsgId(0); auto fromId = MsgId(0);
auto toId = MsgId(0); auto toId = MsgId(0);
for (auto blockIndex = 0, blocksCount = int(blocks.size()); blockIndex < blocksCount; ++blockIndex) { for (const auto &block : blocks) {
const auto &block = blocks[blockIndex]; for (const auto &item : block->messages) {
for (auto itemIndex = 0, itemsCount = int(block->messages.size()); itemIndex < itemsCount; ++itemIndex) { const auto id = item->data()->id;
const auto id = block->messages[itemIndex]->data()->id;
if (id > 0) { if (id > 0) {
fromId = id; fromId = id;
break; break;

View File

@ -216,10 +216,19 @@ public:
void setHasPendingResizedItems(); void setHasPendingResizedItems();
bool mySendActionUpdated(SendAction::Type type, bool doing); bool mySendActionUpdated(SendAction::Type type, bool doing);
bool paintSendAction(Painter &p, int x, int y, int availableWidth, int outerWidth, style::color color, crl::time ms); bool paintSendAction(
Painter &p,
int x,
int y,
int availableWidth,
int outerWidth,
style::color color,
crl::time now);
// Interface for Histories // Interface for Histories
bool updateSendActionNeedsAnimating(crl::time ms, bool force = false); bool updateSendActionNeedsAnimating(
crl::time now,
bool force = false);
bool updateSendActionNeedsAnimating( bool updateSendActionNeedsAnimating(
not_null<UserData*> user, not_null<UserData*> user,
const MTPSendMessageAction &action); const MTPSendMessageAction &action);
@ -490,14 +499,12 @@ private:
TimeId _lastSentDraftTime = 0; TimeId _lastSentDraftTime = 0;
MessageIdsList _forwardDraft; MessageIdsList _forwardDraft;
using TypingUsers = QMap<UserData*, crl::time>; base::flat_map<not_null<UserData*>, crl::time> _typing;
TypingUsers _typing; base::flat_map<not_null<UserData*>, SendAction> _sendActions;
using SendActionUsers = QMap<UserData*, SendAction>;
SendActionUsers _sendActions;
QString _sendActionString; QString _sendActionString;
Text _sendActionText; Text _sendActionText;
Ui::SendActionAnimation _sendActionAnimation; Ui::SendActionAnimation _sendActionAnimation;
QMap<SendAction::Type, crl::time> _mySendActions; base::flat_map<SendAction::Type, crl::time> _mySendActions;
std::weak_ptr<AdminLog::LocalIdManager> _adminLogIdManager; std::weak_ptr<AdminLog::LocalIdManager> _adminLogIdManager;

View File

@ -100,20 +100,22 @@ TopBarWidget::TopBarWidget(
if (Adaptive::OneColumn()) { if (Adaptive::OneColumn()) {
createUnreadBadge(); createUnreadBadge();
} }
Auth().data().sendActionAnimationUpdated( {
) | rpl::start_with_next([=]( using AnimationUpdate = Data::Session::SendActionAnimationUpdate;
const Data::Session::SendActionAnimationUpdate &update) { Auth().data().sendActionAnimationUpdated(
if (update.history == _activeChat.history()) { ) | rpl::filter([=](const AnimationUpdate &update) {
this->update(); return (update.history == _activeChat.history());
} }) | rpl::start_with_next([=] {
}, lifetime()); update();
}, lifetime());
}
using UpdateFlag = Notify::PeerUpdate::Flag; using UpdateFlag = Notify::PeerUpdate::Flag;
auto flags = UpdateFlag::UserHasCalls auto flags = UpdateFlag::UserHasCalls
| UpdateFlag::UserOnlineChanged | UpdateFlag::UserOnlineChanged
| UpdateFlag::MembersChanged | UpdateFlag::MembersChanged
| UpdateFlag::UserSupportInfoChanged; | UpdateFlag::UserSupportInfoChanged;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(flags, [this](const Notify::PeerUpdate &update) { subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(flags, [=](const Notify::PeerUpdate &update) {
if (update.flags & UpdateFlag::UserHasCalls) { if (update.flags & UpdateFlag::UserHasCalls) {
if (update.peer->isUser()) { if (update.peer->isUser()) {
updateControlsVisibility(); updateControlsVisibility();

View File

@ -186,7 +186,7 @@ OverlayWidget::OverlayWidget()
, _docCancel(this, lang(lng_cancel), st::mediaviewFileLink) , _docCancel(this, lang(lng_cancel), st::mediaviewFileLink)
, _radial(animation(this, &OverlayWidget::step_radial)) , _radial(animation(this, &OverlayWidget::step_radial))
, _lastAction(-st::mediaviewDeltaFromLastAction, -st::mediaviewDeltaFromLastAction) , _lastAction(-st::mediaviewDeltaFromLastAction, -st::mediaviewDeltaFromLastAction)
, _a_state([=](float64 now) { step_state(now); }) , _stateAnimation([=](crl::time now) { return stateAnimationCallback(now); })
, _dropdown(this, st::mediaviewDropdownMenu) , _dropdown(this, st::mediaviewDropdownMenu)
, _dropdownShowTimer(this) { , _dropdownShowTimer(this) {
subscribe(Lang::Current().updated(), [this] { refreshLang(); }); subscribe(Lang::Current().updated(), [this] { refreshLang(); });
@ -651,60 +651,57 @@ auto OverlayWidget::computeOverviewType() const
return std::nullopt; return std::nullopt;
} }
void OverlayWidget::step_state(crl::time now) { bool OverlayWidget::stateAnimationCallback(crl::time now) {
if (anim::Disabled()) { if (anim::Disabled()) {
now += st::mediaviewShowDuration + st::mediaviewHideDuration; now += st::mediaviewShowDuration + st::mediaviewHideDuration;
} }
bool result = false; for (auto i = begin(_animations); i != end(_animations);) {
for (auto i = _animations.begin(); i != _animations.end();) { const auto [state, started] = *i;
crl::time start = i.value(); updateOverRect(state);
switch (i.key()) { const auto dt = float64(now - started) / st::mediaviewFadeDuration;
case OverLeftNav: update(_leftNav); break;
case OverRightNav: update(_rightNav); break;
case OverName: update(_nameNav); break;
case OverDate: update(_dateNav); break;
case OverHeader: update(_headerNav); break;
case OverClose: update(_closeNav); break;
case OverSave: update(_saveNav); break;
case OverIcon: update(_docIconRect); break;
case OverMore: update(_moreNav); break;
default: break;
}
const auto dt = float64(now - start) / st::mediaviewFadeDuration;
if (dt >= 1) { if (dt >= 1) {
_animOpacities.remove(i.key()); _animationOpacities.erase(state);
i = _animations.erase(i); i = _animations.erase(i);
} else { } else {
_animOpacities[i.key()].update(dt, anim::linear); _animationOpacities[state].update(dt, anim::linear);
++i; ++i;
} }
} }
if (_controlsState == ControlsShowing || _controlsState == ControlsHiding) { return !_animations.empty() || updateControlsAnimation(now);
float64 dt = float64(now - _controlsAnimStarted) / (_controlsState == ControlsShowing ? st::mediaviewShowDuration : st::mediaviewHideDuration); }
if (dt >= 1) {
a_cOpacity.finish(); bool OverlayWidget::updateControlsAnimation(crl::time now) {
_controlsState = (_controlsState == ControlsShowing ? ControlsShown : ControlsHidden); if (_controlsState != ControlsShowing
updateCursor(); && _controlsState != ControlsHiding) {
} else { return false;
a_cOpacity.update(dt, anim::linear);
}
const auto toUpdate = QRegion()
+ (_over == OverLeftNav ? _leftNav : _leftNavIcon)
+ (_over == OverRightNav ? _rightNav : _rightNavIcon)
+ (_over == OverClose ? _closeNav : _closeNavIcon)
+ _saveNavIcon
+ _moreNavIcon
+ _headerNav
+ _nameNav
+ _dateNav
+ _captionRect.marginsAdded(st::mediaviewCaptionPadding)
+ _groupThumbsRect;
update(toUpdate);
if (dt < 1) result = true;
} }
if (!result && _animations.isEmpty()) { const auto duration = (_controlsState == ControlsShowing)
_a_state.stop(); ? st::mediaviewShowDuration
: st::mediaviewHideDuration;
const auto dt = float64(now - _controlsAnimStarted)
/ duration;
if (dt >= 1) {
_controlsOpacity.finish();
_controlsState = (_controlsState == ControlsShowing)
? ControlsShown
: ControlsHidden;
updateCursor();
} else {
_controlsOpacity.update(dt, anim::linear);
} }
const auto toUpdate = QRegion()
+ (_over == OverLeftNav ? _leftNav : _leftNavIcon)
+ (_over == OverRightNav ? _rightNav : _rightNavIcon)
+ (_over == OverClose ? _closeNav : _closeNavIcon)
+ _saveNavIcon
+ _moreNavIcon
+ _headerNav
+ _nameNav
+ _dateNav
+ _captionRect.marginsAdded(st::mediaviewCaptionPadding)
+ _groupThumbsRect;
update(toUpdate);
return (dt < 1);
} }
void OverlayWidget::step_waiting(crl::time ms, bool timer) { void OverlayWidget::step_waiting(crl::time ms, bool timer) {
@ -910,11 +907,13 @@ void OverlayWidget::clearData() {
if (!isHidden()) { if (!isHidden()) {
hide(); hide();
} }
if (!_animations.isEmpty()) { if (!_animations.empty()) {
_animations.clear(); _animations.clear();
_a_state.stop(); _stateAnimation.stop();
}
if (!_animationOpacities.empty()) {
_animationOpacities.clear();
} }
if (!_animOpacities.isEmpty()) _animOpacities.clear();
clearStreaming(); clearStreaming();
delete _menu; delete _menu;
_menu = nullptr; _menu = nullptr;
@ -967,8 +966,10 @@ void OverlayWidget::activateControls() {
if (_controlsState == ControlsHiding || _controlsState == ControlsHidden) { if (_controlsState == ControlsHiding || _controlsState == ControlsHidden) {
_controlsState = ControlsShowing; _controlsState = ControlsShowing;
_controlsAnimStarted = crl::now(); _controlsAnimStarted = crl::now();
a_cOpacity.start(1); _controlsOpacity.start(1);
if (!_a_state.animating()) _a_state.start(); if (!_stateAnimation.animating()) {
_stateAnimation.start();
}
} }
} }
@ -991,8 +992,10 @@ void OverlayWidget::onHideControls(bool force) {
_lastMouseMovePos = mapFromGlobal(QCursor::pos()); _lastMouseMovePos = mapFromGlobal(QCursor::pos());
_controlsState = ControlsHiding; _controlsState = ControlsHiding;
_controlsAnimStarted = crl::now(); _controlsAnimStarted = crl::now();
a_cOpacity.start(0); _controlsOpacity.start(0);
if (!_a_state.animating()) _a_state.start(); if (!_stateAnimation.animating()) {
_stateAnimation.start();
}
} }
void OverlayWidget::dropdownHidden() { void OverlayWidget::dropdownHidden() {
@ -1632,6 +1635,22 @@ void OverlayWidget::initGroupThumbs() {
height() - _groupThumbsTop); height() - _groupThumbsTop);
} }
void OverlayWidget::clearControlsState() {
_saveMsgStarted = 0;
_loadRequest = 0;
_over = _down = OverNone;
_pressed = false;
_dragging = 0;
setCursor(style::cur_default);
if (!_animations.empty()) {
_animations.clear();
_stateAnimation.stop();
}
if (!_animationOpacities.empty()) {
_animationOpacities.clear();
}
}
void OverlayWidget::showPhoto(not_null<PhotoData*> photo, HistoryItem *context) { void OverlayWidget::showPhoto(not_null<PhotoData*> photo, HistoryItem *context) {
if (context) { if (context) {
setContext(context); setContext(context);
@ -1639,19 +1658,8 @@ void OverlayWidget::showPhoto(not_null<PhotoData*> photo, HistoryItem *context)
setContext(std::nullopt); setContext(std::nullopt);
} }
clearControlsState();
_firstOpenedPeerPhoto = false; _firstOpenedPeerPhoto = false;
_saveMsgStarted = 0;
_loadRequest = 0;
_over = OverNone;
_pressed = false;
_dragging = 0;
setCursor(style::cur_default);
if (!_animations.isEmpty()) {
_animations.clear();
_a_state.stop();
}
if (!_animOpacities.isEmpty()) _animOpacities.clear();
_photo = photo; _photo = photo;
refreshMediaViewer(); refreshMediaViewer();
@ -1664,17 +1672,8 @@ void OverlayWidget::showPhoto(not_null<PhotoData*> photo, HistoryItem *context)
void OverlayWidget::showPhoto(not_null<PhotoData*> photo, not_null<PeerData*> context) { void OverlayWidget::showPhoto(not_null<PhotoData*> photo, not_null<PeerData*> context) {
setContext(context); setContext(context);
clearControlsState();
_firstOpenedPeerPhoto = true; _firstOpenedPeerPhoto = true;
_saveMsgStarted = 0;
_loadRequest = 0;
_over = OverNone;
setCursor(style::cur_default);
if (!_animations.isEmpty()) {
_animations.clear();
_a_state.stop();
}
if (!_animOpacities.isEmpty()) _animOpacities.clear();
_photo = photo; _photo = photo;
refreshMediaViewer(); refreshMediaViewer();
@ -1691,18 +1690,8 @@ void OverlayWidget::showDocument(not_null<DocumentData*> document, HistoryItem *
setContext(std::nullopt); setContext(std::nullopt);
} }
clearControlsState();
_photo = nullptr; _photo = nullptr;
_saveMsgStarted = 0;
_loadRequest = 0;
_down = OverNone;
_pressed = false;
_dragging = 0;
setCursor(style::cur_default);
if (!_animations.isEmpty()) {
_animations.clear();
_a_state.stop();
}
if (!_animOpacities.isEmpty()) _animOpacities.clear();
_streamingStartPaused = false; _streamingStartPaused = false;
displayDocument(document, context); displayDocument(document, context);
@ -2540,7 +2529,7 @@ void OverlayWidget::paintEvent(QPaintEvent *e) {
} }
} }
float64 co = _fullScreenVideo ? 0. : a_cOpacity.current(); float64 co = _fullScreenVideo ? 0. : _controlsOpacity.current();
if (co > 0) { if (co > 0) {
// left nav bar // left nav bar
if (_leftNav.intersects(r) && _leftNavVisible) { if (_leftNav.intersects(r) && _leftNavVisible) {
@ -3276,26 +3265,30 @@ bool OverlayWidget::updateOverState(OverState newState) {
updateOverRect(newState); updateOverRect(newState);
if (_over != OverNone) { if (_over != OverNone) {
_animations[_over] = crl::now(); _animations[_over] = crl::now();
ShowingOpacities::iterator i = _animOpacities.find(_over); const auto i = _animationOpacities.find(_over);
if (i != _animOpacities.end()) { if (i != end(_animationOpacities)) {
i->start(0); i->second.start(0);
} else { } else {
_animOpacities.insert(_over, anim::value(1, 0)); _animationOpacities.emplace(_over, anim::value(1, 0));
}
if (!_stateAnimation.animating()) {
_stateAnimation.start();
} }
if (!_a_state.animating()) _a_state.start();
} else { } else {
result = false; result = false;
} }
_over = newState; _over = newState;
if (newState != OverNone) { if (newState != OverNone) {
_animations[_over] = crl::now(); _animations[_over] = crl::now();
ShowingOpacities::iterator i = _animOpacities.find(_over); const auto i = _animationOpacities.find(_over);
if (i != _animOpacities.end()) { if (i != end(_animationOpacities)) {
i->start(1); i->second.start(1);
} else { } else {
_animOpacities.insert(_over, anim::value(0, 1)); _animationOpacities.emplace(_over, anim::value(0, 1));
}
if (!_stateAnimation.animating()) {
_stateAnimation.start();
} }
if (!_a_state.animating()) _a_state.start();
} }
updateCursor(); updateCursor();
} }
@ -3428,7 +3421,7 @@ void OverlayWidget::contextMenuEvent(QContextMenuEvent *e) {
if (e->reason() != QContextMenuEvent::Mouse || QRect(_x, _y, _w, _h).contains(e->pos())) { if (e->reason() != QContextMenuEvent::Mouse || QRect(_x, _y, _w, _h).contains(e->pos())) {
if (_menu) { if (_menu) {
_menu->deleteLater(); _menu->deleteLater();
_menu = 0; _menu = nullptr;
} }
_menu = new Ui::PopupMenu(this, st::mediaviewPopupMenu); _menu = new Ui::PopupMenu(this, st::mediaviewPopupMenu);
updateActions(); updateActions();
@ -3574,7 +3567,7 @@ void OverlayWidget::setVisibleHook(bool visible) {
if (_menu) _menu->hideMenu(true); if (_menu) _menu->hideMenu(true);
_controlsHideTimer.stop(); _controlsHideTimer.stop();
_controlsState = ControlsShown; _controlsState = ControlsShown;
a_cOpacity = anim::value(1, 1); _controlsOpacity = anim::value(1, 1);
_groupThumbs = nullptr; _groupThumbs = nullptr;
_groupThumbsRect = QRect(); _groupThumbsRect = QRect();
#ifdef USE_OPENGL_OVERLAY_WIDGET #ifdef USE_OPENGL_OVERLAY_WIDGET
@ -3615,7 +3608,7 @@ void OverlayWidget::setVisibleHook(bool visible) {
void OverlayWidget::onMenuDestroy(QObject *obj) { void OverlayWidget::onMenuDestroy(QObject *obj) {
if (_menu == obj) { if (_menu == obj) {
_menu = 0; _menu = nullptr;
activateControls(); activateControls();
} }
_receiveMouse = false; _receiveMouse = false;
@ -3710,8 +3703,10 @@ void OverlayWidget::updateHeader() {
} }
float64 OverlayWidget::overLevel(OverState control) const { float64 OverlayWidget::overLevel(OverState control) const {
auto i = _animOpacities.constFind(control); auto i = _animationOpacities.find(control);
return (i == _animOpacities.cend()) ? (_over == control ? 1 : 0) : i->current(); return (i == end(_animationOpacities))
? (_over == control ? 1. : 0.)
: i->second.current();
} }
} // namespace View } // namespace View

View File

@ -274,9 +274,11 @@ private:
void updateHeader(); void updateHeader();
void snapXY(); void snapXY();
void step_state(crl::time ms); void clearControlsState();
bool stateAnimationCallback(crl::time ms);
void step_radial(crl::time ms, bool timer); void step_radial(crl::time ms, bool timer);
void step_waiting(crl::time ms, bool timer); void step_waiting(crl::time ms, bool timer);
bool updateControlsAnimation(crl::time now);
void zoomIn(); void zoomIn();
void zoomOut(); void zoomOut();
@ -405,7 +407,7 @@ private:
QPoint _lastAction, _lastMouseMovePos; QPoint _lastAction, _lastMouseMovePos;
bool _ignoringDropdown = false; bool _ignoringDropdown = false;
Ui::Animations::Basic _a_state; Ui::Animations::Basic _stateAnimation;
enum ControlsState { enum ControlsState {
ControlsShowing, ControlsShowing,
@ -416,7 +418,7 @@ private:
ControlsState _controlsState = ControlsShown; ControlsState _controlsState = ControlsShown;
crl::time _controlsAnimStarted = 0; crl::time _controlsAnimStarted = 0;
QTimer _controlsHideTimer; QTimer _controlsHideTimer;
anim::value a_cOpacity; anim::value _controlsOpacity;
bool _mousePressed = false; bool _mousePressed = false;
Ui::PopupMenu *_menu = nullptr; Ui::PopupMenu *_menu = nullptr;
@ -431,7 +433,9 @@ private:
bool _receiveMouse = true; bool _receiveMouse = true;
bool _touchPress = false, _touchMove = false, _touchRightButton = false; bool _touchPress = false;
bool _touchMove = false;
bool _touchRightButton = false;
QTimer _touchTimer; QTimer _touchTimer;
QPoint _touchStart; QPoint _touchStart;
QPoint _accumScroll; QPoint _accumScroll;
@ -443,10 +447,8 @@ private:
QTimer _saveMsgUpdater; QTimer _saveMsgUpdater;
Text _saveMsgText; Text _saveMsgText;
typedef QMap<OverState, crl::time> Showing; base::flat_map<OverState, crl::time> _animations;
Showing _animations; base::flat_map<OverState, anim::value> _animationOpacities;
typedef QMap<OverState, anim::value> ShowingOpacities;
ShowingOpacities _animOpacities;
int _verticalWheelDelta = 0; int _verticalWheelDelta = 0;

View File

@ -19,8 +19,12 @@ constexpr auto kPlaybackAnimationDurationMs = crl::time(200);
} // namespace } // namespace
PlaybackProgress::PlaybackProgress() PlaybackProgress::PlaybackProgress()
: _a_value([=](crl::time now) { return valueAnimationCallback(now); }) : _valueAnimation([=](crl::time now) {
, _a_receivedTill([=](crl::time now) { return receivedTillAnimationCallback(now); }) { return valueAnimationCallback(now);
})
, _receivedTillAnimation([=](crl::time now) {
return receivedTillAnimationCallback(now);
}) {
} }
void PlaybackProgress::updateState(const Player::TrackState &state) { void PlaybackProgress::updateState(const Player::TrackState &state) {
@ -87,10 +91,10 @@ void PlaybackProgress::setValue(float64 value, bool animated) {
if (animated) { if (animated) {
valueAnimationCallback(crl::now()); valueAnimationCallback(crl::now());
a_value.start(value); a_value.start(value);
_a_value.start(); _valueAnimation.start();
} else { } else {
a_value = anim::value(value, value); a_value = anim::value(value, value);
_a_value.stop(); _valueAnimation.stop();
} }
emitUpdatedValue(); emitUpdatedValue();
} }
@ -100,19 +104,19 @@ void PlaybackProgress::setReceivedTill(float64 value) {
if (value > current && current > 0.) { if (value > current && current > 0.) {
receivedTillAnimationCallback(crl::now()); receivedTillAnimationCallback(crl::now());
a_receivedTill.start(value); a_receivedTill.start(value);
_a_receivedTill.start(); _receivedTillAnimation.start();
} else if (value > a_value.current()) { } else if (value > a_value.current()) {
a_receivedTill = anim::value(a_value.current(), value); a_receivedTill = anim::value(a_value.current(), value);
_a_receivedTill.start(); _receivedTillAnimation.start();
} else { } else {
a_receivedTill = anim::value(-1., -1.); a_receivedTill = anim::value(-1., -1.);
_a_receivedTill.stop(); _receivedTillAnimation.stop();
} }
emitUpdatedValue(); emitUpdatedValue();
} }
bool PlaybackProgress::valueAnimationCallback(float64 now) { bool PlaybackProgress::valueAnimationCallback(float64 now) {
const auto time = (now - _a_value.started()); const auto time = (now - _valueAnimation.started());
const auto dt = anim::Disabled() const auto dt = anim::Disabled()
? 1. ? 1.
: (time / kPlaybackAnimationDurationMs); : (time / kPlaybackAnimationDurationMs);
@ -126,7 +130,7 @@ bool PlaybackProgress::valueAnimationCallback(float64 now) {
} }
bool PlaybackProgress::receivedTillAnimationCallback(float64 now) { bool PlaybackProgress::receivedTillAnimationCallback(float64 now) {
const auto time = now - _a_receivedTill.started(); const auto time = now - _receivedTillAnimation.started();
const auto dt = anim::Disabled() const auto dt = anim::Disabled()
? 1. ? 1.
: (time / kPlaybackAnimationDurationMs); : (time / kPlaybackAnimationDurationMs);

View File

@ -42,7 +42,7 @@ private:
// so it should be a Basic, not a Simple animation, because // so it should be a Basic, not a Simple animation, because
// Simple-s pauses mtproto responses/updates handling while playing. // Simple-s pauses mtproto responses/updates handling while playing.
anim::value a_value, a_receivedTill; anim::value a_value, a_receivedTill;
Ui::Animations::Basic _a_value, _a_receivedTill; Ui::Animations::Basic _valueAnimation, _receivedTillAnimation;
Fn<void(float64,float64)> _valueChanged; Fn<void(float64,float64)> _valueChanged;
bool _inLoadingState = false; bool _inLoadingState = false;

View File

@ -542,14 +542,14 @@ void LeftOutlineButton::paintEvent(QPaintEvent *e) {
CrossButton::CrossButton(QWidget *parent, const style::CrossButton &st) : RippleButton(parent, st.ripple) CrossButton::CrossButton(QWidget *parent, const style::CrossButton &st) : RippleButton(parent, st.ripple)
, _st(st) , _st(st)
, _a_loading([=](crl::time duration) { return loadingCallback(duration); }) { , _loadingAnimation([=](crl::time now) { return loadingCallback(now); }) {
resize(_st.width, _st.height); resize(_st.width, _st.height);
setCursor(style::cur_pointer); setCursor(style::cur_pointer);
setVisible(false); setVisible(false);
} }
bool CrossButton::loadingCallback(crl::time duration) { bool CrossButton::loadingCallback(crl::time now) {
const auto result = !stopLoadingAnimation(duration); const auto result = !stopLoadingAnimation(now);
if (!result || !anim::Disabled()) { if (!result || !anim::Disabled()) {
update(); update();
} }
@ -563,7 +563,7 @@ void CrossButton::toggle(bool visible, anim::type animated) {
if (isHidden()) { if (isHidden()) {
setVisible(true); setVisible(true);
} }
_a_show.start( _showAnimation.start(
[=] { animationCallback(); }, [=] { animationCallback(); },
_shown ? 0. : 1., _shown ? 0. : 1.,
_shown ? 1. : 0., _shown ? 1. : 0.,
@ -577,7 +577,7 @@ void CrossButton::toggle(bool visible, anim::type animated) {
void CrossButton::animationCallback() { void CrossButton::animationCallback() {
update(); update();
if (!_a_show.animating()) { if (!_showAnimation.animating()) {
setVisible(_shown); setVisible(_shown);
} }
} }
@ -585,18 +585,17 @@ void CrossButton::animationCallback() {
void CrossButton::paintEvent(QPaintEvent *e) { void CrossButton::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
auto ms = crl::now(); auto now = crl::now();
auto over = isOver(); auto over = isOver();
auto shown = _a_show.value(_shown ? 1. : 0.); auto shown = _showAnimation.value(_shown ? 1. : 0.);
p.setOpacity(shown); p.setOpacity(shown);
paintRipple(p, _st.crossPosition.x(), _st.crossPosition.y(), ms); paintRipple(p, _st.crossPosition.x(), _st.crossPosition.y(), now);
auto loading = 0.; auto loading = 0.;
if (_a_loading.animating()) { if (_loadingAnimation.animating()) {
const auto duration = (ms - _a_loading.started()); if (stopLoadingAnimation(now)) {
if (stopLoadingAnimation(duration)) { _loadingAnimation.stop();
_a_loading.stop();
} else if (anim::Disabled()) { } else if (anim::Disabled()) {
CrossAnimation::paintStaticLoading( CrossAnimation::paintStaticLoading(
p, p,
@ -608,8 +607,8 @@ void CrossButton::paintEvent(QPaintEvent *e) {
shown); shown);
return; return;
} else { } else {
loading = (duration % _st.loadingPeriod) loading = ((now - _loadingAnimation.started())
/ float64(_st.loadingPeriod); % _st.loadingPeriod) / float64(_st.loadingPeriod);
} }
} }
CrossAnimation::paint( CrossAnimation::paint(
@ -623,13 +622,14 @@ void CrossButton::paintEvent(QPaintEvent *e) {
loading); loading);
} }
bool CrossButton::stopLoadingAnimation(crl::time duration) { bool CrossButton::stopLoadingAnimation(crl::time now) {
if (!_loadingStopMs) { if (!_loadingStopMs) {
return false; return false;
} }
const auto stopPeriod = (_loadingStopMs - _a_loading.started()) const auto stopPeriod = (_loadingStopMs - _loadingAnimation.started())
/ _st.loadingPeriod;
const auto currentPeriod = (now - _loadingAnimation.started())
/ _st.loadingPeriod; / _st.loadingPeriod;
const auto currentPeriod = duration / _st.loadingPeriod;
if (currentPeriod != stopPeriod) { if (currentPeriod != stopPeriod) {
Assert(currentPeriod > stopPeriod); Assert(currentPeriod > stopPeriod);
return true; return true;
@ -640,13 +640,14 @@ bool CrossButton::stopLoadingAnimation(crl::time duration) {
void CrossButton::setLoadingAnimation(bool enabled) { void CrossButton::setLoadingAnimation(bool enabled) {
if (enabled) { if (enabled) {
_loadingStopMs = 0; _loadingStopMs = 0;
if (!_a_loading.animating()) { if (!_loadingAnimation.animating()) {
_a_loading.start(); _loadingAnimation.start();
} }
} else if (_a_loading.animating()) { } else if (_loadingAnimation.animating()) {
_loadingStopMs = crl::now(); _loadingStopMs = crl::now();
if (!((_loadingStopMs - _a_loading.started()) % _st.loadingPeriod)) { if (!((_loadingStopMs - _loadingAnimation.started())
_a_loading.stop(); % _st.loadingPeriod)) {
_loadingAnimation.stop();
} }
} }
if (anim::Disabled()) { if (anim::Disabled()) {

View File

@ -217,7 +217,7 @@ public:
return toggle(false, animated); return toggle(false, animated);
} }
void finishAnimating() { void finishAnimating() {
_a_show.stop(); _showAnimation.stop();
animationCallback(); animationCallback();
} }
@ -235,17 +235,17 @@ protected:
QPoint prepareRippleStartPosition() const override; QPoint prepareRippleStartPosition() const override;
private: private:
bool loadingCallback(crl::time duration); bool loadingCallback(crl::time now);
bool stopLoadingAnimation(crl::time duration); bool stopLoadingAnimation(crl::time now);
void animationCallback(); void animationCallback();
const style::CrossButton &_st; const style::CrossButton &_st;
bool _shown = false; bool _shown = false;
Ui::Animations::Simple _a_show; Ui::Animations::Simple _showAnimation;
crl::time _loadingStopMs = 0; crl::time _loadingStopMs = 0;
Ui::Animations::Basic _a_loading; Ui::Animations::Basic _loadingAnimation;
}; };

View File

@ -148,7 +148,7 @@ void ContinuousSlider::setOver(bool over) {
_over = over; _over = over;
auto from = _over ? 0. : 1., to = _over ? 1. : 0.; auto from = _over ? 0. : 1., to = _over ? 1. : 0.;
_a_over.start([this] { update(); }, from, to, getOverDuration()); _overAnimation.start([=] { update(); }, from, to, getOverDuration());
} }
FilledSlider::FilledSlider(QWidget *parent, const style::FilledSlider &st) : ContinuousSlider(parent) FilledSlider::FilledSlider(QWidget *parent, const style::FilledSlider &st) : ContinuousSlider(parent)

View File

@ -72,7 +72,7 @@ protected:
return _receivedTill; return _receivedTill;
} }
float64 getCurrentOverFactor() { float64 getCurrentOverFactor() {
return _disabled ? 0. : _a_over.value(_over ? 1. : 0.); return _disabled ? 0. : _overAnimation.value(_over ? 1. : 0.);
} }
Direction getDirection() const { Direction getDirection() const {
return _direction; return _direction;
@ -104,7 +104,7 @@ private:
Fn<void(float64)> _changeFinishedCallback; Fn<void(float64)> _changeFinishedCallback;
bool _over = false; bool _over = false;
Ui::Animations::Simple _a_over; Ui::Animations::Simple _overAnimation;
float64 _value = 0.; float64 _value = 0.;
float64 _receivedTill = 0.; float64 _receivedTill = 0.;

View File

@ -972,7 +972,7 @@ void FlatInput::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
auto ms = crl::now(); auto ms = crl::now();
auto placeholderFocused = _a_placeholderFocused.value(_focused ? 1. : 0.); auto placeholderFocused = _placeholderFocusedAnimation.value(_focused ? 1. : 0.);
auto pen = anim::pen(_st.borderColor, _st.borderActive, placeholderFocused); auto pen = anim::pen(_st.borderColor, _st.borderActive, placeholderFocused);
pen.setWidth(_st.borderWidth); pen.setWidth(_st.borderWidth);
p.setPen(pen); p.setPen(pen);
@ -986,7 +986,8 @@ void FlatInput::paintEvent(QPaintEvent *e) {
_st.icon.paint(p, 0, 0, width()); _st.icon.paint(p, 0, 0, width());
} }
auto placeholderOpacity = _a_placeholderVisible.value(_placeholderVisible ? 1. : 0.); const auto placeholderOpacity = _placeholderVisibleAnimation.value(
_placeholderVisible ? 1. : 0.);
if (placeholderOpacity > 0.) { if (placeholderOpacity > 0.) {
p.setOpacity(placeholderOpacity); p.setOpacity(placeholderOpacity);
@ -1006,7 +1007,7 @@ void FlatInput::paintEvent(QPaintEvent *e) {
void FlatInput::focusInEvent(QFocusEvent *e) { void FlatInput::focusInEvent(QFocusEvent *e) {
if (!_focused) { if (!_focused) {
_focused = true; _focused = true;
_a_placeholderFocused.start( _placeholderFocusedAnimation.start(
[=] { update(); }, [=] { update(); },
0., 0.,
1., 1.,
@ -1020,7 +1021,7 @@ void FlatInput::focusInEvent(QFocusEvent *e) {
void FlatInput::focusOutEvent(QFocusEvent *e) { void FlatInput::focusOutEvent(QFocusEvent *e) {
if (_focused) { if (_focused) {
_focused = false; _focused = false;
_a_placeholderFocused.start( _placeholderFocusedAnimation.start(
[=] { update(); }, [=] { update(); },
1., 1.,
0., 0.,
@ -1076,7 +1077,7 @@ void FlatInput::updatePlaceholder() {
auto placeholderVisible = !hasText; auto placeholderVisible = !hasText;
if (_placeholderVisible != placeholderVisible) { if (_placeholderVisible != placeholderVisible) {
_placeholderVisible = placeholderVisible; _placeholderVisible = placeholderVisible;
_a_placeholderVisible.start( _placeholderVisibleAnimation.start(
[=] { update(); }, [=] { update(); },
_placeholderVisible ? 0. : 1., _placeholderVisible ? 0. : 1.,
_placeholderVisible ? 1. : 0., _placeholderVisible ? 1. : 0.,

View File

@ -111,8 +111,8 @@ private:
bool _focused = false; bool _focused = false;
bool _placeholderVisible = true; bool _placeholderVisible = true;
Animations::Simple _a_placeholderFocused; Animations::Simple _placeholderFocusedAnimation;
Animations::Simple _a_placeholderVisible; Animations::Simple _placeholderVisibleAnimation;
bool _lastPreEditTextNotEmpty = false; bool _lastPreEditTextNotEmpty = false;
const style::FlatInput &_st; const style::FlatInput &_st;