Add new animations engine.

This commit is contained in:
John Preston 2019-02-04 16:34:50 +03:00
parent 92332b45ea
commit 9a616edf2a
19 changed files with 514 additions and 77 deletions

View File

@ -117,10 +117,9 @@ namespace App {
}
MainWindow *wnd() {
if (Core::Sandbox::Instance().applicationLaunched()) {
return Core::App().getActiveWindow();
}
return nullptr;
return Core::IsAppLaunched()
? Core::App().getActiveWindow()
: nullptr;
}
MainWidget *main() {

View File

@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "core/application.h"
#include "core/sandbox.h"
#include "core/changelogs.h"
#include "storage/file_download.h"
#include "storage/file_upload.h"
@ -430,8 +429,7 @@ AuthSession::AuthSession(const MTPUser &user)
}
bool AuthSession::Exists() {
return Core::Sandbox::Instance().applicationLaunched()
&& (Core::App().authSession() != nullptr);
return Core::IsAppLaunched() && (Core::App().authSession() != nullptr);
}
base::Observable<void> &AuthSession::downloaderTaskFinished() {

View File

@ -784,7 +784,7 @@ void BackgroundPreviewBox::elementAnimationAutoplayAsync(
crl::time BackgroundPreviewBox::elementHighlightTime(
not_null<const Element*> element) {
return crl::time();
return crl::time(0);
}
bool BackgroundPreviewBox::elementInSelectionMode() {

View File

@ -47,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "ui/text_options.h"
#include "ui/emoji_config.h"
#include "ui/effects/animations.h"
#include "storage/serialize_common.h"
#include "window/window_controller.h"
#include "base/qthelp_regex.h"
@ -63,6 +64,8 @@ constexpr auto kQuitPreventTimeoutMs = 1500;
} // namespace
Application *Application::Instance = nullptr;
struct Application::Private {
UserId authSessionUserId = 0;
QByteArray authSessionUserSerialized;
@ -78,12 +81,16 @@ Application::Application(not_null<Launcher*> launcher)
, _launcher(launcher)
, _private(std::make_unique<Private>())
, _databases(std::make_unique<Storage::Databases>())
, _animationsManager(std::make_unique<Ui::Animations::Manager>())
, _langpack(std::make_unique<Lang::Instance>())
, _audio(std::make_unique<Media::Audio::Instance>())
, _logo(Window::LoadLogo())
, _logoNoMargin(Window::LoadLogoNoMargin()) {
Expects(!_logo.isNull());
Expects(!_logoNoMargin.isNull());
Expects(Instance == nullptr);
Instance = this;
}
void Application::run() {
@ -1157,10 +1164,18 @@ Application::~Application() {
Local::finish();
Global::finish();
ThirdParty::finish();
Instance = nullptr;
}
bool IsAppLaunched() {
return (Application::Instance != nullptr);
}
Application &App() {
return Sandbox::Instance().application();
Expects(Application::Instance != nullptr);
return *Application::Instance;
}
} // namespace Core

View File

@ -30,6 +30,12 @@ namespace App {
void quit();
} // namespace App
namespace Ui {
namespace Animations {
class Manager;
} // namespace Animations
} // namespace Ui
namespace MTP {
class DcOptions;
class Instance;
@ -74,6 +80,10 @@ public:
void run();
Ui::Animations::Manager &animationManager() const {
return *_animationsManager;
}
// Windows interface.
MainWindow *getActiveWindow() const;
bool closeActiveWindow();
@ -222,6 +232,9 @@ protected:
bool eventFilter(QObject *object, QEvent *event) override;
private:
friend bool IsAppLaunched();
friend Application &App();
void destroyMtpKeys(MTP::AuthKeysList &&keys);
void allKeysDestroyed();
@ -239,6 +252,8 @@ private:
void clearPasscodeLock();
void loggedOut();
static Application *Instance;
not_null<Launcher*> _launcher;
// Some fields are just moved from the declaration.
@ -247,10 +262,11 @@ private:
QWidget _globalShortcutParent;
std::unique_ptr<Storage::Databases> _databases;
const std::unique_ptr<Storage::Databases> _databases;
const std::unique_ptr<Ui::Animations::Manager> _animationsManager;
std::unique_ptr<MainWindow> _window;
std::unique_ptr<Media::View::OverlayWidget> _mediaView;
std::unique_ptr<Lang::Instance> _langpack;
const std::unique_ptr<Lang::Instance> _langpack;
std::unique_ptr<Lang::CloudManager> _langCloudManager;
std::unique_ptr<Lang::Translator> _translator;
std::unique_ptr<MTP::DcOptions> _dcOptions;
@ -261,9 +277,9 @@ private:
base::Observable<void> _passcodedChanged;
QPointer<BoxContent> _badProxyDisableBox;
std::unique_ptr<Media::Audio::Instance> _audio;
QImage _logo;
QImage _logoNoMargin;
const std::unique_ptr<Media::Audio::Instance> _audio;
const QImage _logo;
const QImage _logoNoMargin;
rpl::variable<bool> _passcodeLock;
rpl::event_stream<bool> _termsLockChanges;
@ -289,6 +305,7 @@ private:
};
Application &App();
[[nodiscard]] bool IsAppLaunched();
[[nodiscard]] Application &App();
} // namespace Core

View File

@ -13,15 +13,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localstorage.h"
#include "window/notifications_manager.h"
#include "core/crash_reports.h"
#include "core/crash_report_window.h"
#include "core/application.h"
#include "core/launcher.h"
#include "core/local_url_handlers.h"
#include "core/update_checker.h"
#include "base/timer.h"
#include "base/concurrent_timer.h"
#include "base/qthelp_url.h"
#include "base/qthelp_regex.h"
#include "core/update_checker.h"
#include "core/crash_report_window.h"
#include "ui/effects/animations.h"
namespace Core {
namespace {
@ -498,6 +499,10 @@ bool Sandbox::notify(QObject *receiver, QEvent *e) {
}
const auto wrap = createEventNestingLevel();
const auto type = e->type();
if ((type == QEvent::UpdateRequest) && _application) {
_application->animationManager().update();
}
return QApplication::notify(receiver, e);
}

View File

@ -47,15 +47,6 @@ public:
return *static_cast<Sandbox*>(QApplication::instance());
}
bool applicationLaunched() const {
return _application != nullptr;
}
Application &application() const {
Expects(_application != nullptr);
return *_application;
}
~Sandbox();
protected:

View File

@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/bytes.h"
#include "storage/localstorage.h"
#include "core/application.h"
#include "core/sandbox.h"
#include "mainwindow.h"
#include "core/click_handler_types.h"
#include "info/info_memento.h"
@ -1384,7 +1383,7 @@ Updater::~Updater() {
UpdateChecker::UpdateChecker()
: _updater(GetUpdaterInstance()) {
if (Sandbox::Instance().applicationLaunched()) {
if (IsAppLaunched()) {
if (const auto mtproto = Core::App().mtp()) {
_updater->setMtproto(mtproto);
}

View File

@ -9,15 +9,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localstorage.h"
#include "core/application.h"
#include "core/sandbox.h"
namespace MTP {
namespace internal {
namespace {
//namespace {
int PauseLevel = 0;
} // namespace
//} // namespace
bool paused() {
return PauseLevel > 0;
@ -39,9 +38,7 @@ void unpause() {
} // namespace internal
Instance *MainInstance() {
return Core::Sandbox::Instance().applicationLaunched()
? Core::App().mtp()
: nullptr;
return Core::IsAppLaunched() ? Core::App().mtp() : nullptr;
}
} // namespace MTP

View File

@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h"
#include "mainwidget.h"
#include "core/application.h"
#include "core/sandbox.h"
#include "core/crash_reports.h"
#include "storage/localstorage.h"
#include "media/audio/media_audio.h"
@ -142,13 +141,11 @@ ApplicationDelegate *_sharedDelegate = nil;
- (void) applicationDidBecomeActive:(NSNotification *)aNotification {
ApplicationIsActive = true;
if (Core::Sandbox::Instance().applicationLaunched()) {
if (!_ignoreActivation) {
Core::App().handleAppActivated();
if (auto window = App::wnd()) {
if (window->isHidden()) {
window->showFromTray();
}
if (Core::IsAppLaunched() && !_ignoreActivation) {
Core::App().handleAppActivated();
if (auto window = App::wnd()) {
if (window->isHidden()) {
window->showFromTray();
}
}
}
@ -159,7 +156,7 @@ ApplicationDelegate *_sharedDelegate = nil;
}
- (void) receiveWakeNote:(NSNotification*)aNotification {
if (Core::Sandbox::Instance().applicationLaunched()) {
if (Core::IsAppLaunched()) {
Core::App().checkLocalTime();
}

View File

@ -594,7 +594,7 @@ void ConfirmContactBox::elementAnimationAutoplayAsync(
crl::time ConfirmContactBox::elementHighlightTime(
not_null<const Element*> element) {
return crl::time();
return crl::time(0);
}
bool ConfirmContactBox::elementInSelectionMode() {

View File

@ -0,0 +1,122 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "ui/effects/animations.h"
#include "core/application.h"
namespace Ui {
namespace Animations {
namespace {
constexpr auto kAnimationTimeout = crl::time(1000) / 60;
constexpr auto kIgnoreUpdatesTimeout = crl::time(4);
} // namespace
void Basic::start() {
if (!animating()) {
Core::App().animationManager().start(this);
}
_started = crl::now();
}
void Basic::stop() {
if (animating()) {
Core::App().animationManager().stop(this);
_started = -1;
}
}
void Manager::start(not_null<Basic*> animation) {
if (_updating) {
_starting.push_back(animation);
} else {
if (empty(_active)) {
updateQueued();
}
_active.push_back(animation);
}
}
void Manager::stop(not_null<Basic*> animation) {
if (empty(_active)) {
return;
}
if (_updating) {
const auto i = ranges::find(_active, animation.get());
if (i != end(_active)) {
*i = nullptr;
}
return;
}
_active.erase(ranges::remove(_active, animation.get()), end(_active));
if (empty(_active)) {
stopTimer();
}
}
void Manager::update() {
if (_active.empty() || _updating || _scheduled) {
return;
}
const auto now = crl::now();
if (_lastUpdateTime + kIgnoreUpdatesTimeout >= now) {
return;
}
schedule();
_updating = true;
const auto guard = gsl::finally([&] { _updating = false; });
_lastUpdateTime = now;
_active.erase(ranges::remove_if(_active, [&](Basic *element) {
return !element || !element->call(now);
}), end(_active));
if (!empty(_starting)) {
auto starting = std::move(_starting);
_active.insert(end(_active), begin(starting), end(starting));
}
}
void Manager::updateQueued() {
InvokeQueued(this, [=] { update(); });
}
void Manager::schedule() {
if (_scheduled) {
return;
}
stopTimer();
_scheduled = true;
Ui::PostponeCall([=] {
_scheduled = false;
const auto next = _lastUpdateTime + kAnimationTimeout;
const auto now = crl::now();
if (now < next) {
_timerId = startTimer(next - now, Qt::PreciseTimer);
} else {
updateQueued();
}
});
}
void Manager::stopTimer() {
if (_timerId) {
killTimer(base::take(_timerId));
}
}
void Manager::timerEvent(QTimerEvent *e) {
update();
}
} // namespace Animations
} // namespace Ui

View File

@ -0,0 +1,287 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Ui {
namespace Animations {
class Manager;
class Basic final {
public:
Basic() = default;
template <typename Callback>
explicit Basic(Callback &&callback);
template <typename Callback>
void init(Callback &&callback);
void start();
void stop();
[[nodiscard]] bool animating() const;
~Basic();
private:
friend class Manager;
template <typename Callback>
[[nodiscard]] static Fn<bool(crl::time)> Prepare(Callback &&callback);
[[nodiscard]] bool call(crl::time now) const;
crl::time _started = -1;
Fn<bool(crl::time)> _callback;
};
class Simple final {
public:
template <typename Callback>
void start(
Callback &&callback,
float64 from,
float64 to,
crl::time duration,
anim::transition transition = anim::linear);
void stop();
[[nodiscard]] bool animating() const;
[[nodiscard]] float64 value(float64 final) const;
private:
struct Data {
explicit Data(float64 initial) : value(initial) {
}
~Data() {
if (markOnDelete) {
*markOnDelete = true;
}
}
Basic animation;
anim::transition transition;
float64 from = 0.;
float64 delta = 0.;
float64 value = 0.;
float64 duration = 0.;
bool *markOnDelete = nullptr;
MTP::PauseHolder pause;
};
template <typename Callback>
[[nodiscard]] static decltype(auto) Prepare(Callback &&callback);
void prepare(float64 from, crl::time duration);
void startPrepared(
float64 to,
crl::time duration,
anim::transition transition);
static constexpr auto kLongAnimationDuration = crl::time(1000);
mutable std::unique_ptr<Data> _data;
};
class Manager final : private QObject {
public:
void update();
private:
friend class Basic;
void timerEvent(QTimerEvent *e) override;
void start(not_null<Basic*> animation);
void stop(not_null<Basic*> animation);
void schedule();
void updateQueued();
void stopTimer();
crl::time _lastUpdateTime = 0;
int _timerId = 0;
bool _updating = false;
bool _scheduled = false;
std::vector<Basic*> _active;
std::vector<not_null<Basic*>> _starting;
};
template <typename Callback>
inline Fn<bool(crl::time)> Basic::Prepare(Callback &&callback) {
if constexpr (rpl::details::is_callable_plain_v<Callback, crl::time>) {
using Return = decltype(callback(crl::time(0)));
if constexpr (std::is_convertible_v<Return, bool>) {
return std::forward<Callback>(callback);
} else if constexpr (std::is_same_v<Return, void>) {
return [callback = std::forward<Callback>(callback)](
crl::time time) {
callback(time);
return true;
};
} else {
static_assert(false_t(callback), "Expected void or bool.");
}
} else if constexpr (rpl::details::is_callable_plain_v<Callback>) {
using Return = decltype(callback());
if constexpr (std::is_convertible_v<Return, bool>) {
return [callback = std::forward<Callback>(callback)](crl::time) {
return callback();
};
} else if constexpr (std::is_same_v<Return, void>) {
return [callback = std::forward<Callback>(callback)](crl::time) {
callback();
return true;
};
} else {
static_assert(false_t(callback), "Expected void or bool.");
}
} else {
static_assert(false_t(callback), "Expected crl::time or no args.");
}
}
template <typename Callback>
inline Basic::Basic(Callback &&callback)
: _callback(Prepare(std::forward<Callback>(callback))) {
}
template <typename Callback>
inline void Basic::init(Callback &&callback) {
_callback = Prepare(std::forward<Callback>(callback));
}
TG_FORCE_INLINE bool Basic::animating() const {
return (_started >= 0);
}
TG_FORCE_INLINE bool Basic::call(crl::time now) const {
const auto onstack = _callback;
return onstack(now - _started);
}
inline Basic::~Basic() {
stop();
}
template <typename Callback>
decltype(auto) Simple::Prepare(Callback &&callback) {
if constexpr (rpl::details::is_callable_plain_v<Callback, float64>) {
using Return = decltype(callback(float64(0.)));
if constexpr (std::is_convertible_v<Return, bool>) {
return std::forward<Callback>(callback);
} else if constexpr (std::is_same_v<Return, void>) {
return [callback = std::forward<Callback>(callback)](
float64 value) {
callback(value);
return true;
};
} else {
static_assert(false_t(callback), "Expected void or float64.");
}
} else if constexpr (rpl::details::is_callable_plain_v<Callback>) {
using Return = decltype(callback());
if constexpr (std::is_convertible_v<Return, bool>) {
return [callback = std::forward<Callback>(callback)](float64) {
return callback();
};
} else if constexpr (std::is_same_v<Return, void>) {
return [callback = std::forward<Callback>(callback)](float64) {
callback();
return true;
};
} else {
static_assert(false_t(callback), "Expected void or bool.");
}
} else {
static_assert(false_t(callback), "Expected float64 or no args.");
}
}
template <typename Callback>
inline void Simple::start(
Callback &&callback,
float64 from,
float64 to,
crl::time duration,
anim::transition transition) {
prepare(from, duration);
_data->animation.init([
that = _data.get(),
callback = Prepare(std::forward<Callback>(callback))
](crl::time time) {
const auto finished = (time >= that->duration);
const auto progress = finished
? that->delta
: that->transition(that->delta, time / that->duration);
that->value = that->from + progress;
if (finished) {
that->animation.stop();
}
auto deleted = false;
that->markOnDelete = &deleted;
const auto result = callback(that->value) && !finished;
if (!deleted) {
that->markOnDelete = nullptr;
if (!result) {
that->pause.release();
}
}
return result;
});
startPrepared(to, duration, transition);
}
inline void Simple::prepare(float64 from, crl::time duration) {
const auto isLong = (duration >= kLongAnimationDuration);
if (!_data) {
_data = std::make_unique<Data>(from);
} else if (!isLong) {
_data->pause.restart();
}
if (isLong) {
_data->pause.release();
}
}
inline void Simple::stop() {
_data = nullptr;
}
inline bool Simple::animating() const {
if (!_data) {
return false;
} else if (!_data->animation.animating()) {
_data = nullptr;
return false;
}
return true;
}
TG_FORCE_INLINE float64 Simple::value(float64 final) const {
return animating() ? _data->value : final;
}
inline void Simple::startPrepared(
float64 to,
crl::time duration,
anim::transition transition) {
_data->from = _data->value;
_data->delta = to - _data->from;
_data->duration = duration;
_data->transition = transition;
_data->animation.start();
}
} // namespace Animations
} // namespace Ui

View File

@ -542,19 +542,18 @@ void LeftOutlineButton::paintEvent(QPaintEvent *e) {
CrossButton::CrossButton(QWidget *parent, const style::CrossButton &st) : RippleButton(parent, st.ripple)
, _st(st)
, _a_loading(animation(this, &CrossButton::step_loading)) {
, _a_loading([=](crl::time duration) { return loadingCallback(duration); }) {
resize(_st.width, _st.height);
setCursor(style::cur_pointer);
setVisible(false);
}
void CrossButton::step_loading(crl::time ms, bool timer) {
if (stopLoadingAnimation(ms)) {
_a_loading.stop();
update();
} else if (timer && !anim::Disabled()) {
bool CrossButton::loadingCallback(crl::time duration) {
const auto result = !stopLoadingAnimation(duration);
if (!result || !anim::Disabled()) {
update();
}
return result;
}
void CrossButton::toggle(bool visible, anim::type animated) {
@ -565,7 +564,7 @@ void CrossButton::toggle(bool visible, anim::type animated) {
setVisible(true);
}
_a_show.start(
[this] { animationCallback(); },
[=] { animationCallback(); },
_shown ? 0. : 1.,
_shown ? 1. : 0.,
_st.duration);
@ -588,14 +587,15 @@ void CrossButton::paintEvent(QPaintEvent *e) {
auto ms = crl::now();
auto over = isOver();
auto shown = _a_show.current(ms, _shown ? 1. : 0.);
auto shown = _a_show.value(_shown ? 1. : 0.);
p.setOpacity(shown);
paintRipple(p, _st.crossPosition.x(), _st.crossPosition.y(), ms);
auto loading = 0.;
if (_a_loading.animating()) {
if (stopLoadingAnimation(ms)) {
const auto duration = (ms - _loadingStartMs);
if (stopLoadingAnimation(duration)) {
_a_loading.stop();
} else if (anim::Disabled()) {
CrossAnimation::paintStaticLoading(
@ -608,7 +608,7 @@ void CrossButton::paintEvent(QPaintEvent *e) {
shown);
return;
} else {
loading = ((ms - _loadingStartMs) % _st.loadingPeriod)
loading = (duration % _st.loadingPeriod)
/ float64(_st.loadingPeriod);
}
}
@ -623,12 +623,13 @@ void CrossButton::paintEvent(QPaintEvent *e) {
loading);
}
bool CrossButton::stopLoadingAnimation(crl::time ms) {
bool CrossButton::stopLoadingAnimation(crl::time duration) {
if (!_loadingStopMs) {
return false;
}
auto stopPeriod = (_loadingStopMs - _loadingStartMs) / _st.loadingPeriod;
auto currentPeriod = (ms - _loadingStartMs) / _st.loadingPeriod;
const auto stopPeriod = (_loadingStopMs - _loadingStartMs)
/ _st.loadingPeriod;
const auto currentPeriod = duration / _st.loadingPeriod;
if (currentPeriod != stopPeriod) {
Assert(currentPeriod > stopPeriod);
return true;

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "ui/abstract_button.h"
#include "ui/effects/animations.h"
#include "styles/style_widgets.h"
#include <memory>
@ -216,7 +217,7 @@ public:
return toggle(false, animated);
}
void finishAnimating() {
_a_show.finish();
_a_show.stop();
animationCallback();
}
@ -234,18 +235,18 @@ protected:
QPoint prepareRippleStartPosition() const override;
private:
void step_loading(crl::time ms, bool timer);
bool stopLoadingAnimation(crl::time ms);
bool loadingCallback(crl::time duration);
bool stopLoadingAnimation(crl::time duration);
void animationCallback();
const style::CrossButton &_st;
bool _shown = false;
Animation _a_show;
Ui::Animations::Simple _a_show;
crl::time _loadingStartMs = 0;
crl::time _loadingStopMs = 0;
BasicAnimation _a_loading;
Ui::Animations::Basic _a_loading;
};

View File

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

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "ui/rp_widget.h"
#include "ui/effects/animations.h"
#include "styles/style_widgets.h"
class UserData;
@ -110,8 +111,8 @@ private:
bool _focused = false;
bool _placeholderVisible = true;
Animation _a_placeholderFocused;
Animation _a_placeholderVisible;
Animations::Simple _a_placeholderFocused;
Animations::Simple _a_placeholderVisible;
bool _lastPreEditTextNotEmpty = false;
const style::FlatInput &_st;

View File

@ -16,7 +16,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/confirm_box.h"
#include "core/click_handler_types.h"
#include "core/application.h"
#include "core/sandbox.h"
#include "lang/lang_keys.h"
#include "data/data_session.h"
#include "auth_session.h"
@ -87,12 +86,7 @@ void ConvertIconToBlack(QImage &image) {
}
QIcon CreateOfficialIcon() {
auto image = [&] {
if (Core::Sandbox::Instance().applicationLaunched()) {
return Core::App().logo();
}
return LoadLogo();
}();
auto image = Core::IsAppLaunched() ? Core::App().logo() : LoadLogo();
if (AuthSession::Exists() && Auth().supportMode()) {
ConvertIconToBlack(image);
}

View File

@ -671,6 +671,8 @@
<(src_loc)/support/support_helper.h
<(src_loc)/support/support_templates.cpp
<(src_loc)/support/support_templates.h
<(src_loc)/ui/effects/animations.cpp
<(src_loc)/ui/effects/animations.h
<(src_loc)/ui/effects/cross_animation.cpp
<(src_loc)/ui/effects/cross_animation.h
<(src_loc)/ui/effects/fade_animation.cpp