ZaStoGram_desktop/Telegram/SourceFiles/intro/intro_step.h
loop-uh 8575223c2b Merge remote-tracking branch 'upstream/dev' into dev
Upstream 7.0.6 with WebAuthn/passkey transports, the sticker creator and
image editor work, the thanos collapse-gap fixes and the split of the big
style files.

Conflicts kept our side by default, upstream taken where it fixes things:
- version files: upstream 7.0.6 numbers, our ZaStoGram naming and the
  stable-only comments;
- emoji_list_widget repaintCustom: upstream's guard that only remembers a
  set id when a section really matched, driving our animation scheduler;
- intro_qr: our retry timer next to upstream's stopped/restart handling,
  and the shown flag resets when the step is left;
- boxes.style: took upstream's split, moved our proxy settings metrics to
  connection_box.style;
- .agents/ stays out of version control.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 14:26:28 +03:00

237 lines
6 KiB
C++

/*
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
#include "base/object_ptr.h"
#include "mtproto/instance/sender.h"
#include "ui/text/text_variant.h"
#include "ui/rp_widget.h"
#include "ui/effects/animations.h"
namespace style {
struct RoundButton;
} // namespace style;
namespace Main {
class Account;
} // namespace Main;
namespace Ui {
class SlideAnimation;
class CrossFadeAnimation;
class FlatLabel;
template <typename Widget>
class FadeWrap;
} // namespace Ui
namespace Intro {
namespace details {
struct Data;
enum class StackAction;
enum class Animate;
class Step : public Ui::RpWidget {
public:
Step(
QWidget *parent,
not_null<Main::Account*> account,
not_null<Data*> data,
bool hasCover = false);
~Step();
QAccessible::Role accessibilityRole() override {
return QAccessible::Role::Dialog;
}
QString accessibilityName() override {
return _titleText.current();
}
QString accessibilityDescription() override {
return _descriptionText.current().text;
}
[[nodiscard]] Main::Account &account() const {
return *_account;
}
// It should not be called in StartWidget, in other steps it should be
// present and not changing.
[[nodiscard]] MTP::Sender &api() const;
void apiClear();
virtual void finishInit() {
}
virtual void setInnerFocus() {
setFocus();
}
void setGoCallback(
Fn<void(Step *step, StackAction action, Animate animate)> callback);
void setStepBelowCallback(Fn<Step*()> callback);
void setShowResetCallback(Fn<void()> callback);
void setShowTermsCallback(Fn<void()> callback);
void setCancelNearestDcCallback(Fn<void()> callback);
void setAcceptTermsCallback(
Fn<void(Fn<void()> callback)> callback);
void prepareShowAnimated(Step *after);
void showAnimated(Animate animate);
void showFast();
[[nodiscard]] bool animating() const;
void setShowAnimationClipping(QRect clipping);
[[nodiscard]] bool hasCover() const;
[[nodiscard]] virtual bool hasBack() const;
virtual void activate();
virtual void cancelled();
virtual void finished();
virtual void submit() = 0;
[[nodiscard]] virtual rpl::producer<QString> nextButtonText() const;
[[nodiscard]] virtual auto nextButtonStyle() const
-> rpl::producer<const style::RoundButton*>;
[[nodiscard]] virtual rpl::producer<> nextButtonFocusRequests() const;
[[nodiscard]] int contentLeft() const;
[[nodiscard]] int contentTop() const;
void setErrorCentered(bool centered);
void showError(rpl::producer<QString> text);
void hideError() {
showError(rpl::single(QString()));
}
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void setTitleText(rpl::producer<QString> titleText);
void setDescriptionText(v::text::data &&descriptionText);
bool paintAnimated(QPainter &p, QRect clip);
void fillSentCodeData(const MTPDauth_sentCode &type);
void showDescription();
void hideDescription();
[[nodiscard]] not_null<Data*> getData() const {
return _data;
}
void finish(const MTPauth_Authorization &auth, QImage &&photo = {});
void finish(const MTPUser &user, QImage &&photo = {});
void createSession(
const MTPUser &user,
QImage photo,
const QVector<MTPDialogFilter> &filters,
bool tagsEnabled);
void goBack();
template <typename StepType>
void goNext() {
goNext(new StepType(parentWidget(), _account, _data));
}
template <typename StepType>
void goNextOrBack() {
if (dynamic_cast<StepType*>(stepBelow())) {
goBack();
} else {
goNext<StepType>();
}
}
template <typename StepType>
void goReplace(Animate animate) {
goReplace(new StepType(parentWidget(), _account, _data), animate);
}
void showResetButton() {
if (_showResetCallback) _showResetCallback();
}
void showTerms() {
if (_showTermsCallback) _showTermsCallback();
}
void acceptTerms(Fn<void()> callback) {
if (_acceptTermsCallback) {
_acceptTermsCallback(callback);
}
}
void cancelNearestDcRequest() {
if (_cancelNearestDcCallback) _cancelNearestDcCallback();
}
virtual int errorTop() const;
private:
struct CoverAnimation {
CoverAnimation() = default;
CoverAnimation(CoverAnimation &&other) = default;
CoverAnimation &operator=(CoverAnimation &&other) = default;
~CoverAnimation();
std::unique_ptr<Ui::CrossFadeAnimation> title;
std::unique_ptr<Ui::CrossFadeAnimation> description;
// From content top till the next button top.
QPixmap contentSnapshotWas;
QPixmap contentSnapshotNow;
QRect clipping;
};
void updateLabelsPosition();
void paintContentSnapshot(
QPainter &p,
const QPixmap &snapshot,
float64 alpha,
float64 howMuchHidden);
void refreshError(const QString &text);
void goNext(Step *step);
void goReplace(Step *step, Animate animate);
[[nodiscard]] Step *stepBelow() const;
[[nodiscard]] CoverAnimation prepareCoverAnimation(Step *step);
[[nodiscard]] QPixmap prepareContentSnapshot();
[[nodiscard]] QPixmap prepareSlideAnimation();
void showFinished();
void prepareCoverMask();
void paintCover(QPainter &p, int top);
const not_null<Main::Account*> _account;
const not_null<Data*> _data;
mutable std::optional<MTP::Sender> _api;
bool _hasCover = false;
Fn<void(Step *step, StackAction action, Animate animate)> _goCallback;
Fn<Step*()> _stepBelowCallback;
Fn<void()> _showResetCallback;
Fn<void()> _showTermsCallback;
Fn<void()> _cancelNearestDcCallback;
Fn<void(Fn<void()> callback)> _acceptTermsCallback;
rpl::variable<QString> _titleText;
object_ptr<Ui::FlatLabel> _title;
rpl::variable<TextWithEntities> _descriptionText;
object_ptr<Ui::FadeWrap<Ui::FlatLabel>> _description;
bool _errorCentered = false;
rpl::variable<QString> _errorText;
object_ptr<Ui::FadeWrap<Ui::FlatLabel>> _error = { nullptr };
Ui::Animations::Simple _a_show;
CoverAnimation _coverAnimation;
std::unique_ptr<Ui::SlideAnimation> _slideAnimation;
QPixmap _coverMask;
};
} // namespace details
} // namespace Intro