diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 493a345d93..4029440a02 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -151,7 +151,9 @@ Session::Session(not_null session) Local::cacheBigFilePath(), Local::cacheBigFileSettings())) , _selfDestructTimer([=] { checkSelfDestructItems(); }) -, _a_sendActions(animation(this, &Session::step_typings)) +, _sendActionsAnimation([=](crl::time now) { + return sendActionsAnimationCallback(now); +}) , _groups(this) , _unmuteByFinishedTimer([=] { unmuteByFinished(); }) { _cache->open(Local::cacheKey()); @@ -241,7 +243,8 @@ not_null Session::processUser(const MTPUser &data) { return data.vid.v; })); auto minimal = false; - const MTPUserStatus *status = 0, emptyStatus = MTP_userStatusEmpty(); + const MTPUserStatus *status = nullptr; + const MTPUserStatus emptyStatus = MTP_userStatusEmpty(); Notify::PeerUpdate update; using UpdateFlag = Notify::PeerUpdate::Flag; @@ -749,22 +752,20 @@ void Session::registerSendAction( const auto i = _sendActions.find(history); if (!_sendActions.contains(history)) { _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);) { - if (i->first->updateSendActionNeedsAnimating(ms)) { + if (i->first->updateSendActionNeedsAnimating(now)) { ++i; } else { i = _sendActions.erase(i); } } - if (_sendActions.empty()) { - _a_sendActions.stop(); - } + return !_sendActions.empty(); } Storage::Cache::Database &Session::cache() { diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 011bf66446..7efc58d112 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_notify_settings.h" #include "history/history_location_manager.h" #include "base/timer.h" +#include "ui/effects/animations.h" class Image; class HistoryItem; @@ -670,7 +671,7 @@ private: const MTPMessageMedia &media, TimeId date); - void step_typings(crl::time ms, bool timer); + bool sendActionsAnimationCallback(crl::time now); void setWallpapers(const QVector &data, int32 hash); @@ -733,7 +734,7 @@ private: // When typing in this history started. base::flat_map, crl::time> _sendActions; - BasicAnimation _a_sendActions; + Ui::Animations::Basic _sendActionsAnimation; std::unordered_map< PhotoId, diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 88bb06d235..3c8e9d6323 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -40,6 +40,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text_options.h" #include "core/crash_reports.h" #include "styles/style_dialogs.h" +#include namespace { @@ -352,45 +353,78 @@ bool History::updateSendActionNeedsAnimating( return false; } - auto ms = crl::now(); - switch (action.type()) { - case mtpc_sendMessageTypingAction: _typing.insert(user, ms + kStatusShowClientsideTyping); break; - case mtpc_sendMessageRecordVideoAction: _sendActions.insert(user, { Type::RecordVideo, ms + kStatusShowClientsideRecordVideo }); break; - case mtpc_sendMessageUploadVideoAction: _sendActions.insert(user, { Type::UploadVideo, ms + kStatusShowClientsideUploadVideo, action.c_sendMessageUploadVideoAction().vprogress.v }); break; - case mtpc_sendMessageRecordAudioAction: _sendActions.insert(user, { Type::RecordVoice, ms + kStatusShowClientsideRecordVoice }); break; - 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; - case mtpc_sendMessageUploadRoundAction: _sendActions.insert(user, { Type::UploadRound, ms + kStatusShowClientsideUploadRound }); break; - case mtpc_sendMessageUploadPhotoAction: _sendActions.insert(user, { Type::UploadPhoto, ms + kStatusShowClientsideUploadPhoto, action.c_sendMessageUploadPhotoAction().vprogress.v }); break; - case mtpc_sendMessageUploadDocumentAction: _sendActions.insert(user, { Type::UploadFile, ms + kStatusShowClientsideUploadFile, action.c_sendMessageUploadDocumentAction().vprogress.v }); break; - case mtpc_sendMessageGeoLocationAction: _sendActions.insert(user, { Type::ChooseLocation, ms + kStatusShowClientsideChooseLocation }); break; - case mtpc_sendMessageChooseContactAction: _sendActions.insert(user, { Type::ChooseContact, ms + kStatusShowClientsideChooseContact }); break; - case mtpc_sendMessageGamePlayAction: { - auto it = _sendActions.find(user); - if (it == _sendActions.end() || it->type == Type::PlayGame || it->until <= ms) { - _sendActions.insert(user, { Type::PlayGame, ms + kStatusShowClientsidePlayGame }); + const auto now = crl::now(); + const auto emplaceAction = [&]( + Type type, + crl::time duration, + int progress = 0) { + _sendActions.emplace(user, type, now + duration, progress); + }; + action.match([&](const MTPDsendMessageTypingAction &) { + _typing.emplace(user, now + kStatusShowClientsideTyping); + }, [&](const MTPDsendMessageRecordVideoAction &) { + emplaceAction(Type::RecordVideo, kStatusShowClientsideRecordVideo); + }, [&](const MTPDsendMessageRecordAudioAction &) { + emplaceAction(Type::RecordVoice, kStatusShowClientsideRecordVideo); + }, [&](const MTPDsendMessageRecordRoundAction &) { + emplaceAction(Type::RecordRound, kStatusShowClientsideRecordRound); + }, [&](const MTPDsendMessageGeoLocationAction &) { + 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; - default: return false; - } - return updateSendActionNeedsAnimating(ms, true); + }, [&](const MTPDsendMessageCancelAction &) { + Unexpected("CancelAction here."); + }); + return updateSendActionNeedsAnimating(now, true); } bool History::mySendActionUpdated(SendAction::Type type, bool doing) { - auto ms = crl::now(); - auto i = _mySendActions.find(type); + const auto now = crl::now(); + const auto i = _mySendActions.find(type); if (doing) { - if (i == _mySendActions.cend()) { - _mySendActions.insert(type, ms + kSetMyActionForMs); - } else if (i.value() > ms + (kSetMyActionForMs / 2)) { + if (i == end(_mySendActions)) { + _mySendActions.emplace(type, now + kSetMyActionForMs); + } else if (i->second > now + (kSetMyActionForMs / 2)) { return false; } else { - i.value() = ms + kSetMyActionForMs; + i->second = now + kSetMyActionForMs; } } else { - if (i == _mySendActions.cend()) { + if (i == end(_mySendActions)) { return false; - } else if (i.value() <= ms) { + } else if (i->second <= now) { return false; } else { _mySendActions.erase(i); @@ -425,18 +459,18 @@ bool History::paintSendAction( return false; } -bool History::updateSendActionNeedsAnimating(crl::time ms, bool force) { +bool History::updateSendActionNeedsAnimating(crl::time now, bool force) { auto changed = force; - for (auto i = _typing.begin(), e = _typing.end(); i != e;) { - if (ms >= i.value()) { + for (auto i = begin(_typing); i != end(_typing);) { + if (now >= i->second) { i = _typing.erase(i); changed = true; } else { ++i; } } - for (auto i = _sendActions.begin(); i != _sendActions.cend();) { - if (ms >= i.value().until) { + for (auto i = begin(_sendActions); i != end(_sendActions);) { + if (now >= i->second.until) { i = _sendActions.erase(i); changed = true; } else { @@ -449,10 +483,18 @@ bool History::updateSendActionNeedsAnimating(crl::time ms, bool force) { if (typingCount > 2) { newTypingString = lng_many_typing(lt_count, typingCount); } 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) { - newTypingString = peer->isUser() ? lang(lng_typing) : lng_user_typing(lt_user, _typing.begin().key()->firstName); - } else if (!_sendActions.isEmpty()) { + newTypingString = peer->isUser() + ? lang(lng_typing) + : lng_user_typing( + lt_user, + begin(_typing)->first->firstName); + } else if (!_sendActions.empty()) { // Handles all actions except game playing. using Type = SendAction::Type; auto sendActionString = [](Type type, const QString &name) -> QString { @@ -471,10 +513,12 @@ bool History::updateSendActionNeedsAnimating(crl::time ms, bool force) { }; return QString(); }; - for (auto i = _sendActions.cbegin(), e = _sendActions.cend(); i != e; ++i) { - newTypingString = sendActionString(i->type, peer->isUser() ? QString() : i.key()->firstName); + for (const auto [user, action] : _sendActions) { + newTypingString = sendActionString( + action.type, + peer->isUser() ? QString() : user->firstName); if (!newTypingString.isEmpty()) { - _sendActionAnimation.start(i->type); + _sendActionAnimation.start(action.type); break; } } @@ -483,11 +527,21 @@ bool History::updateSendActionNeedsAnimating(crl::time ms, bool force) { if (newTypingString.isEmpty()) { int playingCount = _sendActions.size(); if (playingCount > 2) { - newTypingString = lng_many_playing_game(lt_count, playingCount); + newTypingString = lng_many_playing_game( + lt_count, + playingCount); } 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 { - 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); } @@ -505,7 +559,7 @@ bool History::updateSendActionNeedsAnimating(crl::time ms, bool force) { Ui::NameTextOptions()); } } - auto result = (!_typing.isEmpty() || !_sendActions.isEmpty()); + const auto result = (!_typing.empty() || !_sendActions.empty()); if (changed || (result && !anim::Disabled())) { _owner->updateSendActionAnimation({ this, @@ -547,7 +601,7 @@ std::vector> History::createItems( for (auto i = data.cend(), e = data.cbegin(); i != e;) { const auto detachExistingItem = true; if (const auto item = createItem(*--i, detachExistingItem)) { - result.push_back(item); + result.emplace_back(item); } } return result; @@ -1064,7 +1118,8 @@ void History::applyServiceChanges( photo->peer = peer; auto &smallSize = sizes.front(); auto &bigSize = sizes.back(); - const MTPFileLocation *smallLoc = 0, *bigLoc = 0; + const MTPFileLocation *smallLoc = nullptr; + const MTPFileLocation *bigLoc = nullptr; switch (smallSize.type()) { case mtpc_photoSize: smallLoc = &smallSize.c_photoSize().vlocation; break; case mtpc_photoCachedSize: smallLoc = &smallSize.c_photoCachedSize().vlocation; break; @@ -1135,12 +1190,12 @@ void History::clearSendAction(not_null from) { auto i = _typing.find(from); if (i != _typing.cend()) { updateAtMs = crl::now(); - i.value() = updateAtMs; + i->second = updateAtMs; } auto j = _sendActions.find(from); if (j != _sendActions.cend()) { if (!updateAtMs) updateAtMs = crl::now(); - j.value().until = updateAtMs; + j->second.until = updateAtMs; } if (updateAtMs) { updateSendActionNeedsAnimating(updateAtMs, true); @@ -1977,7 +2032,7 @@ void History::startBuildingFrontBlock(int expectedItemsCount) { Assert(!isBuildingFrontBlock()); Assert(expectedItemsCount > 0); - _buildingFrontBlock.reset(new BuildingBlock()); + _buildingFrontBlock = std::make_unique(); _buildingFrontBlock->expectedItemsCount = expectedItemsCount; } @@ -2624,10 +2679,9 @@ History *History::migrateFrom() const { MsgRange History::rangeForDifferenceRequest() const { auto fromId = MsgId(0); auto toId = MsgId(0); - for (auto blockIndex = 0, blocksCount = int(blocks.size()); blockIndex < blocksCount; ++blockIndex) { - const auto &block = blocks[blockIndex]; - for (auto itemIndex = 0, itemsCount = int(block->messages.size()); itemIndex < itemsCount; ++itemIndex) { - const auto id = block->messages[itemIndex]->data()->id; + for (const auto &block : blocks) { + for (const auto &item : block->messages) { + const auto id = item->data()->id; if (id > 0) { fromId = id; break; diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 50d0be452a..bd588f1723 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -216,10 +216,19 @@ public: void setHasPendingResizedItems(); 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 - bool updateSendActionNeedsAnimating(crl::time ms, bool force = false); + bool updateSendActionNeedsAnimating( + crl::time now, + bool force = false); bool updateSendActionNeedsAnimating( not_null user, const MTPSendMessageAction &action); @@ -490,14 +499,12 @@ private: TimeId _lastSentDraftTime = 0; MessageIdsList _forwardDraft; - using TypingUsers = QMap; - TypingUsers _typing; - using SendActionUsers = QMap; - SendActionUsers _sendActions; + base::flat_map, crl::time> _typing; + base::flat_map, SendAction> _sendActions; QString _sendActionString; Text _sendActionText; Ui::SendActionAnimation _sendActionAnimation; - QMap _mySendActions; + base::flat_map _mySendActions; std::weak_ptr _adminLogIdManager; diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index a176617f28..3f57523298 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -100,20 +100,22 @@ TopBarWidget::TopBarWidget( if (Adaptive::OneColumn()) { createUnreadBadge(); } - Auth().data().sendActionAnimationUpdated( - ) | rpl::start_with_next([=]( - const Data::Session::SendActionAnimationUpdate &update) { - if (update.history == _activeChat.history()) { - this->update(); - } - }, lifetime()); + { + using AnimationUpdate = Data::Session::SendActionAnimationUpdate; + Auth().data().sendActionAnimationUpdated( + ) | rpl::filter([=](const AnimationUpdate &update) { + return (update.history == _activeChat.history()); + }) | rpl::start_with_next([=] { + update(); + }, lifetime()); + } using UpdateFlag = Notify::PeerUpdate::Flag; auto flags = UpdateFlag::UserHasCalls | UpdateFlag::UserOnlineChanged | UpdateFlag::MembersChanged | 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.peer->isUser()) { updateControlsVisibility(); diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 212e94b214..b3d539ee58 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -186,7 +186,7 @@ OverlayWidget::OverlayWidget() , _docCancel(this, lang(lng_cancel), st::mediaviewFileLink) , _radial(animation(this, &OverlayWidget::step_radial)) , _lastAction(-st::mediaviewDeltaFromLastAction, -st::mediaviewDeltaFromLastAction) -, _a_state([=](float64 now) { step_state(now); }) +, _stateAnimation([=](crl::time now) { return stateAnimationCallback(now); }) , _dropdown(this, st::mediaviewDropdownMenu) , _dropdownShowTimer(this) { subscribe(Lang::Current().updated(), [this] { refreshLang(); }); @@ -651,60 +651,57 @@ auto OverlayWidget::computeOverviewType() const return std::nullopt; } -void OverlayWidget::step_state(crl::time now) { +bool OverlayWidget::stateAnimationCallback(crl::time now) { if (anim::Disabled()) { now += st::mediaviewShowDuration + st::mediaviewHideDuration; } - bool result = false; - for (auto i = _animations.begin(); i != _animations.end();) { - crl::time start = i.value(); - switch (i.key()) { - 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; + for (auto i = begin(_animations); i != end(_animations);) { + const auto [state, started] = *i; + updateOverRect(state); + const auto dt = float64(now - started) / st::mediaviewFadeDuration; if (dt >= 1) { - _animOpacities.remove(i.key()); + _animationOpacities.erase(state); i = _animations.erase(i); } else { - _animOpacities[i.key()].update(dt, anim::linear); + _animationOpacities[state].update(dt, anim::linear); ++i; } } - if (_controlsState == ControlsShowing || _controlsState == ControlsHiding) { - float64 dt = float64(now - _controlsAnimStarted) / (_controlsState == ControlsShowing ? st::mediaviewShowDuration : st::mediaviewHideDuration); - if (dt >= 1) { - a_cOpacity.finish(); - _controlsState = (_controlsState == ControlsShowing ? ControlsShown : ControlsHidden); - updateCursor(); - } else { - 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; + return !_animations.empty() || updateControlsAnimation(now); +} + +bool OverlayWidget::updateControlsAnimation(crl::time now) { + if (_controlsState != ControlsShowing + && _controlsState != ControlsHiding) { + return false; } - if (!result && _animations.isEmpty()) { - _a_state.stop(); + const auto duration = (_controlsState == ControlsShowing) + ? 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) { @@ -910,11 +907,13 @@ void OverlayWidget::clearData() { if (!isHidden()) { hide(); } - if (!_animations.isEmpty()) { + if (!_animations.empty()) { _animations.clear(); - _a_state.stop(); + _stateAnimation.stop(); + } + if (!_animationOpacities.empty()) { + _animationOpacities.clear(); } - if (!_animOpacities.isEmpty()) _animOpacities.clear(); clearStreaming(); delete _menu; _menu = nullptr; @@ -967,8 +966,10 @@ void OverlayWidget::activateControls() { if (_controlsState == ControlsHiding || _controlsState == ControlsHidden) { _controlsState = ControlsShowing; _controlsAnimStarted = crl::now(); - a_cOpacity.start(1); - if (!_a_state.animating()) _a_state.start(); + _controlsOpacity.start(1); + if (!_stateAnimation.animating()) { + _stateAnimation.start(); + } } } @@ -991,8 +992,10 @@ void OverlayWidget::onHideControls(bool force) { _lastMouseMovePos = mapFromGlobal(QCursor::pos()); _controlsState = ControlsHiding; _controlsAnimStarted = crl::now(); - a_cOpacity.start(0); - if (!_a_state.animating()) _a_state.start(); + _controlsOpacity.start(0); + if (!_stateAnimation.animating()) { + _stateAnimation.start(); + } } void OverlayWidget::dropdownHidden() { @@ -1632,6 +1635,22 @@ void OverlayWidget::initGroupThumbs() { 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 photo, HistoryItem *context) { if (context) { setContext(context); @@ -1639,19 +1658,8 @@ void OverlayWidget::showPhoto(not_null photo, HistoryItem *context) setContext(std::nullopt); } + clearControlsState(); _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; refreshMediaViewer(); @@ -1664,17 +1672,8 @@ void OverlayWidget::showPhoto(not_null photo, HistoryItem *context) void OverlayWidget::showPhoto(not_null photo, not_null context) { setContext(context); + clearControlsState(); _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; refreshMediaViewer(); @@ -1691,18 +1690,8 @@ void OverlayWidget::showDocument(not_null document, HistoryItem * setContext(std::nullopt); } + clearControlsState(); _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; 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) { // left nav bar if (_leftNav.intersects(r) && _leftNavVisible) { @@ -3276,26 +3265,30 @@ bool OverlayWidget::updateOverState(OverState newState) { updateOverRect(newState); if (_over != OverNone) { _animations[_over] = crl::now(); - ShowingOpacities::iterator i = _animOpacities.find(_over); - if (i != _animOpacities.end()) { - i->start(0); + const auto i = _animationOpacities.find(_over); + if (i != end(_animationOpacities)) { + i->second.start(0); } 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 { result = false; } _over = newState; if (newState != OverNone) { _animations[_over] = crl::now(); - ShowingOpacities::iterator i = _animOpacities.find(_over); - if (i != _animOpacities.end()) { - i->start(1); + const auto i = _animationOpacities.find(_over); + if (i != end(_animationOpacities)) { + i->second.start(1); } 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(); } @@ -3428,7 +3421,7 @@ void OverlayWidget::contextMenuEvent(QContextMenuEvent *e) { if (e->reason() != QContextMenuEvent::Mouse || QRect(_x, _y, _w, _h).contains(e->pos())) { if (_menu) { _menu->deleteLater(); - _menu = 0; + _menu = nullptr; } _menu = new Ui::PopupMenu(this, st::mediaviewPopupMenu); updateActions(); @@ -3574,7 +3567,7 @@ void OverlayWidget::setVisibleHook(bool visible) { if (_menu) _menu->hideMenu(true); _controlsHideTimer.stop(); _controlsState = ControlsShown; - a_cOpacity = anim::value(1, 1); + _controlsOpacity = anim::value(1, 1); _groupThumbs = nullptr; _groupThumbsRect = QRect(); #ifdef USE_OPENGL_OVERLAY_WIDGET @@ -3615,7 +3608,7 @@ void OverlayWidget::setVisibleHook(bool visible) { void OverlayWidget::onMenuDestroy(QObject *obj) { if (_menu == obj) { - _menu = 0; + _menu = nullptr; activateControls(); } _receiveMouse = false; @@ -3710,8 +3703,10 @@ void OverlayWidget::updateHeader() { } float64 OverlayWidget::overLevel(OverState control) const { - auto i = _animOpacities.constFind(control); - return (i == _animOpacities.cend()) ? (_over == control ? 1 : 0) : i->current(); + auto i = _animationOpacities.find(control); + return (i == end(_animationOpacities)) + ? (_over == control ? 1. : 0.) + : i->second.current(); } } // namespace View diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h index ec04c918d5..7682a434fb 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h @@ -274,9 +274,11 @@ private: void updateHeader(); 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_waiting(crl::time ms, bool timer); + bool updateControlsAnimation(crl::time now); void zoomIn(); void zoomOut(); @@ -405,7 +407,7 @@ private: QPoint _lastAction, _lastMouseMovePos; bool _ignoringDropdown = false; - Ui::Animations::Basic _a_state; + Ui::Animations::Basic _stateAnimation; enum ControlsState { ControlsShowing, @@ -416,7 +418,7 @@ private: ControlsState _controlsState = ControlsShown; crl::time _controlsAnimStarted = 0; QTimer _controlsHideTimer; - anim::value a_cOpacity; + anim::value _controlsOpacity; bool _mousePressed = false; Ui::PopupMenu *_menu = nullptr; @@ -431,7 +433,9 @@ private: bool _receiveMouse = true; - bool _touchPress = false, _touchMove = false, _touchRightButton = false; + bool _touchPress = false; + bool _touchMove = false; + bool _touchRightButton = false; QTimer _touchTimer; QPoint _touchStart; QPoint _accumScroll; @@ -443,10 +447,8 @@ private: QTimer _saveMsgUpdater; Text _saveMsgText; - typedef QMap Showing; - Showing _animations; - typedef QMap ShowingOpacities; - ShowingOpacities _animOpacities; + base::flat_map _animations; + base::flat_map _animationOpacities; int _verticalWheelDelta = 0; diff --git a/Telegram/SourceFiles/media/view/media_view_playback_progress.cpp b/Telegram/SourceFiles/media/view/media_view_playback_progress.cpp index 48c180851a..2979904c50 100644 --- a/Telegram/SourceFiles/media/view/media_view_playback_progress.cpp +++ b/Telegram/SourceFiles/media/view/media_view_playback_progress.cpp @@ -19,8 +19,12 @@ constexpr auto kPlaybackAnimationDurationMs = crl::time(200); } // namespace PlaybackProgress::PlaybackProgress() -: _a_value([=](crl::time now) { return valueAnimationCallback(now); }) -, _a_receivedTill([=](crl::time now) { return receivedTillAnimationCallback(now); }) { +: _valueAnimation([=](crl::time now) { + return valueAnimationCallback(now); +}) +, _receivedTillAnimation([=](crl::time now) { + return receivedTillAnimationCallback(now); +}) { } void PlaybackProgress::updateState(const Player::TrackState &state) { @@ -87,10 +91,10 @@ void PlaybackProgress::setValue(float64 value, bool animated) { if (animated) { valueAnimationCallback(crl::now()); a_value.start(value); - _a_value.start(); + _valueAnimation.start(); } else { a_value = anim::value(value, value); - _a_value.stop(); + _valueAnimation.stop(); } emitUpdatedValue(); } @@ -100,19 +104,19 @@ void PlaybackProgress::setReceivedTill(float64 value) { if (value > current && current > 0.) { receivedTillAnimationCallback(crl::now()); a_receivedTill.start(value); - _a_receivedTill.start(); + _receivedTillAnimation.start(); } else if (value > a_value.current()) { a_receivedTill = anim::value(a_value.current(), value); - _a_receivedTill.start(); + _receivedTillAnimation.start(); } else { a_receivedTill = anim::value(-1., -1.); - _a_receivedTill.stop(); + _receivedTillAnimation.stop(); } emitUpdatedValue(); } bool PlaybackProgress::valueAnimationCallback(float64 now) { - const auto time = (now - _a_value.started()); + const auto time = (now - _valueAnimation.started()); const auto dt = anim::Disabled() ? 1. : (time / kPlaybackAnimationDurationMs); @@ -126,7 +130,7 @@ bool PlaybackProgress::valueAnimationCallback(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() ? 1. : (time / kPlaybackAnimationDurationMs); diff --git a/Telegram/SourceFiles/media/view/media_view_playback_progress.h b/Telegram/SourceFiles/media/view/media_view_playback_progress.h index 6273633c1c..6a05f50ce7 100644 --- a/Telegram/SourceFiles/media/view/media_view_playback_progress.h +++ b/Telegram/SourceFiles/media/view/media_view_playback_progress.h @@ -42,7 +42,7 @@ private: // so it should be a Basic, not a Simple animation, because // Simple-s pauses mtproto responses/updates handling while playing. anim::value a_value, a_receivedTill; - Ui::Animations::Basic _a_value, _a_receivedTill; + Ui::Animations::Basic _valueAnimation, _receivedTillAnimation; Fn _valueChanged; bool _inLoadingState = false; diff --git a/Telegram/SourceFiles/ui/widgets/buttons.cpp b/Telegram/SourceFiles/ui/widgets/buttons.cpp index 883e19e611..d029f86e0c 100644 --- a/Telegram/SourceFiles/ui/widgets/buttons.cpp +++ b/Telegram/SourceFiles/ui/widgets/buttons.cpp @@ -542,14 +542,14 @@ void LeftOutlineButton::paintEvent(QPaintEvent *e) { CrossButton::CrossButton(QWidget *parent, const style::CrossButton &st) : RippleButton(parent, st.ripple) , _st(st) -, _a_loading([=](crl::time duration) { return loadingCallback(duration); }) { +, _loadingAnimation([=](crl::time now) { return loadingCallback(now); }) { resize(_st.width, _st.height); setCursor(style::cur_pointer); setVisible(false); } -bool CrossButton::loadingCallback(crl::time duration) { - const auto result = !stopLoadingAnimation(duration); +bool CrossButton::loadingCallback(crl::time now) { + const auto result = !stopLoadingAnimation(now); if (!result || !anim::Disabled()) { update(); } @@ -563,7 +563,7 @@ void CrossButton::toggle(bool visible, anim::type animated) { if (isHidden()) { setVisible(true); } - _a_show.start( + _showAnimation.start( [=] { animationCallback(); }, _shown ? 0. : 1., _shown ? 1. : 0., @@ -577,7 +577,7 @@ void CrossButton::toggle(bool visible, anim::type animated) { void CrossButton::animationCallback() { update(); - if (!_a_show.animating()) { + if (!_showAnimation.animating()) { setVisible(_shown); } } @@ -585,18 +585,17 @@ void CrossButton::animationCallback() { void CrossButton::paintEvent(QPaintEvent *e) { Painter p(this); - auto ms = crl::now(); + auto now = crl::now(); auto over = isOver(); - auto shown = _a_show.value(_shown ? 1. : 0.); + auto shown = _showAnimation.value(_shown ? 1. : 0.); p.setOpacity(shown); - paintRipple(p, _st.crossPosition.x(), _st.crossPosition.y(), ms); + paintRipple(p, _st.crossPosition.x(), _st.crossPosition.y(), now); auto loading = 0.; - if (_a_loading.animating()) { - const auto duration = (ms - _a_loading.started()); - if (stopLoadingAnimation(duration)) { - _a_loading.stop(); + if (_loadingAnimation.animating()) { + if (stopLoadingAnimation(now)) { + _loadingAnimation.stop(); } else if (anim::Disabled()) { CrossAnimation::paintStaticLoading( p, @@ -608,8 +607,8 @@ void CrossButton::paintEvent(QPaintEvent *e) { shown); return; } else { - loading = (duration % _st.loadingPeriod) - / float64(_st.loadingPeriod); + loading = ((now - _loadingAnimation.started()) + % _st.loadingPeriod) / float64(_st.loadingPeriod); } } CrossAnimation::paint( @@ -623,13 +622,14 @@ void CrossButton::paintEvent(QPaintEvent *e) { loading); } -bool CrossButton::stopLoadingAnimation(crl::time duration) { +bool CrossButton::stopLoadingAnimation(crl::time now) { if (!_loadingStopMs) { 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; - const auto currentPeriod = duration / _st.loadingPeriod; if (currentPeriod != stopPeriod) { Assert(currentPeriod > stopPeriod); return true; @@ -640,13 +640,14 @@ bool CrossButton::stopLoadingAnimation(crl::time duration) { void CrossButton::setLoadingAnimation(bool enabled) { if (enabled) { _loadingStopMs = 0; - if (!_a_loading.animating()) { - _a_loading.start(); + if (!_loadingAnimation.animating()) { + _loadingAnimation.start(); } - } else if (_a_loading.animating()) { + } else if (_loadingAnimation.animating()) { _loadingStopMs = crl::now(); - if (!((_loadingStopMs - _a_loading.started()) % _st.loadingPeriod)) { - _a_loading.stop(); + if (!((_loadingStopMs - _loadingAnimation.started()) + % _st.loadingPeriod)) { + _loadingAnimation.stop(); } } if (anim::Disabled()) { diff --git a/Telegram/SourceFiles/ui/widgets/buttons.h b/Telegram/SourceFiles/ui/widgets/buttons.h index ab04ba799b..3b6e4f3eb9 100644 --- a/Telegram/SourceFiles/ui/widgets/buttons.h +++ b/Telegram/SourceFiles/ui/widgets/buttons.h @@ -217,7 +217,7 @@ public: return toggle(false, animated); } void finishAnimating() { - _a_show.stop(); + _showAnimation.stop(); animationCallback(); } @@ -235,17 +235,17 @@ protected: QPoint prepareRippleStartPosition() const override; private: - bool loadingCallback(crl::time duration); - bool stopLoadingAnimation(crl::time duration); + bool loadingCallback(crl::time now); + bool stopLoadingAnimation(crl::time now); void animationCallback(); const style::CrossButton &_st; bool _shown = false; - Ui::Animations::Simple _a_show; + Ui::Animations::Simple _showAnimation; crl::time _loadingStopMs = 0; - Ui::Animations::Basic _a_loading; + Ui::Animations::Basic _loadingAnimation; }; diff --git a/Telegram/SourceFiles/ui/widgets/continuous_sliders.cpp b/Telegram/SourceFiles/ui/widgets/continuous_sliders.cpp index ff3bf3c3b4..1a7e56c981 100644 --- a/Telegram/SourceFiles/ui/widgets/continuous_sliders.cpp +++ b/Telegram/SourceFiles/ui/widgets/continuous_sliders.cpp @@ -148,7 +148,7 @@ void ContinuousSlider::setOver(bool over) { _over = over; 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) diff --git a/Telegram/SourceFiles/ui/widgets/continuous_sliders.h b/Telegram/SourceFiles/ui/widgets/continuous_sliders.h index 1a7073796a..80c7e41948 100644 --- a/Telegram/SourceFiles/ui/widgets/continuous_sliders.h +++ b/Telegram/SourceFiles/ui/widgets/continuous_sliders.h @@ -72,7 +72,7 @@ protected: return _receivedTill; } float64 getCurrentOverFactor() { - return _disabled ? 0. : _a_over.value(_over ? 1. : 0.); + return _disabled ? 0. : _overAnimation.value(_over ? 1. : 0.); } Direction getDirection() const { return _direction; @@ -104,7 +104,7 @@ private: Fn _changeFinishedCallback; bool _over = false; - Ui::Animations::Simple _a_over; + Ui::Animations::Simple _overAnimation; float64 _value = 0.; float64 _receivedTill = 0.; diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.cpp b/Telegram/SourceFiles/ui/widgets/input_fields.cpp index fe77b928c1..9eecc41bf8 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.cpp +++ b/Telegram/SourceFiles/ui/widgets/input_fields.cpp @@ -972,7 +972,7 @@ void FlatInput::paintEvent(QPaintEvent *e) { Painter p(this); 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); pen.setWidth(_st.borderWidth); p.setPen(pen); @@ -986,7 +986,8 @@ void FlatInput::paintEvent(QPaintEvent *e) { _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.) { p.setOpacity(placeholderOpacity); @@ -1006,7 +1007,7 @@ void FlatInput::paintEvent(QPaintEvent *e) { void FlatInput::focusInEvent(QFocusEvent *e) { if (!_focused) { _focused = true; - _a_placeholderFocused.start( + _placeholderFocusedAnimation.start( [=] { update(); }, 0., 1., @@ -1020,7 +1021,7 @@ void FlatInput::focusInEvent(QFocusEvent *e) { void FlatInput::focusOutEvent(QFocusEvent *e) { if (_focused) { _focused = false; - _a_placeholderFocused.start( + _placeholderFocusedAnimation.start( [=] { update(); }, 1., 0., @@ -1076,7 +1077,7 @@ void FlatInput::updatePlaceholder() { auto placeholderVisible = !hasText; if (_placeholderVisible != placeholderVisible) { _placeholderVisible = placeholderVisible; - _a_placeholderVisible.start( + _placeholderVisibleAnimation.start( [=] { update(); }, _placeholderVisible ? 0. : 1., _placeholderVisible ? 1. : 0., diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.h b/Telegram/SourceFiles/ui/widgets/input_fields.h index c4e7365335..e1327995be 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.h +++ b/Telegram/SourceFiles/ui/widgets/input_fields.h @@ -111,8 +111,8 @@ private: bool _focused = false; bool _placeholderVisible = true; - Animations::Simple _a_placeholderFocused; - Animations::Simple _a_placeholderVisible; + Animations::Simple _placeholderFocusedAnimation; + Animations::Simple _placeholderVisibleAnimation; bool _lastPreEditTextNotEmpty = false; const style::FlatInput &_st;