ZaStoGram_desktop/Telegram/SourceFiles/main/main_domain.h
loop-uh 0fd5d76a67 Merge upstream v7.3.1
Слияние с tdesktop от 64ca5475f2 до тега v7.3.1 (7.2.10 beta, 7.3, 7.3.1).

- Версия 7.3.1 (7003001), BetaChannel 0, комментарий ZaStoGram сохранён.
- Обновлятор: оригинал убрал пакеты v1 (RSA), а наш Packer и Forgejo
  выпускают именно их. v1 оставлен как UnpackUpdateV1 рядом с v2 и
  использует новые проверенные распаковку и извлечение файлов.
- mtproto: исправления импорта авторизации из оригинала перенесены в нашу
  структуру RequestRegistry; пути include новых файлов кошелька
  приведены к нашей раскладке mtproto/.
- prepare.py: стадии оригинала (ucrt64, ffmpeg 8, openssl 3.5, libheif,
  Rust, wallet-engine) с нашими skip-debug и patches_extra.
- lib_ui, lib_lottie: форки слиты с версиями из v7.3.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:43:47 +03:00

176 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/timer.h"
#include "base/weak_ptr.h"
namespace Storage {
class Domain;
class PasscodeDerivation;
enum class StartResult : uchar;
} // namespace Storage
namespace MTP {
enum class Environment : uchar;
class ProxyEndpointContext;
} // namespace MTP
namespace Wallet {
class VaultRuntime;
} // namespace Wallet
namespace Main {
class Account;
class Session;
class Domain final : public base::has_weak_ptr {
public:
struct AccountWithIndex {
int index = 0;
std::unique_ptr<Account> account;
};
static constexpr auto kMaxAccounts = 100;
static constexpr auto kPremiumMaxAccounts = 100;
explicit Domain(const QString &dataName);
~Domain();
[[nodiscard]] bool started() const;
[[nodiscard]] Storage::StartResult start(const QByteArray &passcode);
// One passcode attempt at a time for the whole application: while the
// derivation runs on a worker this returns true, and every further call
// answers false without starting anything or ever invoking its done.
// The verdict is applied here on the main thread - a cold attempt starts
// the domain, a warm one only checks the passcode - and done(correct)
// runs last. An attempt whose started-ness changed underneath it (the
// lock screen's Log out started the domain from scratch, or finish() ran
// during shutdown) applies nothing and reports the passcode incorrect.
// An attempt answered while the application is quitting applies nothing
// and drops its done as well: finish() leaves a cold domain as unstarted
// as it found it, so started-ness alone cannot tell a quitting cold
// attempt from one that should start every account. An attempt that
// outlives the domain is dropped together with its done.
[[nodiscard]] bool tryPasscode(
const QByteArray &passcode,
Fn<void(bool correct)> done);
void resetWithForgottenPasscode();
void finish();
[[nodiscard]] int maxAccounts() const;
[[nodiscard]] rpl::producer<int> maxAccountsChanges() const;
[[nodiscard]] Storage::Domain &local() const {
return *_local;
}
[[nodiscard]] auto proxyEndpointContext() const
-> std::shared_ptr<MTP::ProxyEndpointContext> {
return _proxyEndpointContext;
}
[[nodiscard]] Wallet::VaultRuntime &walletKeyring();
[[nodiscard]] auto accounts() const
-> const std::vector<AccountWithIndex> &;
[[nodiscard]] std::vector<not_null<Account*>> orderedAccounts() const;
[[nodiscard]] rpl::producer<Account*> activeValue() const;
[[nodiscard]] rpl::producer<> accountsChanges() const;
[[nodiscard]] Account *maybeLastOrSomeAuthedAccount();
[[nodiscard]] int accountsAuthedCount() const;
// Expects(started());
[[nodiscard]] Account &active() const;
[[nodiscard]] rpl::producer<not_null<Account*>> activeChanges() const;
[[nodiscard]] rpl::producer<Session*> activeSessionValue() const;
[[nodiscard]] rpl::producer<Session*> activeSessionChanges() const;
[[nodiscard]] int unreadBadge() const;
[[nodiscard]] bool unreadBadgeMuted() const;
[[nodiscard]] rpl::producer<> unreadBadgeChanges() const;
void notifyUnreadBadgeChanged();
[[nodiscard]] not_null<Main::Account*> add(MTP::Environment environment);
void maybeActivate(not_null<Main::Account*> account);
void activate(not_null<Main::Account*> account);
void addActivated(MTP::Environment environment, bool newWindow = false);
// Drops session-less accounts that have no window open for them.
void removeRedundantAccounts();
// Interface for Storage::Domain.
void accountAddedInStorage(AccountWithIndex accountWithIndex);
void activateFromStorage(int index);
[[nodiscard]] int activeForStorage() const;
private:
[[nodiscard]] Storage::StartResult startWith(
Storage::PasscodeDerivation derived);
void activateAfterStarting();
void closeAccountWindows(not_null<Main::Account*> account);
// Answers whether a removal ran whose checked write already persisted
// the current accounts info - not whether a passcode is gone, which
// would make the no-passcode case skip the caller's accounts write.
bool removePasscodeIfEmpty();
// True when a completed last logout has left the passcode guarding
// nothing that can still be asked for: one account, its session gone,
// and a passcode still installed. The one definition both the logout
// call site and the retry read.
[[nodiscard]] bool passcodeRemovalAuthorized() const;
bool clearPasscodeAfterLastLogout();
void reportFailedPasscodeClear();
// Retries the removal a completed last logout authorized, after its
// checked write did not reach the disk. The authorization is re-read
// here and never carried over from the failed attempt, so a passcode
// already gone, an account signed in again or a second account all
// make this do nothing at all. Answers whether this call removed the
// passcode, so the caller can say so.
[[nodiscard]] bool finishPasscodeClearAfterReset();
void watchSession(not_null<Account*> account);
void scheduleWriteAccounts();
void checkForLastProductionConfig(not_null<Main::Account*> account);
void updateUnreadBadge();
void scheduleUpdateUnreadBadge();
void suggestExportIfNeeded();
const QString _dataName;
const std::unique_ptr<Storage::Domain> _local;
const std::shared_ptr<MTP::ProxyEndpointContext> _proxyEndpointContext;
std::shared_ptr<Wallet::VaultRuntime> _walletKeyring;
std::vector<AccountWithIndex> _accounts;
rpl::event_stream<> _accountsChanges;
rpl::variable<Account*> _active = nullptr;
int _accountToActivate = -1;
int _lastActiveIndex = -1;
bool _writeAccountsScheduled = false;
rpl::event_stream<Session*> _activeSessions;
rpl::event_stream<> _unreadBadgeChanges;
int _unreadBadge = 0;
bool _unreadBadgeMuted = true;
bool _unreadBadgeUpdateScheduled = false;
bool _passcodeDeriving = false;
rpl::variable<int> _lastMaxAccounts;
rpl::lifetime _activeLifetime;
rpl::lifetime _lifetime;
};
} // namespace Main