New connecting status design.
@ -215,8 +215,6 @@ emojiReplaceHeight: 56px;
|
||||
emojiReplaceInnerHeight: 42px;
|
||||
emojiReplacePadding: 14px;
|
||||
|
||||
connectingPadding: margins(5px, 5px, 5px, 5px);
|
||||
|
||||
dragFont: font(28px semibold);
|
||||
dragSubfont: font(20px semibold);
|
||||
dragColor: windowSubTextFg;
|
||||
|
BIN
Telegram/Resources/icons/connecting_body.png
Normal file
After Width: | Height: | Size: 95 B |
BIN
Telegram/Resources/icons/connecting_body@2x.png
Normal file
After Width: | Height: | Size: 112 B |
BIN
Telegram/Resources/icons/connecting_body_shadow.png
Normal file
After Width: | Height: | Size: 117 B |
BIN
Telegram/Resources/icons/connecting_body_shadow@2x.png
Normal file
After Width: | Height: | Size: 151 B |
BIN
Telegram/Resources/icons/connecting_left.png
Normal file
After Width: | Height: | Size: 357 B |
BIN
Telegram/Resources/icons/connecting_left@2x.png
Normal file
After Width: | Height: | Size: 717 B |
BIN
Telegram/Resources/icons/connecting_left_shadow.png
Normal file
After Width: | Height: | Size: 550 B |
BIN
Telegram/Resources/icons/connecting_left_shadow@2x.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Telegram/Resources/icons/connecting_right.png
Normal file
After Width: | Height: | Size: 347 B |
BIN
Telegram/Resources/icons/connecting_right@2x.png
Normal file
After Width: | Height: | Size: 679 B |
BIN
Telegram/Resources/icons/connecting_right_shadow.png
Normal file
After Width: | Height: | Size: 573 B |
BIN
Telegram/Resources/icons/connecting_right_shadow@2x.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Telegram/Resources/icons/proxy_off.png
Normal file
After Width: | Height: | Size: 529 B |
BIN
Telegram/Resources/icons/proxy_off@2x.png
Normal file
After Width: | Height: | Size: 1012 B |
BIN
Telegram/Resources/icons/proxy_on.png
Normal file
After Width: | Height: | Size: 584 B |
BIN
Telegram/Resources/icons/proxy_on@2x.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
@ -168,9 +168,6 @@ namespace {
|
||||
|
||||
cSetOtherOnline(0);
|
||||
clearStorageImages();
|
||||
if (auto w = wnd()) {
|
||||
w->updateConnectingStatus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "window/window_slide_animation.h"
|
||||
#include "window/window_connecting_widget.h"
|
||||
#include "profile/profile_channel_controllers.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "data/data_session.h"
|
||||
@ -170,6 +171,13 @@ DialogsWidget::DialogsWidget(QWidget *parent, not_null<Window::Controller*> cont
|
||||
|
||||
updateJumpToDateVisibility(true);
|
||||
updateSearchFromVisibility(true);
|
||||
setupConnectingWidget();
|
||||
}
|
||||
|
||||
void DialogsWidget::setupConnectingWidget() {
|
||||
_connecting = Window::ConnectingWidget::CreateDefaultWidget(
|
||||
this,
|
||||
Window::AdaptiveIsOneColumn());
|
||||
}
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
@ -282,6 +290,7 @@ void DialogsWidget::showAnimated(Window::SlideDirection direction, const Window:
|
||||
_jumpToDate->hide(anim::type::instant);
|
||||
_chooseFromUser->hide(anim::type::instant);
|
||||
_lockUnlock->hide();
|
||||
_connecting->setForceHidden(true);
|
||||
|
||||
int delta = st::slideShift;
|
||||
if (_showDirection == Window::SlideDirection::FromLeft) {
|
||||
@ -307,6 +316,7 @@ void DialogsWidget::animationCallback() {
|
||||
_mainMenuToggle->show();
|
||||
if (_forwardCancel) _forwardCancel->show();
|
||||
_filter->show();
|
||||
_connecting->setForceHidden(false);
|
||||
updateLockUnlockVisibility();
|
||||
updateJumpToDateVisibility(true);
|
||||
updateSearchFromVisibility(true);
|
||||
|
@ -34,6 +34,7 @@ class FadeWrapScaled;
|
||||
|
||||
namespace Window {
|
||||
class Controller;
|
||||
class ConnectingWidget;
|
||||
} // namespace Window
|
||||
|
||||
enum DialogsSearchRequestType {
|
||||
@ -151,6 +152,7 @@ private:
|
||||
const QVector<MTPDialog> &dialogs,
|
||||
const QVector<MTPMessage> &messages);
|
||||
|
||||
void setupConnectingWidget();
|
||||
bool searchForPeersRequired(const QString &query) const;
|
||||
void setSearchInChat(Dialogs::Key chat, UserData *from = nullptr);
|
||||
void showJumpToDate();
|
||||
@ -194,6 +196,7 @@ private:
|
||||
QPointer<DialogsInner> _inner;
|
||||
class UpdateButton;
|
||||
object_ptr<UpdateButton> _updateTelegram = { nullptr };
|
||||
base::unique_qptr<Window::ConnectingWidget> _connecting;
|
||||
|
||||
Animation _a_show;
|
||||
Window::SlideDirection _showDirection;
|
||||
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "info/info_section_widget.h"
|
||||
|
||||
#include "window/window_connecting_widget.h"
|
||||
#include "info/info_content_widget.h"
|
||||
#include "info/info_wrap_widget.h"
|
||||
#include "info/info_layer_widget.h"
|
||||
@ -42,6 +43,15 @@ void SectionWidget::init() {
|
||||
auto additionalScroll = 0;
|
||||
wrap->updateGeometry(wrapGeometry, additionalScroll);
|
||||
}, _content->lifetime());
|
||||
|
||||
_connecting = Window::ConnectingWidget::CreateDefaultWidget(
|
||||
_content.data(),
|
||||
Window::AdaptiveIsOneColumn());
|
||||
|
||||
_content->contentChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
_connecting->raise();
|
||||
}, _connecting->lifetime());
|
||||
}
|
||||
|
||||
Dialogs::RowDescriptor SectionWidget::activeChat() const {
|
||||
|
@ -14,6 +14,10 @@ namespace Ui {
|
||||
class SettingsSlider;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class ConnectingWidget;
|
||||
} // namespace Window
|
||||
|
||||
namespace Info {
|
||||
|
||||
class Memento;
|
||||
@ -65,6 +69,7 @@ private:
|
||||
|
||||
object_ptr<WrapWidget> _content;
|
||||
object_ptr<Ui::RpWidget> _topBarSurrogate = { nullptr };
|
||||
base::unique_qptr<Window::ConnectingWidget> _connecting;
|
||||
|
||||
};
|
||||
|
||||
|
@ -582,6 +582,7 @@ void WrapWidget::finishShowContent() {
|
||||
_scrollTillBottomChanges.fire(_content->scrollTillBottomChanges());
|
||||
_topShadow->raise();
|
||||
_topShadow->finishAnimating();
|
||||
_contentChanges.fire({});
|
||||
|
||||
// This was done for tabs support.
|
||||
//
|
||||
@ -680,6 +681,10 @@ void WrapWidget::setWrap(Wrap wrap) {
|
||||
_wrap = wrap;
|
||||
}
|
||||
|
||||
rpl::producer<> WrapWidget::contentChanged() const {
|
||||
return _contentChanges.events();
|
||||
}
|
||||
|
||||
bool WrapWidget::hasTopBarShadow() const {
|
||||
return _topShadow->toggled();
|
||||
}
|
||||
|
@ -90,6 +90,8 @@ public:
|
||||
rpl::producer<Wrap> wrapValue() const;
|
||||
void setWrap(Wrap wrap);
|
||||
|
||||
rpl::producer<> contentChanged() const;
|
||||
|
||||
not_null<Controller*> controller() {
|
||||
return _controller.get();
|
||||
}
|
||||
@ -217,6 +219,7 @@ private:
|
||||
rpl::event_stream<rpl::producer<bool>> _desiredShadowVisibilities;
|
||||
rpl::event_stream<rpl::producer<SelectedItems>> _selectedLists;
|
||||
rpl::event_stream<rpl::producer<int>> _scrollTillBottomChanges;
|
||||
rpl::event_stream<> _contentChanges;
|
||||
|
||||
};
|
||||
|
||||
|
@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/effects/slide_animation.h"
|
||||
#include "core/update_checker.h"
|
||||
#include "window/window_slide_animation.h"
|
||||
#include "window/window_connecting_widget.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_intro.h"
|
||||
#include "styles/style_window.h"
|
||||
@ -65,6 +66,7 @@ Widget::Widget(QWidget *parent) : RpWidget(parent)
|
||||
_settings->entity()->setClickedCallback([] { App::wnd()->showSettings(); });
|
||||
|
||||
getNearestDC();
|
||||
setupConnectingWidget();
|
||||
|
||||
appendStep(new StartWidget(this, getData()));
|
||||
fixOrder();
|
||||
@ -97,6 +99,12 @@ Widget::Widget(QWidget *parent) : RpWidget(parent)
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
}
|
||||
|
||||
void Widget::setupConnectingWidget() {
|
||||
_connecting = Window::ConnectingWidget::CreateDefaultWidget(
|
||||
this,
|
||||
rpl::single(true));
|
||||
}
|
||||
|
||||
void Widget::refreshLang() {
|
||||
_changeLanguage.destroy();
|
||||
createLanguageLink();
|
||||
@ -212,6 +220,7 @@ void Widget::fixOrder() {
|
||||
if (_update) _update->raise();
|
||||
_settings->raise();
|
||||
_back->raise();
|
||||
_connecting->raise();
|
||||
}
|
||||
|
||||
void Widget::moveToStep(Step *step, Direction direction) {
|
||||
@ -221,6 +230,7 @@ void Widget::moveToStep(Step *step, Direction direction) {
|
||||
if (_update) {
|
||||
_update->raise();
|
||||
}
|
||||
_connecting->raise();
|
||||
|
||||
historyMove(direction);
|
||||
}
|
||||
@ -310,6 +320,7 @@ void Widget::showControls() {
|
||||
getStep()->show();
|
||||
_next->show();
|
||||
_next->setText([this] { return getStep()->nextButtonText(); });
|
||||
_connecting->setForceHidden(false);
|
||||
auto hasCover = getStep()->hasCover();
|
||||
_settings->toggle(!hasCover, anim::type::instant);
|
||||
if (_update) _update->toggle(!hasCover, anim::type::instant);
|
||||
@ -320,6 +331,7 @@ void Widget::showControls() {
|
||||
void Widget::hideControls() {
|
||||
getStep()->hide();
|
||||
_next->hide();
|
||||
_connecting->setForceHidden(true);
|
||||
_settings->hide(anim::type::instant);
|
||||
if (_update) _update->hide(anim::type::instant);
|
||||
if (_changeLanguage) _changeLanguage->hide(anim::type::instant);
|
||||
|
@ -21,6 +21,10 @@ template <typename Widget>
|
||||
class FadeWrap;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class ConnectingWidget;
|
||||
} // namespace Window
|
||||
|
||||
namespace Intro {
|
||||
|
||||
class Widget : public Ui::RpWidget, private MTP::Sender, private base::Subscriber {
|
||||
@ -202,6 +206,7 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
void setupConnectingWidget();
|
||||
void refreshLang();
|
||||
void animationCallback();
|
||||
void createLanguageLink();
|
||||
@ -249,6 +254,8 @@ private:
|
||||
object_ptr<Ui::FadeWrap<Ui::LinkButton>> _changeLanguage = { nullptr };
|
||||
object_ptr<Ui::FadeWrap<Ui::RoundButton>> _resetAccount = { nullptr };
|
||||
|
||||
base::unique_qptr<Window::ConnectingWidget> _connecting;
|
||||
|
||||
mtpRequestId _resetRequest = 0;
|
||||
|
||||
};
|
||||
|
@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "window/section_memento.h"
|
||||
#include "window/section_widget.h"
|
||||
#include "window/window_connecting_widget.h"
|
||||
#include "ui/widgets/dropdown_menu.h"
|
||||
#include "ui/focus_persister.h"
|
||||
#include "ui/resize_area.h"
|
||||
@ -56,6 +57,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/mute_settings_box.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "boxes/download_path_box.h"
|
||||
#include "boxes/connection_box.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "shortcuts.h"
|
||||
#include "media/media_audio.h"
|
||||
@ -214,6 +216,7 @@ MainWidget::MainWidget(
|
||||
|
||||
_ptsWaiter.setRequesting(true);
|
||||
updateScrollColors();
|
||||
setupConnectingWidget();
|
||||
|
||||
connect(_dialogs, SIGNAL(cancelled()), this, SLOT(dialogsCancelled()));
|
||||
connect(this, SIGNAL(dialogsUpdated()), _dialogs, SLOT(onListScroll()));
|
||||
@ -329,6 +332,13 @@ MainWidget::MainWidget(
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
}
|
||||
|
||||
void MainWidget::setupConnectingWidget() {
|
||||
using namespace rpl::mappers;
|
||||
_connecting = Window::ConnectingWidget::CreateDefaultWidget(
|
||||
this,
|
||||
Window::AdaptiveIsOneColumn() | rpl::map(!_1));
|
||||
}
|
||||
|
||||
void MainWidget::checkCurrentFloatPlayer() {
|
||||
const auto state = Media::Player::instance()->current(AudioMsgId::Type::Voice);
|
||||
const auto fullId = state.contextId();
|
||||
@ -2567,6 +2577,7 @@ void MainWidget::orderWidgets() {
|
||||
if (_thirdColumnResizeArea) {
|
||||
_thirdColumnResizeArea->raise();
|
||||
}
|
||||
_connecting->raise();
|
||||
_playerPlaylist->raise();
|
||||
_playerPanel->raise();
|
||||
for (auto &instance : _playerFloats) {
|
||||
|
@ -54,6 +54,7 @@ class PlayerWrapWidget;
|
||||
class SectionMemento;
|
||||
class SectionWidget;
|
||||
class AbstractSectionWidget;
|
||||
class ConnectingWidget;
|
||||
struct SectionSlideParams;
|
||||
struct SectionShow;
|
||||
enum class Column;
|
||||
@ -426,6 +427,7 @@ private:
|
||||
-> std::unique_ptr<Window::SectionMemento>;
|
||||
void userIsContactUpdated(not_null<UserData*> user);
|
||||
|
||||
void setupConnectingWidget();
|
||||
void createPlayer();
|
||||
void switchToPanelPlayer();
|
||||
void switchToFixedPlayer();
|
||||
@ -561,6 +563,7 @@ private:
|
||||
object_ptr<Window::SectionWidget> _mainSection = { nullptr };
|
||||
object_ptr<Window::SectionWidget> _thirdSection = { nullptr };
|
||||
std::unique_ptr<Window::SectionMemento> _thirdSectionFromStack;
|
||||
base::unique_qptr<Window::ConnectingWidget> _connecting;
|
||||
|
||||
base::weak_ptr<Calls::Call> _currentCall;
|
||||
object_ptr<Ui::SlideWrap<Calls::TopBar>> _callTopBar = { nullptr };
|
||||
|
@ -63,50 +63,6 @@ void FeedLangTestingKey(int key) {
|
||||
|
||||
} // namespace
|
||||
|
||||
ConnectingWidget::ConnectingWidget(QWidget *parent, const QString &text, const QString &reconnect) : TWidget(parent)
|
||||
, _reconnect(this, QString()) {
|
||||
set(text, reconnect);
|
||||
connect(_reconnect, SIGNAL(clicked()), this, SLOT(onReconnect()));
|
||||
}
|
||||
|
||||
void ConnectingWidget::set(const QString &text, const QString &reconnect) {
|
||||
_text = text;
|
||||
_textWidth = st::linkFont->width(_text) + st::linkFont->spacew;
|
||||
int32 _reconnectWidth = 0;
|
||||
if (reconnect.isEmpty()) {
|
||||
_reconnect->hide();
|
||||
} else {
|
||||
_reconnect->setText(reconnect);
|
||||
_reconnect->show();
|
||||
_reconnect->move(st::connectingPadding.left() + _textWidth, st::boxRoundShadow.extend.top() + st::connectingPadding.top());
|
||||
_reconnectWidth = _reconnect->width();
|
||||
}
|
||||
resize(st::connectingPadding.left() + _textWidth + _reconnectWidth + st::connectingPadding.right() + st::boxRoundShadow.extend.right(), st::boxRoundShadow.extend.top() + st::connectingPadding.top() + st::normalFont->height + st::connectingPadding.bottom());
|
||||
update();
|
||||
}
|
||||
|
||||
void ConnectingWidget::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
auto sides = RectPart::Top | RectPart::Right;
|
||||
Ui::Shadow::paint(p, QRect(0, st::boxRoundShadow.extend.top(), width() - st::boxRoundShadow.extend.right(), height() - st::boxRoundShadow.extend.top()), width(), st::boxRoundShadow, sides);
|
||||
auto parts = RectPart::Top | RectPart::TopRight | RectPart::Center | RectPart::Right;
|
||||
App::roundRect(p, QRect(-st::boxRadius, st::boxRoundShadow.extend.top(), width() - st::boxRoundShadow.extend.right() + st::boxRadius, height() - st::boxRoundShadow.extend.top() + st::boxRadius), st::boxBg, BoxCorners, nullptr, parts);
|
||||
|
||||
p.setFont(st::normalFont);
|
||||
p.setPen(st::windowSubTextFg);
|
||||
p.drawText(st::connectingPadding.left(), st::boxRoundShadow.extend.top() + st::connectingPadding.top() + st::normalFont->ascent, _text);
|
||||
}
|
||||
|
||||
void ConnectingWidget::onReconnect() {
|
||||
if (Global::UseProxy()) {
|
||||
//Ui::show(Box<ConnectionBox>());
|
||||
Ui::show(ProxiesBoxController::CreateOwningBox());
|
||||
} else {
|
||||
MTP::restart();
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow::MainWindow() {
|
||||
auto logo = Messenger::Instance().logo();
|
||||
icon16 = logo.scaledToWidth(16, Qt::SmoothTransformation);
|
||||
@ -244,8 +200,6 @@ void MainWindow::setupIntro() {
|
||||
|
||||
fixOrder();
|
||||
|
||||
updateConnectingStatus();
|
||||
|
||||
_delayedServiceMsgs.clear();
|
||||
if (_serviceHistoryRequest) {
|
||||
MTP::cancel(_serviceHistoryRequest);
|
||||
@ -332,8 +286,6 @@ void MainWindow::setupMain(const MTPUser *self) {
|
||||
_main->start(self);
|
||||
|
||||
fixOrder();
|
||||
|
||||
updateConnectingStatus();
|
||||
}
|
||||
|
||||
void MainWindow::showSettings() {
|
||||
@ -400,28 +352,6 @@ void MainWindow::ui_hideSettingsAndLayer(anim::type animated) {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::mtpStateChanged(int32 dc, int32 state) {
|
||||
if (dc == MTP::maindc()) {
|
||||
updateConnectingStatus();
|
||||
Global::RefConnectionTypeChanged().notify();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateConnectingStatus() {
|
||||
const auto state = MTP::dcstate();
|
||||
const auto throughProxy = Global::UseProxy();
|
||||
if (state == MTP::ConnectingState || state == MTP::DisconnectedState || (state < 0 && state > -600)) {
|
||||
if (_main || getms() > 5000 || _connecting) {
|
||||
showConnecting(lang(throughProxy ? lng_connecting_to_proxy : lng_connecting), throughProxy ? lang(lng_connecting_settings) : QString());
|
||||
}
|
||||
} else if (state < 0) {
|
||||
showConnecting(lng_reconnecting(lt_count, ((-state) / 1000) + 1), lang(throughProxy ? lng_connecting_settings : lng_reconnecting_try_now));
|
||||
QTimer::singleShot((-state) % 1000, this, SLOT(updateConnectingStatus()));
|
||||
} else {
|
||||
hideConnecting();
|
||||
}
|
||||
}
|
||||
|
||||
MainWidget *MainWindow::mainWidget() {
|
||||
return _main;
|
||||
}
|
||||
@ -493,24 +423,6 @@ void MainWindow::ui_hideMediaPreview() {
|
||||
_mediaPreview->hidePreview();
|
||||
}
|
||||
|
||||
void MainWindow::showConnecting(const QString &text, const QString &reconnect) {
|
||||
if (_connecting) {
|
||||
_connecting->set(text, reconnect);
|
||||
_connecting->show();
|
||||
} else {
|
||||
_connecting.create(bodyWidget(), text, reconnect);
|
||||
_connecting->show();
|
||||
updateControlsGeometry();
|
||||
fixOrder();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::hideConnecting() {
|
||||
if (_connecting) {
|
||||
_connecting->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::themeUpdated(const Window::Theme::BackgroundUpdate &data) {
|
||||
using Type = Window::Theme::BackgroundUpdate::Type;
|
||||
|
||||
@ -758,7 +670,6 @@ bool MainWindow::takeThirdSectionFromLayer() {
|
||||
void MainWindow::fixOrder() {
|
||||
if (_layerBg) _layerBg->raise();
|
||||
if (_mediaPreview) _mediaPreview->raise();
|
||||
if (_connecting) _connecting->raise();
|
||||
if (_testingThemeWarning) _testingThemeWarning->raise();
|
||||
}
|
||||
|
||||
@ -850,7 +761,6 @@ void MainWindow::updateControlsGeometry() {
|
||||
if (_intro) _intro->setGeometry(body);
|
||||
if (_layerBg) _layerBg->setGeometry(body);
|
||||
if (_mediaPreview) _mediaPreview->setGeometry(body);
|
||||
if (_connecting) _connecting->moveToLeft(0, body.height() - _connecting->height());
|
||||
if (_testingThemeWarning) _testingThemeWarning->setGeometry(body);
|
||||
|
||||
if (_main) _main->checkMainSectionToLayer();
|
||||
|
@ -38,26 +38,6 @@ namespace Ui {
|
||||
class LinkButton;
|
||||
} // namespace Ui
|
||||
|
||||
class ConnectingWidget : public TWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConnectingWidget(QWidget *parent, const QString &text, const QString &reconnect);
|
||||
void set(const QString &text, const QString &reconnect);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
public slots:
|
||||
void onReconnect();
|
||||
|
||||
private:
|
||||
QString _text;
|
||||
int _textWidth = 0;
|
||||
object_ptr<Ui::LinkButton> _reconnect;
|
||||
|
||||
};
|
||||
|
||||
class MediaPreviewWidget;
|
||||
|
||||
class MainWindow : public Platform::MainWindow {
|
||||
@ -77,8 +57,6 @@ public:
|
||||
void sendServiceHistoryRequest();
|
||||
void showDelayedServiceMsgs();
|
||||
|
||||
void mtpStateChanged(int32 dc, int32 state);
|
||||
|
||||
MainWidget *chatsWidget() {
|
||||
return mainWidget();
|
||||
}
|
||||
@ -153,7 +131,6 @@ protected:
|
||||
public slots:
|
||||
void showSettings();
|
||||
void setInnerFocus();
|
||||
void updateConnectingStatus();
|
||||
|
||||
void quitFromTray();
|
||||
void showFromTray(QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Unknown);
|
||||
@ -174,9 +151,6 @@ signals:
|
||||
void checkNewAuthorization();
|
||||
|
||||
private:
|
||||
void showConnecting(const QString &text, const QString &reconnect = QString());
|
||||
void hideConnecting();
|
||||
|
||||
[[nodiscard]] bool skipTrayClick() const;
|
||||
|
||||
void ensureLayerCreated();
|
||||
@ -206,7 +180,6 @@ private:
|
||||
object_ptr<Window::LayerStackWidget> _layerBg = { nullptr };
|
||||
object_ptr<MediaPreviewWidget> _mediaPreview = { nullptr };
|
||||
|
||||
object_ptr<ConnectingWidget> _connecting = { nullptr };
|
||||
object_ptr<Window::Theme::WarningWidget> _testingThemeWarning = { nullptr };
|
||||
|
||||
Local::ClearManager *_clearManager = nullptr;
|
||||
|
@ -397,9 +397,9 @@ void Messenger::startMtp() {
|
||||
_mtproto->setUserPhone(cLoggedPhoneNumber());
|
||||
_private->mtpConfig.mainDcId = _mtproto->mainDcId();
|
||||
|
||||
_mtproto->setStateChangedHandler([](MTP::ShiftedDcId shiftedDcId, int32 state) {
|
||||
if (App::wnd()) {
|
||||
App::wnd()->mtpStateChanged(shiftedDcId, state);
|
||||
_mtproto->setStateChangedHandler([](MTP::ShiftedDcId dc, int32 state) {
|
||||
if (dc == MTP::maindc()) {
|
||||
Global::RefConnectionTypeChanged().notify();
|
||||
}
|
||||
});
|
||||
_mtproto->setSessionResetHandler([](MTP::ShiftedDcId shiftedDcId) {
|
||||
|
@ -111,7 +111,6 @@ void AdvancedWidget::connectionTypeUpdated() {
|
||||
}
|
||||
|
||||
void AdvancedWidget::onConnectionType() {
|
||||
//Ui::show(Box<ConnectionBox>());
|
||||
Ui::show(ProxiesBoxController::CreateOwningBox());
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY
|
||||
|
@ -125,6 +125,14 @@ void InfiniteRadialAnimation::draw(
|
||||
Painter &p,
|
||||
QPoint position,
|
||||
int outerWidth) {
|
||||
draw(p, position, _st.size, outerWidth);
|
||||
}
|
||||
|
||||
void InfiniteRadialAnimation::draw(
|
||||
Painter &p,
|
||||
QPoint position,
|
||||
QSize size,
|
||||
int outerWidth) {
|
||||
const auto state = computeState();
|
||||
|
||||
auto o = p.opacity();
|
||||
@ -142,8 +150,8 @@ void InfiniteRadialAnimation::draw(
|
||||
rtlrect(
|
||||
position.x(),
|
||||
position.y(),
|
||||
_st.size.width(),
|
||||
_st.size.height(),
|
||||
size.width(),
|
||||
size.height(),
|
||||
outerWidth),
|
||||
state.arcFrom,
|
||||
state.arcLength);
|
||||
|
@ -73,6 +73,11 @@ public:
|
||||
Painter &p,
|
||||
QPoint position,
|
||||
int outerWidth);
|
||||
void draw(
|
||||
Painter &p,
|
||||
QPoint position,
|
||||
QSize size,
|
||||
int outerWidth);
|
||||
|
||||
State computeState();
|
||||
|
||||
|
@ -135,7 +135,7 @@ public:
|
||||
|
||||
void setVisible(bool visible) final override {
|
||||
auto wasVisible = !this->isHidden();
|
||||
Parent::setVisible(visible);
|
||||
setVisibleHook(visible);
|
||||
visibilityChangedHook(wasVisible, !this->isHidden());
|
||||
}
|
||||
|
||||
@ -151,6 +151,9 @@ protected:
|
||||
bool eventHook(QEvent *event) override {
|
||||
return Parent::event(event);
|
||||
}
|
||||
virtual void setVisibleHook(bool visible) {
|
||||
Parent::setVisible(visible);
|
||||
}
|
||||
|
||||
private:
|
||||
void callSetVisible(bool visible) override {
|
||||
|
@ -14,35 +14,45 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
namespace Ui {
|
||||
|
||||
LinkButton::LinkButton(QWidget *parent, const QString &text, const style::LinkButton &st) : AbstractButton(parent)
|
||||
LinkButton::LinkButton(
|
||||
QWidget *parent,
|
||||
const QString &text,
|
||||
const style::LinkButton &st)
|
||||
: AbstractButton(parent)
|
||||
, _st(st)
|
||||
, _text(text)
|
||||
, _textWidth(st.font->width(_text))
|
||||
, _st(st) {
|
||||
resize(_textWidth, _st.font->height);
|
||||
, _textWidth(st.font->width(_text)) {
|
||||
resize(
|
||||
naturalWidth(),
|
||||
_st.padding.top() + _st.font->height + _st.padding.bottom());
|
||||
setCursor(style::cur_pointer);
|
||||
}
|
||||
|
||||
int LinkButton::naturalWidth() const {
|
||||
return _textWidth;
|
||||
return _st.padding.left() + _textWidth + _st.padding.right();
|
||||
}
|
||||
|
||||
void LinkButton::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
auto &font = (isOver() ? _st.overFont : _st.font);
|
||||
auto &pen = (isOver() ? _st.overColor : _st.color);
|
||||
p.setFont(font);
|
||||
p.setPen(pen);
|
||||
if (_textWidth > width()) {
|
||||
p.drawText(0, font->ascent, font->elided(_text, width()));
|
||||
const auto left = _st.padding.left();
|
||||
const auto top = _st.padding.top() + font->ascent;
|
||||
if (width() > naturalWidth()) {
|
||||
const auto available = width() - left - _st.padding.right();
|
||||
p.drawText(left, top, font->elided(_text, available));
|
||||
} else {
|
||||
p.drawText(0, font->ascent, _text);
|
||||
p.drawText(left, top, _text);
|
||||
}
|
||||
}
|
||||
|
||||
void LinkButton::setText(const QString &text) {
|
||||
_text = text;
|
||||
_textWidth = _st.font->width(_text);
|
||||
resize(_textWidth, _st.font->height);
|
||||
resize(naturalWidth(), _st.font->height);
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -31,9 +31,9 @@ protected:
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
|
||||
private:
|
||||
const style::LinkButton &_st;
|
||||
QString _text;
|
||||
int _textWidth = 0;
|
||||
const style::LinkButton &_st;
|
||||
|
||||
};
|
||||
|
||||
|
@ -29,6 +29,7 @@ LinkButton {
|
||||
overColor: color;
|
||||
font: font;
|
||||
overFont: font;
|
||||
padding: margins;
|
||||
}
|
||||
|
||||
RippleAnimation {
|
||||
|
@ -247,6 +247,27 @@ windowEmojiSuggestionsPopup: PopupMenu(defaultPopupMenu) {
|
||||
}
|
||||
}
|
||||
|
||||
connectingLeftShadow: icon {{ "connecting_left_shadow", windowShadowFg }};
|
||||
connectingLeft: icon {{ "connecting_left", windowBg }};
|
||||
connectingRightShadow: icon {{ "connecting_right_shadow", windowShadowFg }};
|
||||
connectingRight: icon {{ "connecting_right", windowBg }};
|
||||
connectingBodyShadow: icon {{ "connecting_body_shadow", windowShadowFg }};
|
||||
connectingBody: icon {{ "connecting_body", windowBg }};
|
||||
connectingMargin: margins(2px, 2px, 2px, 2px);
|
||||
connectingTextPadding: margins(18px, 11px, 18px, 0px);
|
||||
connectingRadialSkip: 6px;
|
||||
connectingRadial: InfiniteRadialAnimation(defaultInfiniteRadialAnimation) {
|
||||
color: menuIconFg;
|
||||
thickness: 2px;
|
||||
size: size(20px, 20px);
|
||||
}
|
||||
connectingRetryLink: LinkButton(defaultLinkButton) {
|
||||
padding: margins(6px, 11px, 6px, 0px);
|
||||
}
|
||||
connectingProxyOff: icon {{ "proxy_off", menuIconFg }};
|
||||
connectingProxyOn: icon {{ "proxy_on", windowBgActive }};
|
||||
connectingDuration: 150;
|
||||
|
||||
// Mac specific
|
||||
|
||||
macAccessoryWidth: 450.;
|
||||
|
523
Telegram/SourceFiles/window/window_connecting_widget.cpp
Normal file
@ -0,0 +1,523 @@
|
||||
/*
|
||||
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 "window/window_connecting_widget.h"
|
||||
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/effects/radial_animation.h"
|
||||
#include "boxes/connection_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_window.h"
|
||||
|
||||
namespace Window {
|
||||
namespace {
|
||||
|
||||
constexpr auto kIgnoreStartConnectingFor = TimeMs(3000);
|
||||
constexpr auto kConnectingStateDelay = TimeMs(1000);
|
||||
constexpr auto kRefreshTimeout = TimeMs(200);
|
||||
constexpr auto kMinimalWaitingStateDuration = TimeMs(4000);
|
||||
|
||||
class Progress : public Ui::RpWidget {
|
||||
public:
|
||||
Progress(QWidget *parent);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
void step(TimeMs ms, bool timer);
|
||||
|
||||
Ui::InfiniteRadialAnimation _animation;
|
||||
|
||||
};
|
||||
|
||||
Progress::Progress(QWidget *parent)
|
||||
: RpWidget(parent)
|
||||
, _animation(animation(this, &Progress::step), st::connectingRadial) {
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
resize(st::connectingRadial.size);
|
||||
_animation.start();
|
||||
}
|
||||
|
||||
void Progress::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
p.fillRect(e->rect(), st::windowBg);
|
||||
const auto &st = st::connectingRadial;
|
||||
const auto shift = st.thickness - (st.thickness / 2);
|
||||
_animation.draw(
|
||||
p,
|
||||
{ shift, shift },
|
||||
QSize(st.size.width() - 2 * shift, st.size.height() - 2 * shift),
|
||||
width());
|
||||
}
|
||||
|
||||
void Progress::step(TimeMs ms, bool timer) {
|
||||
if (timer) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class ConnectingWidget::ProxyIcon : public Ui::RpWidget {
|
||||
public:
|
||||
ProxyIcon(QWidget *parent);
|
||||
|
||||
void setToggled(bool toggled);
|
||||
void setOpacity(float64 opacity);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
float64 _opacity = 1.;
|
||||
QPixmap _cacheOn;
|
||||
QPixmap _cacheOff;
|
||||
bool _toggled = true;
|
||||
|
||||
};
|
||||
|
||||
ConnectingWidget::ProxyIcon::ProxyIcon(QWidget *parent) : RpWidget(parent) {
|
||||
resize(
|
||||
std::max(
|
||||
st::connectingRadial.size.width(),
|
||||
st::connectingProxyOn.width()),
|
||||
std::max(
|
||||
st::connectingRadial.size.height(),
|
||||
st::connectingProxyOn.height()));
|
||||
|
||||
const auto prepareCache = [&](const style::icon &icon) {
|
||||
auto image = QImage(
|
||||
size() * cIntRetinaFactor(),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
image.fill(st::windowBg->c);
|
||||
{
|
||||
Painter p(&image);
|
||||
icon.paint(
|
||||
p,
|
||||
(width() - icon.width()) / 2,
|
||||
(height() - icon.height()) / 2,
|
||||
width());
|
||||
}
|
||||
return App::pixmapFromImageInPlace(std::move(image));
|
||||
};
|
||||
_cacheOn = prepareCache(st::connectingProxyOn);
|
||||
_cacheOff = prepareCache(st::connectingProxyOff);
|
||||
}
|
||||
|
||||
void ConnectingWidget::ProxyIcon::setToggled(bool toggled) {
|
||||
if (_toggled != toggled) {
|
||||
_toggled = toggled;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectingWidget::ProxyIcon::setOpacity(float64 opacity) {
|
||||
_opacity = opacity;
|
||||
if (_opacity == 0.) {
|
||||
hide();
|
||||
} else if (isHidden()) {
|
||||
show();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void ConnectingWidget::ProxyIcon::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
p.setOpacity(_opacity);
|
||||
p.drawPixmap(0, 0, _toggled ? _cacheOn : _cacheOff);
|
||||
}
|
||||
|
||||
bool ConnectingWidget::State::operator==(const State &other) const {
|
||||
return (type == other.type)
|
||||
&& (useProxy == other.useProxy)
|
||||
&& (underCursor == other.underCursor)
|
||||
&& (waitTillRetry == other.waitTillRetry);
|
||||
}
|
||||
|
||||
ConnectingWidget::ConnectingWidget(QWidget *parent)
|
||||
: AbstractButton(parent)
|
||||
, _refreshTimer([=] { refreshState(); })
|
||||
, _currentLayout(computeLayout(_state)) {
|
||||
_proxyIcon = Ui::CreateChild<ProxyIcon>(this);
|
||||
_progress = Ui::CreateChild<Progress>(this);
|
||||
|
||||
addClickHandler([=] {
|
||||
Ui::show(ProxiesBoxController::CreateOwningBox());
|
||||
});
|
||||
|
||||
subscribe(Global::RefConnectionTypeChanged(), [=] {
|
||||
refreshState();
|
||||
});
|
||||
refreshState();
|
||||
}
|
||||
|
||||
rpl::producer<float64> ConnectingWidget::visibility() const {
|
||||
return _visibilityValues.events_starting_with(currentVisibility());
|
||||
}
|
||||
|
||||
void ConnectingWidget::finishAnimating() {
|
||||
if (_contentWidth.animating()) {
|
||||
_contentWidth.finish();
|
||||
updateWidth();
|
||||
}
|
||||
if (_visibility.animating()) {
|
||||
_visibility.finish();
|
||||
updateVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectingWidget::setForceHidden(bool hidden) {
|
||||
if (_forceHidden == hidden) {
|
||||
return;
|
||||
}
|
||||
if (hidden) {
|
||||
const auto real = isHidden();
|
||||
if (!real) {
|
||||
hide();
|
||||
}
|
||||
_realHidden = real;
|
||||
}
|
||||
_forceHidden = hidden;
|
||||
if (!hidden && isHidden() != _realHidden) {
|
||||
setVisible(!_realHidden);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectingWidget::setVisibleHook(bool visible) {
|
||||
if (_forceHidden) {
|
||||
_realHidden = !visible;
|
||||
return;
|
||||
}
|
||||
QWidget::setVisible(visible);
|
||||
}
|
||||
|
||||
base::unique_qptr<ConnectingWidget> ConnectingWidget::CreateDefaultWidget(
|
||||
Ui::RpWidget *parent,
|
||||
rpl::producer<bool> shown) {
|
||||
auto result = base::make_unique_q<Window::ConnectingWidget>(parent);
|
||||
const auto weak = result.get();
|
||||
rpl::combine(
|
||||
result->visibility(),
|
||||
parent->heightValue(),
|
||||
std::move(shown)
|
||||
) | rpl::start_with_next([=](float64 visible, int height, bool shown) {
|
||||
const auto hidden = (visible == 0.) || !shown;
|
||||
if (weak->isHidden() != hidden) {
|
||||
weak->setVisible(!hidden);
|
||||
}
|
||||
const auto size = weak->size();
|
||||
weak->moveToLeft(0, anim::interpolate(
|
||||
height - st::connectingMargin.top(),
|
||||
height - weak->height(),
|
||||
visible));
|
||||
}, weak->lifetime());
|
||||
result->finishAnimating();
|
||||
return result;
|
||||
}
|
||||
|
||||
void ConnectingWidget::onStateChanged(
|
||||
AbstractButton::State was,
|
||||
StateChangeSource source) {
|
||||
crl::on_main(this, [=] { refreshState(); });
|
||||
}
|
||||
|
||||
void ConnectingWidget::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::windowBg);
|
||||
const auto inner = innerRect();
|
||||
const auto content = contentRect();
|
||||
const auto text = textRect();
|
||||
const auto left = inner.topLeft();
|
||||
const auto right = content.topLeft() + QPoint(content.width(), 0);
|
||||
st::connectingLeftShadow.paint(p, left, width());
|
||||
st::connectingLeft.paint(p, left, width());
|
||||
st::connectingRightShadow.paint(p, right, width());
|
||||
st::connectingRight.paint(p, right, width());
|
||||
st::connectingBodyShadow.fill(p, content);
|
||||
st::connectingBody.fill(p, content);
|
||||
|
||||
const auto available = text.width();
|
||||
if (available > 0 && !_currentLayout.text.isEmpty()) {
|
||||
p.setFont(st::normalFont);
|
||||
p.setPen(st::windowSubTextFg);
|
||||
if (available >= _currentLayout.textWidth) {
|
||||
p.drawTextLeft(
|
||||
text.x(),
|
||||
text.y(),
|
||||
width(),
|
||||
_currentLayout.text,
|
||||
_currentLayout.textWidth);
|
||||
} else {
|
||||
p.drawTextLeft(
|
||||
text.x(),
|
||||
text.y(),
|
||||
width(),
|
||||
st::normalFont->elided(_currentLayout.text, available));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QRect ConnectingWidget::innerRect() const {
|
||||
return rect().marginsRemoved(
|
||||
st::connectingMargin
|
||||
);
|
||||
}
|
||||
|
||||
QRect ConnectingWidget::contentRect() const {
|
||||
return innerRect().marginsRemoved(style::margins(
|
||||
st::connectingLeft.width(),
|
||||
0,
|
||||
st::connectingRight.width(),
|
||||
0));
|
||||
}
|
||||
|
||||
QRect ConnectingWidget::textRect() const {
|
||||
return contentRect().marginsRemoved(
|
||||
st::connectingTextPadding
|
||||
);
|
||||
}
|
||||
|
||||
void ConnectingWidget::resizeEvent(QResizeEvent *e) {
|
||||
{
|
||||
const auto xShift = (height() - _progress->width()) / 2;
|
||||
const auto yShift = (height() - _progress->height()) / 2;
|
||||
_progress->moveToLeft(xShift, yShift);
|
||||
}
|
||||
{
|
||||
const auto xShift = (height() - _proxyIcon->width()) / 2;
|
||||
const auto yShift = (height() - _proxyIcon->height()) / 2;
|
||||
_proxyIcon->moveToRight(xShift, yShift);
|
||||
}
|
||||
updateRetryGeometry();
|
||||
}
|
||||
|
||||
void ConnectingWidget::updateRetryGeometry() {
|
||||
if (!_retry) {
|
||||
return;
|
||||
}
|
||||
const auto text = textRect();
|
||||
const auto available = text.width() - _currentLayout.textWidth;
|
||||
if (available <= 0) {
|
||||
_retry->hide();
|
||||
} else {
|
||||
_retry->show();
|
||||
_retry->resize(
|
||||
std::min(available, _retry->naturalWidth()),
|
||||
innerRect().height());
|
||||
_retry->moveToLeft(
|
||||
text.x() + text.width() - _retry->width(),
|
||||
st::connectingMargin.top());
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectingWidget::refreshState() {
|
||||
const auto state = [&]() -> State {
|
||||
const auto under = isOver();
|
||||
const auto mtp = MTP::dcstate();
|
||||
const auto throughProxy = Global::UseProxy();
|
||||
if (mtp == MTP::ConnectingState
|
||||
|| mtp == MTP::DisconnectedState
|
||||
|| (mtp < 0 && mtp > -600)) {
|
||||
return { State::Type::Connecting, throughProxy, under };
|
||||
} else if (mtp < 0
|
||||
&& mtp >= -kMinimalWaitingStateDuration
|
||||
&& _state.type != State::Type::Waiting) {
|
||||
return { State::Type::Connecting, throughProxy, under };
|
||||
} else if (mtp < 0) {
|
||||
const auto seconds = ((-mtp) / 1000) + 1;
|
||||
return { State::Type::Waiting, throughProxy, under, seconds };
|
||||
}
|
||||
return { State::Type::Connected, throughProxy, under };
|
||||
}();
|
||||
if (state.waitTillRetry > 0) {
|
||||
_refreshTimer.callOnce(kRefreshTimeout);
|
||||
}
|
||||
if (state == _state) {
|
||||
return;
|
||||
} else if (state.type == State::Type::Connecting
|
||||
&& _state.type == State::Type::Connected) {
|
||||
const auto now = getms();
|
||||
if (!_connectingStartedAt) {
|
||||
_connectingStartedAt = now;
|
||||
_refreshTimer.callOnce(kConnectingStateDelay);
|
||||
return;
|
||||
}
|
||||
const auto applyConnectingAt = std::max(
|
||||
_connectingStartedAt + kConnectingStateDelay,
|
||||
kIgnoreStartConnectingFor);
|
||||
if (now < applyConnectingAt) {
|
||||
_refreshTimer.callOnce(applyConnectingAt - now);
|
||||
return;
|
||||
}
|
||||
}
|
||||
applyState(state);
|
||||
}
|
||||
|
||||
void ConnectingWidget::applyState(const State &state) {
|
||||
const auto newLayout = computeLayout(state);
|
||||
const auto guard = gsl::finally([&] {
|
||||
updateWidth();
|
||||
update();
|
||||
});
|
||||
|
||||
_state = state;
|
||||
if (_currentLayout.visible != newLayout.visible) {
|
||||
changeVisibilityWithLayout(newLayout);
|
||||
return;
|
||||
}
|
||||
if (_currentLayout.contentWidth != newLayout.contentWidth) {
|
||||
if (!_currentLayout.contentWidth
|
||||
|| !newLayout.contentWidth
|
||||
|| _contentWidth.animating()) {
|
||||
_contentWidth.start(
|
||||
[=] { updateWidth(); },
|
||||
_currentLayout.contentWidth,
|
||||
newLayout.contentWidth,
|
||||
st::connectingDuration);
|
||||
}
|
||||
}
|
||||
const auto saved = _currentLayout;
|
||||
setLayout(newLayout);
|
||||
if (_currentLayout.text.isEmpty()
|
||||
&& !saved.text.isEmpty()
|
||||
&& _contentWidth.animating()) {
|
||||
_currentLayout.text = saved.text;
|
||||
_currentLayout.textWidth = saved.textWidth;
|
||||
}
|
||||
refreshRetryLink(_currentLayout.hasRetry);
|
||||
}
|
||||
|
||||
void ConnectingWidget::changeVisibilityWithLayout(const Layout &layout) {
|
||||
Expects(_currentLayout.visible != layout.visible);
|
||||
|
||||
const auto changeLayout = !_currentLayout.visible;
|
||||
_visibility.start(
|
||||
[=] { updateVisibility(); },
|
||||
layout.visible ? 0. : 1.,
|
||||
layout.visible ? 1. : 0.,
|
||||
st::connectingDuration);
|
||||
if (_contentWidth.animating()) {
|
||||
_contentWidth.start(
|
||||
[=] { updateWidth(); },
|
||||
_currentLayout.contentWidth,
|
||||
(changeLayout ? layout : _currentLayout).contentWidth,
|
||||
st::connectingDuration);
|
||||
}
|
||||
if (changeLayout) {
|
||||
setLayout(layout);
|
||||
} else {
|
||||
_currentLayout.visible = layout.visible;
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectingWidget::setLayout(const Layout &layout) {
|
||||
_currentLayout = layout;
|
||||
_proxyIcon->setToggled(_currentLayout.proxyEnabled);
|
||||
_progress->setVisible(_contentWidth.animating()
|
||||
|| _currentLayout.progressShown);
|
||||
}
|
||||
|
||||
void ConnectingWidget::refreshRetryLink(bool hasRetry) {
|
||||
if (hasRetry && !_retry) {
|
||||
_retry = base::make_unique_q<Ui::LinkButton>(
|
||||
this,
|
||||
lang(lng_reconnecting_try_now),
|
||||
st::connectingRetryLink);
|
||||
_retry->addClickHandler([=] {
|
||||
MTP::restart();
|
||||
});
|
||||
updateRetryGeometry();
|
||||
} else if (!hasRetry) {
|
||||
_retry = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectingWidget::updateVisibility() {
|
||||
const auto value = currentVisibility();
|
||||
if (value == 0. && _contentWidth.animating()) {
|
||||
_contentWidth.finish();
|
||||
updateWidth();
|
||||
}
|
||||
_visibilityValues.fire_copy(value);
|
||||
}
|
||||
|
||||
float64 ConnectingWidget::currentVisibility() const {
|
||||
return _visibility.current(_currentLayout.visible ? 1. : 0.);
|
||||
}
|
||||
|
||||
auto ConnectingWidget::computeLayout(const State &state) const -> Layout {
|
||||
auto result = Layout();
|
||||
result.proxyEnabled = state.useProxy;
|
||||
result.progressShown = (state.type != State::Type::Connected);
|
||||
result.visible = state.useProxy
|
||||
|| state.type == State::Type::Connecting
|
||||
|| state.type == State::Type::Waiting;
|
||||
switch (state.type) {
|
||||
case State::Type::Connecting:
|
||||
result.text = state.underCursor ? lang(lng_connecting) : QString();
|
||||
break;
|
||||
|
||||
case State::Type::Waiting:
|
||||
Assert(state.waitTillRetry > 0);
|
||||
result.text = lng_reconnecting(lt_count, state.waitTillRetry);
|
||||
break;
|
||||
}
|
||||
result.textWidth = st::normalFont->width(result.text);
|
||||
const auto maxTextWidth = (state.type == State::Type::Waiting)
|
||||
? st::normalFont->width(lng_reconnecting(lt_count, 88))
|
||||
: result.textWidth;
|
||||
result.contentWidth = (result.textWidth > 0)
|
||||
? (st::connectingTextPadding.left()
|
||||
+ result.textWidth
|
||||
+ st::connectingTextPadding.right())
|
||||
: 0;
|
||||
if (state.type == State::Type::Waiting) {
|
||||
result.contentWidth += st::connectingRetryLink.padding.left()
|
||||
+ st::connectingRetryLink.font->width(
|
||||
lang(lng_reconnecting_try_now))
|
||||
+ st::connectingRetryLink.padding.right();
|
||||
}
|
||||
result.hasRetry = (state.type == State::Type::Waiting);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ConnectingWidget::updateWidth() {
|
||||
const auto current = _contentWidth.current(_currentLayout.contentWidth);
|
||||
const auto height = st::connectingLeft.height();
|
||||
const auto desired = QRect(0, 0, current, height).marginsAdded(
|
||||
style::margins(
|
||||
st::connectingLeft.width(),
|
||||
0,
|
||||
st::connectingRight.width(),
|
||||
0)
|
||||
).marginsAdded(
|
||||
st::connectingMargin
|
||||
);
|
||||
resize(desired.size());
|
||||
if (!_contentWidth.animating()) {
|
||||
_progress->setVisible(_currentLayout.progressShown);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
rpl::producer<bool> AdaptiveIsOneColumn() {
|
||||
return rpl::single(
|
||||
Adaptive::OneColumn()
|
||||
) | rpl::then(base::ObservableViewer(
|
||||
Adaptive::Changed()
|
||||
) | rpl::map([] {
|
||||
return Adaptive::OneColumn();
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace Window
|
100
Telegram/SourceFiles/window/window_connecting_widget.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
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 "ui/abstract_button.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
namespace Ui {
|
||||
class LinkButton;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
|
||||
class ConnectingWidget
|
||||
: public Ui::AbstractButton
|
||||
, private base::Subscriber {
|
||||
public:
|
||||
ConnectingWidget(QWidget *parent);
|
||||
|
||||
rpl::producer<float64> visibility() const;
|
||||
|
||||
void finishAnimating();
|
||||
void setForceHidden(bool hidden);
|
||||
void setVisibleHook(bool visible) override;
|
||||
|
||||
static base::unique_qptr<ConnectingWidget> CreateDefaultWidget(
|
||||
Ui::RpWidget *parent,
|
||||
rpl::producer<bool> shown);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
|
||||
private:
|
||||
class ProxyIcon;
|
||||
struct State {
|
||||
enum class Type {
|
||||
Connected,
|
||||
Connecting,
|
||||
Waiting,
|
||||
};
|
||||
Type type = Type::Connected;
|
||||
bool useProxy = false;
|
||||
bool underCursor = false;
|
||||
int waitTillRetry = 0;
|
||||
|
||||
bool operator==(const State &other) const;
|
||||
|
||||
};
|
||||
struct Layout {
|
||||
bool visible = false;
|
||||
bool hasRetry = false;
|
||||
bool proxyEnabled = false;
|
||||
bool progressShown = false;
|
||||
int contentWidth = 0;
|
||||
QString text;
|
||||
int textWidth = 0;
|
||||
|
||||
};
|
||||
void updateRetryGeometry();
|
||||
void updateWidth();
|
||||
void updateVisibility();
|
||||
void refreshState();
|
||||
void applyState(const State &state);
|
||||
void changeVisibilityWithLayout(const Layout &layout);
|
||||
void refreshRetryLink(bool hasRetry);
|
||||
Layout computeLayout(const State &state) const;
|
||||
void setLayout(const Layout &layout);
|
||||
float64 currentVisibility() const;
|
||||
|
||||
QRect innerRect() const;
|
||||
QRect contentRect() const;
|
||||
QRect textRect() const;
|
||||
|
||||
base::Timer _refreshTimer;
|
||||
State _state;
|
||||
Layout _currentLayout;
|
||||
TimeMs _connectingStartedAt = 0;
|
||||
Animation _contentWidth;
|
||||
Animation _visibility;
|
||||
base::unique_qptr<Ui::LinkButton> _retry;
|
||||
QPointer<Ui::RpWidget> _progress;
|
||||
QPointer<ProxyIcon> _proxyIcon;
|
||||
bool _forceHidden = false;
|
||||
bool _realHidden = false;
|
||||
|
||||
rpl::event_stream<float64> _visibilityValues;
|
||||
|
||||
};
|
||||
|
||||
rpl::producer<bool> AdaptiveIsOneColumn();
|
||||
|
||||
} // namespace Window
|
@ -701,6 +701,8 @@
|
||||
<(src_loc)/window/section_memento.h
|
||||
<(src_loc)/window/section_widget.cpp
|
||||
<(src_loc)/window/section_widget.h
|
||||
<(src_loc)/window/window_connecting_widget.cpp
|
||||
<(src_loc)/window/window_connecting_widget.h
|
||||
<(src_loc)/window/window_controller.cpp
|
||||
<(src_loc)/window/window_controller.h
|
||||
<(src_loc)/window/window_main_menu.cpp
|
||||
|