mirror of https://github.com/procxx/kepka.git
Add new animations engine.
This commit is contained in:
parent
92332b45ea
commit
9a616edf2a
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue