mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Allow switching accounts from the main menu.
This commit is contained in:
parent
f129b6b90d
commit
5f238a71f9
9 changed files with 430 additions and 102 deletions
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_menu_update" = "Update";
|
||||
"lng_menu_back" = "Back";
|
||||
"lng_menu_night_mode" = "Night Mode";
|
||||
"lng_menu_add_account" = "Add Account";
|
||||
|
||||
"lng_disable_notifications_from_tray" = "Disable notifications";
|
||||
"lng_enable_notifications_from_tray" = "Enable notifications";
|
||||
|
|
|
@ -145,6 +145,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
qint32 dictionariesEnabledCount = 0;
|
||||
std::vector<int> dictionariesEnabled;
|
||||
qint32 autoDownloadDictionaries = _autoDownloadDictionaries.current() ? 1 : 0;
|
||||
qint32 mainMenuAccountsShown = _mainMenuAccountsShown.current() ? 1 : 0;
|
||||
|
||||
stream >> themesAccentColors;
|
||||
if (!stream.atEnd()) {
|
||||
|
@ -203,7 +204,8 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
}
|
||||
}
|
||||
stream
|
||||
>> autoDownloadDictionaries;
|
||||
>> autoDownloadDictionaries
|
||||
>> mainMenuAccountsShown;
|
||||
}
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("App Error: "
|
||||
|
@ -274,6 +276,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
_videoPipGeometry = (videoPipGeometry);
|
||||
_dictionariesEnabled = std::move(dictionariesEnabled);
|
||||
_autoDownloadDictionaries = (autoDownloadDictionaries == 1);
|
||||
_mainMenuAccountsShown = (mainMenuAccountsShown == 1);
|
||||
}
|
||||
|
||||
bool Settings::chatWide() const {
|
||||
|
@ -337,7 +340,7 @@ void Settings::resetOnLastLogout() {
|
|||
//_videoPipGeometry = QByteArray();
|
||||
_dictionariesEnabled = std::vector<int>();
|
||||
_autoDownloadDictionaries = true;
|
||||
|
||||
_mainMenuAccountsShown = false;
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
@ -349,6 +349,15 @@ public:
|
|||
void setRememberedFlashBounceNotifyFromTray(bool value) {
|
||||
_rememberedFlashBounceNotifyFromTray = value;
|
||||
}
|
||||
[[nodiscard]] bool mainMenuAccountsShown() const {
|
||||
return _mainMenuAccountsShown.current();
|
||||
}
|
||||
[[nodiscard]] rpl::producer<bool> mainMenuAccountsShownValue() const {
|
||||
return _mainMenuAccountsShown.value();
|
||||
}
|
||||
void setMainMenuAccountsShown(bool value) {
|
||||
_mainMenuAccountsShown = value;
|
||||
}
|
||||
|
||||
[[nodiscard]] static qint32 SerializePlaybackSpeed(float64 speed) {
|
||||
return int(std::round(std::clamp(speed * 4., 2., 8.))) - 2;
|
||||
|
@ -407,6 +416,7 @@ private:
|
|||
QByteArray _videoPipGeometry;
|
||||
rpl::variable<std::vector<int>> _dictionariesEnabled;
|
||||
rpl::variable<bool> _autoDownloadDictionaries = true;
|
||||
rpl::variable<bool> _mainMenuAccountsShown = false;
|
||||
|
||||
float64 _rememberedSongVolume = kDefaultVolume;
|
||||
bool _rememberedSoundNotifyFromTray = false;
|
||||
|
|
|
@ -100,6 +100,10 @@ const std::vector<Domain::AccountWithIndex> &Domain::accounts() const {
|
|||
return _accounts;
|
||||
}
|
||||
|
||||
rpl::producer<> Domain::accountsChanges() const {
|
||||
return _accountsChanges.events();
|
||||
}
|
||||
|
||||
rpl::producer<Account*> Domain::activeValue() const {
|
||||
return _active.value();
|
||||
}
|
||||
|
@ -176,6 +180,7 @@ void Domain::scheduleUpdateUnreadBadge() {
|
|||
|
||||
not_null<Main::Account*> Domain::add(MTP::Environment environment) {
|
||||
Expects(started());
|
||||
Expects(_accounts.size() < kMaxAccounts);
|
||||
|
||||
static const auto cloneConfig = [](const MTP::Config &config) {
|
||||
return std::make_unique<MTP::Config>(config);
|
||||
|
@ -207,6 +212,7 @@ not_null<Main::Account*> Domain::add(MTP::Environment environment) {
|
|||
const auto account = _accounts.back().account.get();
|
||||
_local->startAdded(account, std::move(config));
|
||||
watchSession(account);
|
||||
_accountsChanges.fire({});
|
||||
return account;
|
||||
}
|
||||
|
||||
|
@ -280,6 +286,7 @@ void Domain::removeRedundantAccounts() {
|
|||
|
||||
if (!removePasscodeIfEmpty() && _accounts.size() != was) {
|
||||
scheduleWriteAccounts();
|
||||
_accountsChanges.fire({});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ public:
|
|||
[[nodiscard]] auto accounts() const
|
||||
-> const std::vector<AccountWithIndex> &;
|
||||
[[nodiscard]] rpl::producer<Account*> activeValue() const;
|
||||
[[nodiscard]] rpl::producer<> accountsChanges() const;
|
||||
|
||||
// Expects(started());
|
||||
[[nodiscard]] Account &active() const;
|
||||
|
@ -83,6 +84,7 @@ private:
|
|||
const std::unique_ptr<Storage::Domain> _local;
|
||||
|
||||
std::vector<AccountWithIndex> _accounts;
|
||||
rpl::event_stream<> _accountsChanges;
|
||||
rpl::variable<Account*> _active = nullptr;
|
||||
int _accountToActivate = -1;
|
||||
bool _writeAccountsScheduled = false;
|
||||
|
|
|
@ -113,7 +113,7 @@ mainMenuResetScaleIconLeft: 5px;
|
|||
mainMenuCoverTextLeft: 30px;
|
||||
mainMenuCoverNameTop: 84px;
|
||||
mainMenuCoverStatusTop: 102px;
|
||||
mainMenuSkip: 13px;
|
||||
mainMenuSkip: 10px;
|
||||
mainMenu: Menu(defaultMenu) {
|
||||
itemFg: windowBoldFg;
|
||||
itemFgOver: windowBoldFgOver;
|
||||
|
@ -145,6 +145,8 @@ mainMenuReload: icon {{ "menu_reload", menuIconFg }};
|
|||
mainMenuReloadOver: icon {{ "menu_reload", menuIconFgOver }};
|
||||
mainMenuFixOrder: icon {{ "menu_fix_order", menuIconFg }};
|
||||
mainMenuFixOrderOver: icon {{ "menu_fix_order", menuIconFgOver }};
|
||||
mainMenuAddAccount: icon {{ "menu_fix_order", menuIconFg }};
|
||||
mainMenuAddAccountOver: icon {{ "menu_fix_order", menuIconFgOver }};
|
||||
mainMenuFooterLeft: 30px;
|
||||
mainMenuTelegramLabel: FlatLabel(defaultFlatLabel) {
|
||||
align: align(left);
|
||||
|
|
|
@ -13,9 +13,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/menu.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "ui/empty_userpic.h"
|
||||
#include "base/call_delayed.h"
|
||||
#include "mainwindow.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "storage/storage_account.h"
|
||||
|
@ -27,8 +32,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "calls/calls_box_controller.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "core/application.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_session_settings.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_domain.h"
|
||||
#include "mtproto/mtp_instance.h"
|
||||
#include "mtproto/mtproto_config.h"
|
||||
#include "data/data_folder.h"
|
||||
#include "data/data_session.h"
|
||||
|
@ -37,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mainwidget.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_window.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
@ -70,7 +81,22 @@ bool IsShadowShown(const QImage &img, const QRect r, float64 intensityText) {
|
|||
|
||||
namespace Window {
|
||||
|
||||
class MainMenu::ResetScaleButton : public Ui::AbstractButton {
|
||||
class MainMenu::AccountButton final : public Ui::RippleButton {
|
||||
public:
|
||||
AccountButton(QWidget *parent, not_null<Main::Account*> account);
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
const not_null<Main::Account*> _account;
|
||||
const style::Menu &_st;
|
||||
std::shared_ptr<Data::CloudImageView> _userpicView;
|
||||
int _unreadBadge = 0;
|
||||
bool _unreadBadgeMuted = true;
|
||||
|
||||
};
|
||||
|
||||
class MainMenu::ResetScaleButton final : public Ui::AbstractButton {
|
||||
public:
|
||||
ResetScaleButton(QWidget *parent);
|
||||
|
||||
|
@ -81,6 +107,61 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
MainMenu::AccountButton::AccountButton(
|
||||
QWidget *parent,
|
||||
not_null<Main::Account*> account)
|
||||
: RippleButton(parent, st::defaultRippleAnimation)
|
||||
, _account(account)
|
||||
, _st(st::mainMenu){
|
||||
const auto height = _st.itemPadding.top()
|
||||
+ _st.itemStyle.font->height
|
||||
+ _st.itemPadding.bottom();
|
||||
resize(width(), height);
|
||||
|
||||
_account->sessionValue(
|
||||
) | rpl::filter([=](Main::Session *session) {
|
||||
return (session != nullptr);
|
||||
}) | rpl::start_with_next([=](not_null<Main::Session*> session) {
|
||||
rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(
|
||||
session->data().unreadBadgeChanges()
|
||||
) | rpl::start_with_next([=] {
|
||||
_unreadBadge = session->data().unreadBadge();
|
||||
_unreadBadgeMuted = session->data().unreadBadgeMuted();
|
||||
update();
|
||||
}, lifetime());
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void MainMenu::AccountButton::paintEvent(QPaintEvent *e) {
|
||||
Expects(_account->sessionExists());
|
||||
|
||||
const auto &session = _account->session();
|
||||
|
||||
auto p = Painter(this);
|
||||
const auto over = isOver();
|
||||
p.fillRect(rect(), over ? _st.itemBgOver : _st.itemBg);
|
||||
paintRipple(p, 0, 0);
|
||||
|
||||
const auto available = width() - 2 * _st.itemPadding.left();
|
||||
|
||||
session.user()->paintUserpicLeft(
|
||||
p,
|
||||
_userpicView,
|
||||
_st.itemIconPosition.x(),
|
||||
_st.itemIconPosition.y(),
|
||||
width(),
|
||||
height() - 2 * _st.itemIconPosition.y());
|
||||
|
||||
p.setPen(over ? _st.itemFgOver : _st.itemFg);
|
||||
session.user()->nameText().drawElided(
|
||||
p,
|
||||
_st.itemPadding.left(),
|
||||
_st.itemPadding.top(),
|
||||
available);
|
||||
}
|
||||
|
||||
MainMenu::ResetScaleButton::ResetScaleButton(QWidget *parent)
|
||||
: AbstractButton(parent) {
|
||||
const auto margin = st::mainMenuCloudButton.height
|
||||
|
@ -130,63 +211,38 @@ MainMenu::MainMenu(
|
|||
not_null<SessionController*> controller)
|
||||
: LayerWidget(parent)
|
||||
, _controller(controller)
|
||||
, _menu(this, st::mainMenu)
|
||||
, _telegram(this, st::mainMenuTelegramLabel)
|
||||
, _version(this, st::mainMenuVersionLabel) {
|
||||
, _userpicButton(
|
||||
this,
|
||||
_controller,
|
||||
_controller->session().user(),
|
||||
Ui::UserpicButton::Role::Custom,
|
||||
st::mainMenuUserpic)
|
||||
, _toggleAccounts(this)
|
||||
, _archiveButton(this, st::mainMenuCloudButton)
|
||||
, _scroll(this, st::defaultSolidScroll)
|
||||
, _inner(_scroll->setOwnedWidget(
|
||||
object_ptr<Ui::VerticalLayout>(_scroll.data())))
|
||||
, _accounts(_inner->add(object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
_inner.get(),
|
||||
object_ptr<Ui::VerticalLayout>(_inner.get()))))
|
||||
, _shadow(_inner->add(object_ptr<Ui::SlideWrap<Ui::PlainShadow>>(
|
||||
_inner.get(),
|
||||
object_ptr<Ui::PlainShadow>(_inner.get()))))
|
||||
, _menu(_inner->add(
|
||||
object_ptr<Ui::Menu>(_inner.get(), st::mainMenu),
|
||||
{ 0, st::mainMenuSkip, 0, 0 }))
|
||||
, _footer(_inner->add(object_ptr<Ui::RpWidget>(_inner.get())))
|
||||
, _telegram(
|
||||
Ui::CreateChild<Ui::FlatLabel>(_footer.get(), st::mainMenuTelegramLabel))
|
||||
, _version(
|
||||
Ui::CreateChild<Ui::FlatLabel>(
|
||||
_footer.get(),
|
||||
st::mainMenuVersionLabel)) {
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
||||
const auto showSelfChat = [=] {
|
||||
controller->content()->choosePeer(
|
||||
_controller->session().userPeerId(),
|
||||
ShowAtUnreadMsgId);
|
||||
};
|
||||
const auto showArchive = [=] {
|
||||
const auto folder = _controller->session().data().folderLoaded(
|
||||
Data::Folder::kId);
|
||||
if (folder) {
|
||||
controller->openFolder(folder);
|
||||
Ui::hideSettingsAndLayer();
|
||||
}
|
||||
};
|
||||
const auto checkArchive = [=] {
|
||||
const auto folder = _controller->session().data().folderLoaded(
|
||||
Data::Folder::kId);
|
||||
return folder
|
||||
&& !folder->chatsList()->empty()
|
||||
&& _controller->session().settings().archiveInMainMenu();
|
||||
};
|
||||
_userpicButton.create(
|
||||
this,
|
||||
_controller,
|
||||
_controller->session().user(),
|
||||
Ui::UserpicButton::Role::Custom,
|
||||
st::mainMenuUserpic);
|
||||
_userpicButton->setClickedCallback(showSelfChat);
|
||||
_userpicButton->show();
|
||||
_cloudButton.create(this, st::mainMenuCloudButton);
|
||||
_cloudButton->setClickedCallback(showSelfChat);
|
||||
_cloudButton->show();
|
||||
|
||||
_archiveButton.create(this, st::mainMenuCloudButton);
|
||||
_archiveButton->setHidden(!checkArchive());
|
||||
_archiveButton->setAcceptBoth(true);
|
||||
_archiveButton->clicks(
|
||||
) | rpl::start_with_next([=](Qt::MouseButton which) {
|
||||
if (which == Qt::LeftButton) {
|
||||
showArchive();
|
||||
return;
|
||||
} else if (which != Qt::RightButton) {
|
||||
return;
|
||||
}
|
||||
_contextMenu = base::make_unique_q<Ui::PopupMenu>(this);
|
||||
_contextMenu->addAction(
|
||||
tr::lng_context_archive_to_list(tr::now), [=] {
|
||||
_controller->session().settings().setArchiveInMainMenu(false);
|
||||
_controller->session().saveSettingsDelayed();
|
||||
Ui::hideSettingsAndLayer();
|
||||
});
|
||||
_contextMenu->popup(QCursor::pos());
|
||||
}, _archiveButton->lifetime());
|
||||
setupArchiveButton();
|
||||
setupUserpicButton();
|
||||
setupAccounts();
|
||||
|
||||
_nightThemeSwitch.setCallback([this] {
|
||||
if (const auto action = *_nightThemeAction) {
|
||||
|
@ -198,6 +254,19 @@ MainMenu::MainMenu(
|
|||
}
|
||||
});
|
||||
|
||||
_footer->heightValue(
|
||||
) | rpl::start_with_next([=] {
|
||||
_telegram->moveToLeft(st::mainMenuFooterLeft, _footer->height() - st::mainMenuTelegramBottom - _telegram->height());
|
||||
_version->moveToLeft(st::mainMenuFooterLeft, _footer->height() - st::mainMenuVersionBottom - _version->height());
|
||||
}, _footer->lifetime());
|
||||
|
||||
rpl::combine(
|
||||
heightValue(),
|
||||
_inner->heightValue()
|
||||
) | rpl::start_with_next([=] {
|
||||
updateInnerControlsGeometry();
|
||||
}, _inner->lifetime());
|
||||
|
||||
parentResized();
|
||||
_menu->setTriggeredCallback([](QAction *action, int actionTop, Ui::Menu::TriggeredSource source) {
|
||||
emit action->triggered();
|
||||
|
@ -235,15 +304,219 @@ MainMenu::MainMenu(
|
|||
refreshBackground();
|
||||
}
|
||||
});
|
||||
updatePhone();
|
||||
initResetScaleButton();
|
||||
}
|
||||
|
||||
void MainMenu::setupArchiveButton() {
|
||||
const auto showArchive = [=] {
|
||||
const auto folder = _controller->session().data().folderLoaded(
|
||||
Data::Folder::kId);
|
||||
if (folder) {
|
||||
_controller->openFolder(folder);
|
||||
Ui::hideSettingsAndLayer();
|
||||
}
|
||||
};
|
||||
const auto checkArchive = [=] {
|
||||
const auto folder = _controller->session().data().folderLoaded(
|
||||
Data::Folder::kId);
|
||||
return folder
|
||||
&& !folder->chatsList()->empty()
|
||||
&& _controller->session().settings().archiveInMainMenu();
|
||||
};
|
||||
_archiveButton->setVisible(checkArchive());
|
||||
_archiveButton->setAcceptBoth(true);
|
||||
_archiveButton->clicks(
|
||||
) | rpl::start_with_next([=](Qt::MouseButton which) {
|
||||
if (which == Qt::LeftButton) {
|
||||
showArchive();
|
||||
return;
|
||||
} else if (which != Qt::RightButton) {
|
||||
return;
|
||||
}
|
||||
_contextMenu = base::make_unique_q<Ui::PopupMenu>(this);
|
||||
_contextMenu->addAction(
|
||||
tr::lng_context_archive_to_list(tr::now), [=] {
|
||||
_controller->session().settings().setArchiveInMainMenu(false);
|
||||
_controller->session().saveSettingsDelayed();
|
||||
Ui::hideSettingsAndLayer();
|
||||
});
|
||||
_contextMenu->popup(QCursor::pos());
|
||||
}, _archiveButton->lifetime());
|
||||
|
||||
_controller->session().data().chatsListChanges(
|
||||
) | rpl::filter([](Data::Folder *folder) {
|
||||
return folder && (folder->id() == Data::Folder::kId);
|
||||
}) | rpl::start_with_next([=](Data::Folder *folder) {
|
||||
_archiveButton->setHidden(!checkArchive());
|
||||
_archiveButton->setVisible(checkArchive());
|
||||
update();
|
||||
}, lifetime());
|
||||
updatePhone();
|
||||
initResetScaleButton();
|
||||
}
|
||||
|
||||
void MainMenu::setupUserpicButton() {
|
||||
_userpicButton->setClickedCallback([=] {
|
||||
_controller->content()->choosePeer(
|
||||
_controller->session().userPeerId(),
|
||||
ShowAtUnreadMsgId);
|
||||
});
|
||||
_userpicButton->show();
|
||||
}
|
||||
|
||||
void MainMenu::setupAccounts() {
|
||||
const auto inner = _accounts->entity();
|
||||
|
||||
inner->add(object_ptr<Ui::FixedHeightWidget>(inner, st::mainMenuSkip));
|
||||
_addAccount = setupAddAccount(inner);
|
||||
inner->add(object_ptr<Ui::FixedHeightWidget>(inner, st::mainMenuSkip));
|
||||
|
||||
rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(Core::App().domain().accountsChanges(
|
||||
)) | rpl::start_with_next([=] {
|
||||
const auto &list = Core::App().domain().accounts();
|
||||
const auto exists = [&](not_null<Main::Account*> account) {
|
||||
for (const auto &[index, existing] : list) {
|
||||
if (account == existing.get()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (auto i = _watched.begin(); i != _watched.end();) {
|
||||
if (!exists(i->first)) {
|
||||
i = _watched.erase(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
for (const auto &[index, account] : list) {
|
||||
if (_watched.emplace(account.get()).second) {
|
||||
account->sessionChanges(
|
||||
) | rpl::start_with_next([=](Main::Session *session) {
|
||||
rebuildAccounts();
|
||||
}, lifetime());
|
||||
}
|
||||
}
|
||||
rebuildAccounts();
|
||||
}, lifetime());
|
||||
|
||||
_accounts->toggleOn(Core::App().settings().mainMenuAccountsShownValue());
|
||||
_accounts->finishAnimating();
|
||||
|
||||
_shadow->setDuration(0)->toggleOn(_accounts->shownValue());
|
||||
|
||||
_toggleAccounts->show();
|
||||
_toggleAccounts->setClickedCallback([=] {
|
||||
auto &settings = Core::App().settings();
|
||||
const auto shown = !settings.mainMenuAccountsShown();
|
||||
settings.setMainMenuAccountsShown(shown);
|
||||
});
|
||||
}
|
||||
|
||||
void MainMenu::rebuildAccounts() {
|
||||
const auto inner = _accounts->entity();
|
||||
|
||||
auto count = 0;
|
||||
for (auto &[account, button] : _watched) {
|
||||
if (!account->sessionExists()) {
|
||||
button = nullptr;
|
||||
} else if (!button) {
|
||||
button.reset(inner->insert(
|
||||
++count,
|
||||
object_ptr<AccountButton>(inner, account)));
|
||||
button->setClickedCallback([=] {
|
||||
auto activate = [=, guard = _accountSwitchGuard.make_guard()]{
|
||||
if (guard) {
|
||||
Core::App().domain().activate(account);
|
||||
}
|
||||
};
|
||||
base::call_delayed(
|
||||
st::defaultRippleAnimation.hideDuration,
|
||||
account,
|
||||
std::move(activate));
|
||||
});
|
||||
} else {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
inner->resizeToWidth(_accounts->width());
|
||||
|
||||
_addAccount->toggle(
|
||||
(count < Main::Domain::kMaxAccounts),
|
||||
anim::type::instant);
|
||||
}
|
||||
|
||||
not_null<Ui::SlideWrap<Ui::RippleButton>*> MainMenu::setupAddAccount(
|
||||
not_null<Ui::VerticalLayout*> container) {
|
||||
const auto result = container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::RippleButton>>(
|
||||
container.get(),
|
||||
object_ptr<Ui::RippleButton>(
|
||||
container.get(),
|
||||
st::defaultRippleAnimation)))->setDuration(0);
|
||||
const auto st = &st::mainMenu;
|
||||
const auto height = st->itemPadding.top()
|
||||
+ st->itemStyle.font->height
|
||||
+ st->itemPadding.bottom();
|
||||
const auto button = result->entity();
|
||||
button->resize(button->width(), height);
|
||||
|
||||
button->paintRequest(
|
||||
) | rpl::start_with_next([=] {
|
||||
auto p = Painter(button);
|
||||
const auto over = button->isOver();
|
||||
p.fillRect(button->rect(), over ? st->itemBgOver : st->itemBg);
|
||||
button->paintRipple(p, 0, 0);
|
||||
const auto &icon = over
|
||||
? st::mainMenuAddAccountOver
|
||||
: st::mainMenuAddAccount;
|
||||
icon.paint(p, st->itemIconPosition, width());
|
||||
p.setPen(over ? st->itemFgOver : st->itemFg);
|
||||
p.setFont(st->itemStyle.font);
|
||||
p.drawTextLeft(
|
||||
st->itemPadding.left(),
|
||||
st->itemPadding.top(),
|
||||
width(),
|
||||
tr::lng_menu_add_account(tr::now));
|
||||
}, button->lifetime());
|
||||
|
||||
const auto add = [=](MTP::Environment environment) {
|
||||
auto &domain = Core::App().domain();
|
||||
if (domain.accounts().size() < Main::Domain::kMaxAccounts) {
|
||||
domain.activate(domain.add(environment));
|
||||
} else {
|
||||
for (auto &[index, account] : domain.accounts()) {
|
||||
if (!account->sessionExists()
|
||||
&& account->mtp().environment() == environment) {
|
||||
domain.activate(account.get());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
button->setAcceptBoth(true);
|
||||
button->clicks(
|
||||
) | rpl::start_with_next([=](Qt::MouseButton which) {
|
||||
if (which == Qt::LeftButton) {
|
||||
add(MTP::Environment::Production);
|
||||
return;
|
||||
} else if (which != Qt::RightButton
|
||||
|| !(button->clickModifiers() & Qt::ShiftModifier)
|
||||
|| !(button->clickModifiers() & Qt::AltModifier)) {
|
||||
return;
|
||||
}
|
||||
_contextMenu = base::make_unique_q<Ui::PopupMenu>(this);
|
||||
_contextMenu->addAction("Production Server", [=] {
|
||||
add(MTP::Environment::Production);
|
||||
});
|
||||
_contextMenu->addAction("Test Server", [=] {
|
||||
add(MTP::Environment::Test);
|
||||
});
|
||||
_contextMenu->popup(QCursor::pos());
|
||||
}, _archiveButton->lifetime());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MainMenu::parentResized() {
|
||||
|
@ -374,31 +647,41 @@ void MainMenu::refreshBackground() {
|
|||
|
||||
void MainMenu::resizeEvent(QResizeEvent *e) {
|
||||
_menu->setForceWidth(width());
|
||||
_inner->resizeToWidth(width());
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
void MainMenu::updateControlsGeometry() {
|
||||
if (_userpicButton) {
|
||||
_userpicButton->moveToLeft(st::mainMenuUserpicLeft, st::mainMenuUserpicTop);
|
||||
}
|
||||
if (_cloudButton) {
|
||||
const auto offset = st::mainMenuCloudSize / 4;
|
||||
const auto y = st::mainMenuCoverHeight
|
||||
- _cloudButton->height()
|
||||
- offset;
|
||||
_cloudButton->moveToRight(offset, y);
|
||||
if (_archiveButton) {
|
||||
_archiveButton->moveToRight(
|
||||
offset,
|
||||
y - _cloudButton->height());
|
||||
}
|
||||
}
|
||||
_userpicButton->moveToLeft(st::mainMenuUserpicLeft, st::mainMenuUserpicTop);
|
||||
if (_resetScaleButton) {
|
||||
_resetScaleButton->moveToRight(0, 0);
|
||||
_archiveButton->moveToRight(_resetScaleButton->width(), 0);
|
||||
} else {
|
||||
const auto offset = st::mainMenuCloudSize / 4;
|
||||
_archiveButton->moveToRight(offset, offset);
|
||||
}
|
||||
_toggleAccounts->setGeometry(
|
||||
0,
|
||||
st::mainMenuCoverNameTop,
|
||||
width(),
|
||||
st::mainMenuCoverHeight - st::mainMenuCoverNameTop);
|
||||
const auto top = st::mainMenuCoverHeight;
|
||||
_scroll->setGeometry(0, top, width(), height() - top);
|
||||
updateInnerControlsGeometry();
|
||||
}
|
||||
|
||||
void MainMenu::updateInnerControlsGeometry() {
|
||||
const auto contentHeight = _accounts->height()
|
||||
+ _shadow->height()
|
||||
+ st::mainMenuSkip
|
||||
+ _menu->height();
|
||||
const auto available = height() - st::mainMenuCoverHeight - contentHeight;
|
||||
const auto footerHeight = std::max(
|
||||
available,
|
||||
st::mainMenuTelegramBottom + _telegram->height() + st::mainMenuSkip);
|
||||
if (_footer->height() != footerHeight) {
|
||||
_footer->resize(_footer->width(), footerHeight);
|
||||
}
|
||||
_menu->moveToLeft(0, st::mainMenuCoverHeight + st::mainMenuSkip);
|
||||
_telegram->moveToLeft(st::mainMenuFooterLeft, height() - st::mainMenuTelegramBottom - _telegram->height());
|
||||
_version->moveToLeft(st::mainMenuFooterLeft, height() - st::mainMenuVersionBottom - _version->height());
|
||||
}
|
||||
|
||||
void MainMenu::updatePhone() {
|
||||
|
@ -425,9 +708,7 @@ void MainMenu::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
if (!cover.isEmpty()) {
|
||||
const auto widthText = _cloudButton
|
||||
? _cloudButton->x() - st::mainMenuCloudSize
|
||||
: width() - 2 * st::mainMenuCoverTextLeft;
|
||||
const auto widthText = width() - 2 * st::mainMenuCoverTextLeft;
|
||||
|
||||
if (isFill) {
|
||||
p.fillRect(cover, st::mainMenuCoverBg);
|
||||
|
@ -442,16 +723,6 @@ void MainMenu::paintEvent(QPaintEvent *e) {
|
|||
width());
|
||||
p.setFont(st::normalFont);
|
||||
p.drawTextLeft(st::mainMenuCoverTextLeft, st::mainMenuCoverStatusTop, width(), _phoneText);
|
||||
if (_cloudButton) {
|
||||
Ui::EmptyUserpic::PaintSavedMessages(
|
||||
p,
|
||||
_cloudButton->x() + (_cloudButton->width() - st::mainMenuCloudSize) / 2,
|
||||
_cloudButton->y() + (_cloudButton->height() - st::mainMenuCloudSize) / 2,
|
||||
width(),
|
||||
st::mainMenuCloudSize,
|
||||
isFill ? st::mainMenuCloudBg : st::msgServiceBg,
|
||||
isFill ? st::mainMenuCloudFg : st::msgServiceFg);
|
||||
}
|
||||
|
||||
// Draw Archive button.
|
||||
if (!_archiveButton->isHidden()) {
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "base/timer.h"
|
||||
#include "base/object_ptr.h"
|
||||
#include "base/binary_guard.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/layers/layer_widget.h"
|
||||
|
||||
|
@ -18,8 +19,19 @@ class FlatLabel;
|
|||
class Menu;
|
||||
class UserpicButton;
|
||||
class PopupMenu;
|
||||
class AbstractButton;
|
||||
class ScrollArea;
|
||||
class VerticalLayout;
|
||||
class RippleButton;
|
||||
class PlainShadow;
|
||||
template <typename Widget>
|
||||
class SlideWrap;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Main {
|
||||
class Account;
|
||||
} // namespace Main
|
||||
|
||||
namespace Window {
|
||||
|
||||
class SessionController;
|
||||
|
@ -39,25 +51,45 @@ protected:
|
|||
}
|
||||
|
||||
private:
|
||||
class AccountButton;
|
||||
class ResetScaleButton;
|
||||
|
||||
void setupArchiveButton();
|
||||
void setupUserpicButton();
|
||||
void setupAccounts();
|
||||
[[nodiscard]] not_null<Ui::SlideWrap<Ui::RippleButton>*> setupAddAccount(
|
||||
not_null<Ui::VerticalLayout*> container);
|
||||
void rebuildAccounts();
|
||||
void updateControlsGeometry();
|
||||
void updateInnerControlsGeometry();
|
||||
void updatePhone();
|
||||
void initResetScaleButton();
|
||||
void refreshMenu();
|
||||
void refreshBackground();
|
||||
|
||||
class ResetScaleButton;
|
||||
not_null<SessionController*> _controller;
|
||||
object_ptr<Ui::UserpicButton> _userpicButton = { nullptr };
|
||||
object_ptr<Ui::IconButton> _cloudButton = { nullptr };
|
||||
object_ptr<Ui::IconButton> _archiveButton = { nullptr };
|
||||
const not_null<SessionController*> _controller;
|
||||
object_ptr<Ui::UserpicButton> _userpicButton;
|
||||
object_ptr<Ui::AbstractButton> _toggleAccounts;
|
||||
object_ptr<Ui::IconButton> _archiveButton;
|
||||
object_ptr<ResetScaleButton> _resetScaleButton = { nullptr };
|
||||
object_ptr<Ui::Menu> _menu;
|
||||
object_ptr<Ui::FlatLabel> _telegram;
|
||||
object_ptr<Ui::FlatLabel> _version;
|
||||
object_ptr<Ui::ScrollArea> _scroll;
|
||||
not_null<Ui::VerticalLayout*> _inner;
|
||||
base::flat_map<
|
||||
not_null<Main::Account*>,
|
||||
base::unique_qptr<AccountButton>> _watched;
|
||||
not_null<Ui::SlideWrap<Ui::VerticalLayout>*> _accounts;
|
||||
Ui::SlideWrap<Ui::RippleButton> *_addAccount = nullptr;
|
||||
not_null<Ui::SlideWrap<Ui::PlainShadow>*> _shadow;
|
||||
not_null<Ui::Menu*> _menu;
|
||||
not_null<Ui::RpWidget*> _footer;
|
||||
not_null<Ui::FlatLabel*> _telegram;
|
||||
not_null<Ui::FlatLabel*> _version;
|
||||
std::shared_ptr<QPointer<QAction>> _nightThemeAction;
|
||||
base::Timer _nightThemeSwitch;
|
||||
base::unique_qptr<Ui::PopupMenu> _contextMenu;
|
||||
|
||||
base::binary_guard _accountSwitchGuard;
|
||||
|
||||
QString _phoneText;
|
||||
QImage _background;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 4e6763d1769e6305a3da158e1a332ccd6a30398a
|
||||
Subproject commit d31d94e8fb47b8492fbf341b93c19ddfbcb42fa2
|
Loading…
Add table
Reference in a new issue